Skip to content

Commit

Permalink
[PAL/Linux-SGX] Add sgx.insecure__allow_memfaults_without_exinfo op…
Browse files Browse the repository at this point in the history
…tion

Commits "[PAL/Linux-SGX] Disallow memfault handling with no faulting
address reported" and "[PAL/Linux-SGX] Cross-verify SW signals vs HW
exceptions" hardened Gramine's exception handling in the SGX PAL. In
particular, memory faults (#PF and #GP) became allowed only when the
SGX EXINFO feature is available on the CPU and is enabled in the
manifest (via `sgx.use_exinfo`). Otherwise Gramine immediately
terminated the SGX enclave.

However, some applications (Java runtimes in particular) rely on
exception handling of memory faults, even if the related MADDR (faulting
address) and ERRCD (error code) have dummy zero values. The two
mentioned commits effectively forbade such applications from running on
older CPUs that don't have EXINFO. This is unfortunate because
frequently, the development/testing machines have old SGX CPUs.

To work around the problem of old CPUs, this commit introduces the
`sgx.insecure__allow_memfaults_without_exinfo` manifest option, that
restores the previous (insecure) Gramine behavior. This is only a
temporary solution; it will be removed in the near future.

Signed-off-by: Dmitrii Kuvaiskii <dmitrii.kuvaiskii@intel.com>
  • Loading branch information
Dmitrii Kuvaiskii committed Feb 12, 2024
1 parent 748514a commit c06a4ae
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 8 deletions.
26 changes: 22 additions & 4 deletions Documentation/manifest-syntax.rst
Original file line number Diff line number Diff line change
Expand Up @@ -797,11 +797,29 @@ SGX EXINFO
sgx.use_exinfo = [true|false]
(Default: false)

sgx.insecure__allow_memfaults_without_exinfo = [true|false]
(Default: false)

If ``sgx.use_exinfo`` is set, user application can retrieve faulting address in
signal handler in case of a page fault. Otherwise (set to ``false``), the
faulting address will always be provided as ``0``. The default is ``false``
because some frameworks/runtimes could otherwise print the callstack and
variables/registers on exceptions, potentially leaking data.
signal handler in case of page/general protection faults (#PF and #GP).
Otherwise (set to ``false``), the behavior depends on
``sgx.insecure__allow_memfaults_without_exinfo``:

- If ``sgx.insecure__allow_memfaults_without_exinfo`` is unset (default), then
Gramine terminates with an error, to prevent a possible attack.
- Otherwise the exception is allowed and Gramine forwards it to the application,
and the faulting address is provided as ``0``.

The default value for ``sgx.use_exinfo`` is ``false`` because some
frameworks/runtimes could otherwise print the callstack and variables/registers
on exceptions, potentially leaking data.

.. note::
The option ``sgx.insecure__allow_memfaults_without_exinfo`` is provided only
to allow debugging/testing on old CPUs that do not support the EXINFO
feature. Without EXINFO support, a malicious host may attack the application
by injecting a memory fault. This option is thus insecure and must not be
used in production environments! It will be removed in near future.

Optional CPU features (AVX, AVX512, AMX, MPX, PKRU)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
21 changes: 18 additions & 3 deletions pal/src/host/linux-sgx/pal_exception.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,8 +286,23 @@ void _PalExceptionHandler(uint32_t trusted_exit_info_,
/* corresponds to last column in the table above */
if (untrusted_external_event != PAL_EVENT_QUIT
&& untrusted_external_event != PAL_EVENT_INTERRUPTED) {
log_error("Host injected malicious signal %u", untrusted_external_event);
_PalProcessExit(1);
if (untrusted_external_event == PAL_EVENT_MEMFAULT
&& g_pal_linuxsgx_state.memfaults_without_exinfo_allowed) {
/*
* NOTE: Old CPUs may have SGX without the EXINFO feature, thus they do not
* report/reflect #PF and #GP exceptions in the trusted EXITINFO struct. In some
* situations (debugging using older CPUs) we don't want to terminate immediately.
* Instead we propagate this reported-by-host and possibly malicious exception to
* the app, with MADDR (faulting addr) and ERRCD (error code) set to zeros.
*
* This is enabled via an (insecure) manifest option and will be removed in the near
* future.
*/
memset(&trusted_exit_info, 0, sizeof(trusted_exit_info));
} else {
log_error("Host injected malicious signal %u", untrusted_external_event);
_PalProcessExit(1);
}
}
event_num = untrusted_external_event;
} else {
Expand Down Expand Up @@ -416,7 +431,7 @@ void _PalExceptionHandler(uint32_t trusted_exit_info_,
addr = uc->rip;
break;
case PAL_EVENT_MEMFAULT:
if (!has_hw_fault_address) {
if (!has_hw_fault_address && !g_pal_linuxsgx_state.memfaults_without_exinfo_allowed) {
log_error("Tried to handle a memory fault with no faulting address reported by "
"SGX. Please consider enabling 'sgx.use_exinfo' in the manifest.");
_PalProcessExit(1);
Expand Down
1 change: 1 addition & 0 deletions pal/src/host/linux-sgx/pal_linux.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ extern struct pal_linuxsgx_state {
/* enclave information */
bool enclave_initialized; /* thread creation ECALL is allowed only after this is set */
bool edmm_enabled;
bool memfaults_without_exinfo_allowed;
sgx_target_info_t qe_targetinfo; /* received from untrusted host, use carefully */
sgx_report_body_t enclave_info; /* cached self-report result, trusted */

Expand Down
18 changes: 17 additions & 1 deletion pal/src/host/linux-sgx/pal_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,7 @@ static int print_warnings_on_insecure_configs(PAL_HANDLE parent_process) {
bool allow_all_files = false;
bool use_allowed_files = g_allowed_files_warn;
bool encrypted_files_keys = false;
bool memfaults_without_exinfo_allowed = g_pal_linuxsgx_state.memfaults_without_exinfo_allowed;

char* log_level_str = NULL;

Expand Down Expand Up @@ -485,7 +486,7 @@ static int print_warnings_on_insecure_configs(PAL_HANDLE parent_process) {

if (!verbose_log_level && !sgx_debug && !use_cmdline_argv && !use_host_env && !disable_aslr &&
!allow_eventfd && !experimental_flock && !allow_all_files && !use_allowed_files &&
!encrypted_files_keys) {
!encrypted_files_keys && !memfaults_without_exinfo_allowed) {
/* there are no insecure configurations, skip printing */
ret = 0;
goto out;
Expand Down Expand Up @@ -523,6 +524,10 @@ static int print_warnings_on_insecure_configs(PAL_HANDLE parent_process) {
log_always(" - sys.experimental__enable_flock = true "
"(flock syscall is enabled; still under development and may contain bugs)");

if (memfaults_without_exinfo_allowed)
log_always(" - sgx.insecure__allow_memfaults_without_exinfo "
"(allow memory faults even when SGX EXINFO is not supported by CPU)");

if (allow_all_files)
log_always(" - sgx.file_check_policy = allow_all_but_log "
"(all files are passed through from untrusted host without verification)");
Expand All @@ -535,6 +540,7 @@ static int print_warnings_on_insecure_configs(PAL_HANDLE parent_process) {
log_always(" - fs.insecure__keys.* = \"...\" "
"(keys hardcoded in manifest)");


log_always("\nGramine will continue application execution, but this configuration must not be "
"used in production!");
log_always("-------------------------------------------------------------------------------"
Expand Down Expand Up @@ -774,6 +780,16 @@ noreturn void pal_linux_main(void* uptr_libpal_uri, size_t libpal_uri_len, void*
ocall_exit(1, /*is_exitgroup=*/true);
}

/* TODO: temporarily allow old CPUs (that don't have EXINFO for #PF and #GP memory faults)
* to deliver memory faults instead of terminating; remove this in future */
ret = toml_bool_in(g_pal_public_state.manifest_root,
"sgx.insecure__allow_memfaults_without_exinfo", /*defaultval=*/false,
&g_pal_linuxsgx_state.memfaults_without_exinfo_allowed);
if (ret < 0) {
log_error("Cannot parse 'sgx.insecure__allow_memfaults_without_exinfo'");
ocall_exit(1, /*is_exitgroup=*/true);
}

int64_t thread_num_int64;
ret = toml_int_in(g_pal_public_state.manifest_root, "sgx.max_threads",
/*defaultval=*/-1, &thread_num_int64);
Expand Down

0 comments on commit c06a4ae

Please sign in to comment.