diff --git a/libos/test/abi/x86_64/manifest.template b/libos/test/abi/x86_64/manifest.template index c130d46db0..9c1608dd2e 100644 --- a/libos/test/abi/x86_64/manifest.template +++ b/libos/test/abi/x86_64/manifest.template @@ -7,6 +7,7 @@ fs.mounts = [ sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} sgx.max_threads = {{ '1' if env.get('EDMM', '0') == '1' else '4' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ binary_dir }}/{{ entrypoint }}", diff --git a/libos/test/abi/x86_64/stack_arg.manifest.template b/libos/test/abi/x86_64/stack_arg.manifest.template index bc8658be3c..0b22a45104 100644 --- a/libos/test/abi/x86_64/stack_arg.manifest.template +++ b/libos/test/abi/x86_64/stack_arg.manifest.template @@ -12,6 +12,7 @@ fs.mounts = [ sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} sgx.max_threads = {{ '1' if env.get('EDMM', '0') == '1' else '4' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ binary_dir }}/{{ entrypoint }}", diff --git a/libos/test/abi/x86_64/stack_env.manifest.template b/libos/test/abi/x86_64/stack_env.manifest.template index ef892f68f8..c0d075a36c 100644 --- a/libos/test/abi/x86_64/stack_env.manifest.template +++ b/libos/test/abi/x86_64/stack_env.manifest.template @@ -12,6 +12,7 @@ fs.mounts = [ sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} sgx.max_threads = {{ '1' if env.get('EDMM', '0') == '1' else '4' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ binary_dir }}/{{ entrypoint }}", diff --git a/libos/test/fs/manifest.template b/libos/test/fs/manifest.template index 612873c068..f8d74543e6 100644 --- a/libos/test/fs/manifest.template +++ b/libos/test/fs/manifest.template @@ -22,6 +22,7 @@ fs.insecure__keys.default = "ffeeddccbbaa99887766554433221100" sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} sgx.max_threads = {{ '1' if env.get('EDMM', '0') == '1' else '16' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.allowed_files = [ "file:tmp/", diff --git a/libos/test/ltp/manifest.template b/libos/test/ltp/manifest.template index 40d17ea3b4..f1909baa89 100644 --- a/libos/test/ltp/manifest.template +++ b/libos/test/ltp/manifest.template @@ -26,6 +26,7 @@ sys.brk.max_size = "32M" sys.stack.size = "4M" sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} # for tests that require SIGSEGV handling (e.g., setrlimit01, mmap03) sgx.use_exinfo = true diff --git a/libos/test/regression/argv_from_file.manifest.template b/libos/test/regression/argv_from_file.manifest.template index bc086bd4ec..072ff027d3 100644 --- a/libos/test/regression/argv_from_file.manifest.template +++ b/libos/test/regression/argv_from_file.manifest.template @@ -12,6 +12,7 @@ fs.mounts = [ sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.allowed_files = [ "file:argv_test_input", diff --git a/libos/test/regression/argv_from_manifest.manifest.template b/libos/test/regression/argv_from_manifest.manifest.template index 147ba14946..bd32c44292 100644 --- a/libos/test/regression/argv_from_manifest.manifest.template +++ b/libos/test/regression/argv_from_manifest.manifest.template @@ -19,6 +19,7 @@ fs.mounts = [ sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ gramine.runtimedir(libc) }}/", diff --git a/libos/test/regression/attestation.manifest.template b/libos/test/regression/attestation.manifest.template index 54c86c1ef3..38ecd43454 100644 --- a/libos/test/regression/attestation.manifest.template +++ b/libos/test/regression/attestation.manifest.template @@ -12,6 +12,7 @@ fs.insecure__keys.default = "ffeeddccbbaa99887766554433221100" sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.remote_attestation = "{{ env.get('RA_TYPE', 'none') }}" sgx.ra_client_spid = "{{ env.get('RA_CLIENT_SPID', '') }}" diff --git a/libos/test/regression/bootstrap_cpp.manifest.template b/libos/test/regression/bootstrap_cpp.manifest.template index ba5b53f9fa..9893a42808 100644 --- a/libos/test/regression/bootstrap_cpp.manifest.template +++ b/libos/test/regression/bootstrap_cpp.manifest.template @@ -15,6 +15,7 @@ fs.mounts = [ sgx.max_threads = {{ '1' if env.get('EDMM', '0') == '1' else '8' }} sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ gramine.runtimedir(libc) }}/", diff --git a/libos/test/regression/debug_log_file.manifest.template b/libos/test/regression/debug_log_file.manifest.template index af4976c2ed..a99e343edd 100644 --- a/libos/test/regression/debug_log_file.manifest.template +++ b/libos/test/regression/debug_log_file.manifest.template @@ -14,6 +14,7 @@ fs.mounts = [ sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ gramine.runtimedir(libc) }}/", diff --git a/libos/test/regression/debug_log_inline.manifest.template b/libos/test/regression/debug_log_inline.manifest.template index 44ed734dc9..bf05bb07e5 100644 --- a/libos/test/regression/debug_log_inline.manifest.template +++ b/libos/test/regression/debug_log_inline.manifest.template @@ -13,6 +13,7 @@ fs.mounts = [ sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ gramine.runtimedir(libc) }}/", diff --git a/libos/test/regression/device_passthrough.manifest.template b/libos/test/regression/device_passthrough.manifest.template index 2c056bccac..181141110e 100644 --- a/libos/test/regression/device_passthrough.manifest.template +++ b/libos/test/regression/device_passthrough.manifest.template @@ -10,6 +10,7 @@ fs.mounts = [ sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ gramine.runtimedir(libc) }}/", diff --git a/libos/test/regression/env_from_file.manifest.template b/libos/test/regression/env_from_file.manifest.template index dbb9eb3da7..aeca295e9e 100644 --- a/libos/test/regression/env_from_file.manifest.template +++ b/libos/test/regression/env_from_file.manifest.template @@ -12,6 +12,7 @@ fs.mounts = [ sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.allowed_files = [ "file:env_test_input", diff --git a/libos/test/regression/env_from_host.manifest.template b/libos/test/regression/env_from_host.manifest.template index ba450019af..0fa6625735 100644 --- a/libos/test/regression/env_from_host.manifest.template +++ b/libos/test/regression/env_from_host.manifest.template @@ -12,6 +12,7 @@ fs.mounts = [ sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ gramine.runtimedir(libc) }}/", diff --git a/libos/test/regression/env_passthrough.manifest.template b/libos/test/regression/env_passthrough.manifest.template index 95d054f186..64a7eb60d2 100644 --- a/libos/test/regression/env_passthrough.manifest.template +++ b/libos/test/regression/env_passthrough.manifest.template @@ -17,6 +17,7 @@ fs.mounts = [ sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ gramine.runtimedir(libc) }}/", diff --git a/libos/test/regression/eventfd_fork.manifest.template b/libos/test/regression/eventfd_fork.manifest.template index 6c9887e436..86b8def2aa 100644 --- a/libos/test/regression/eventfd_fork.manifest.template +++ b/libos/test/regression/eventfd_fork.manifest.template @@ -11,6 +11,7 @@ sys.insecure__allow_eventfd = true sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ gramine.runtimedir(libc) }}/", diff --git a/libos/test/regression/eventfd_fork_allowed_failing.manifest.template b/libos/test/regression/eventfd_fork_allowed_failing.manifest.template index ba50648401..858af8c29a 100644 --- a/libos/test/regression/eventfd_fork_allowed_failing.manifest.template +++ b/libos/test/regression/eventfd_fork_allowed_failing.manifest.template @@ -17,6 +17,7 @@ fs.mounts = [ sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ gramine.runtimedir(libc) }}/", diff --git a/libos/test/regression/fcntl_lock_child_only.manifest.template b/libos/test/regression/fcntl_lock_child_only.manifest.template index 202bfe59ed..090622ce2a 100644 --- a/libos/test/regression/fcntl_lock_child_only.manifest.template +++ b/libos/test/regression/fcntl_lock_child_only.manifest.template @@ -13,6 +13,7 @@ fs.insecure__keys.default = "ffeeddccbbaa99887766554433221100" sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ gramine.runtimedir(libc) }}/", diff --git a/libos/test/regression/file_check_policy_allow_all_but_log.manifest.template b/libos/test/regression/file_check_policy_allow_all_but_log.manifest.template index c2639b80e7..f67eb3160e 100644 --- a/libos/test/regression/file_check_policy_allow_all_but_log.manifest.template +++ b/libos/test/regression/file_check_policy_allow_all_but_log.manifest.template @@ -14,6 +14,7 @@ fs.mounts = [ sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.file_check_policy = "allow_all_but_log" diff --git a/libos/test/regression/file_check_policy_strict.manifest.template b/libos/test/regression/file_check_policy_strict.manifest.template index 927c148671..34e96d2ccf 100644 --- a/libos/test/regression/file_check_policy_strict.manifest.template +++ b/libos/test/regression/file_check_policy_strict.manifest.template @@ -14,6 +14,7 @@ fs.mounts = [ sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.file_check_policy = "strict" diff --git a/libos/test/regression/fork_and_access_file.manifest.template b/libos/test/regression/fork_and_access_file.manifest.template index 8f63bf4106..30cdaadfbf 100644 --- a/libos/test/regression/fork_and_access_file.manifest.template +++ b/libos/test/regression/fork_and_access_file.manifest.template @@ -10,6 +10,7 @@ fs.mounts = [ sgx.max_threads = {{ '1' if env.get('EDMM', '0') == '1' else '16' }} sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} # this is only to test that `sgx.enable_stats` works (it can only be specified for debug-mode tests) sgx.enable_stats = true diff --git a/libos/test/regression/fork_disallowed.manifest.template b/libos/test/regression/fork_disallowed.manifest.template index 6cdb30edb3..03b0047546 100644 --- a/libos/test/regression/fork_disallowed.manifest.template +++ b/libos/test/regression/fork_disallowed.manifest.template @@ -15,6 +15,7 @@ sys.disallow_subprocesses = true sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ gramine.runtimedir(libc) }}/", diff --git a/libos/test/regression/host_root_fs.manifest.template b/libos/test/regression/host_root_fs.manifest.template index 12f4f9442f..8277c98141 100644 --- a/libos/test/regression/host_root_fs.manifest.template +++ b/libos/test/regression/host_root_fs.manifest.template @@ -12,6 +12,7 @@ fs.mounts = [ sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ gramine.runtimedir(libc) }}/", diff --git a/libos/test/regression/hostname_extra_runtime_conf.manifest.template b/libos/test/regression/hostname_extra_runtime_conf.manifest.template index 2cdb1c9aa4..664fbec5ae 100644 --- a/libos/test/regression/hostname_extra_runtime_conf.manifest.template +++ b/libos/test/regression/hostname_extra_runtime_conf.manifest.template @@ -12,6 +12,7 @@ sys.enable_extra_runtime_domain_names_conf = true sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ gramine.runtimedir(libc) }}/", diff --git a/libos/test/regression/init_fail.manifest.template b/libos/test/regression/init_fail.manifest.template index 755f8b1c0a..a2c3462ac2 100644 --- a/libos/test/regression/init_fail.manifest.template +++ b/libos/test/regression/init_fail.manifest.template @@ -11,6 +11,7 @@ fs.mounts = [ sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ gramine.runtimedir(libc) }}/", diff --git a/libos/test/regression/init_fail2.manifest.template b/libos/test/regression/init_fail2.manifest.template index 2222af6dbd..eedec259a2 100644 --- a/libos/test/regression/init_fail2.manifest.template +++ b/libos/test/regression/init_fail2.manifest.template @@ -11,6 +11,7 @@ fs.mounts = [ sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} # this is an impossible combination of options, LibOS must fail very early in init process sgx.enclave_size = "256M" diff --git a/libos/test/regression/large_mmap.manifest.template b/libos/test/regression/large_mmap.manifest.template index 324b5a0097..dda3cfd712 100644 --- a/libos/test/regression/large_mmap.manifest.template +++ b/libos/test/regression/large_mmap.manifest.template @@ -14,6 +14,7 @@ fs.mounts = [ sgx.enclave_size = "8G" sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.allowed_files = [ "file:testfile", diff --git a/libos/test/regression/madvise.manifest.template b/libos/test/regression/madvise.manifest.template index 185365c189..b2cac3b6a1 100644 --- a/libos/test/regression/madvise.manifest.template +++ b/libos/test/regression/madvise.manifest.template @@ -10,6 +10,7 @@ fs.mounts = [ sgx.max_threads = {{ '1' if env.get('EDMM', '0') == '1' else '4' }} sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} # `use_exinfo = true` is needed because `madvise(MADV_DONTNEED)` is used in this test. When EDMM is # enabled, it will free the committed pages but automatically recommit them on subsequent accesses diff --git a/libos/test/regression/manifest.template b/libos/test/regression/manifest.template index ab236b1cf2..51e8cf8528 100644 --- a/libos/test/regression/manifest.template +++ b/libos/test/regression/manifest.template @@ -24,6 +24,7 @@ sgx.max_threads = {{ '1' if env.get('EDMM', '0') == '1' else '16' }} sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} sgx.use_exinfo = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.allowed_files = [ "file:tmp/", diff --git a/libos/test/regression/mmap_map_noreserve.manifest.template b/libos/test/regression/mmap_map_noreserve.manifest.template index 372e485ed9..ee3cf8075e 100644 --- a/libos/test/regression/mmap_map_noreserve.manifest.template +++ b/libos/test/regression/mmap_map_noreserve.manifest.template @@ -16,6 +16,7 @@ sgx.max_threads = {{ '1' if env.get('EDMM', '0') == '1' else '20' }} sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} sgx.use_exinfo = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.allowed_files = [ "file:testfile_map_noreserve", diff --git a/libos/test/regression/mock_syscalls.manifest.template b/libos/test/regression/mock_syscalls.manifest.template index a6b042f19d..c85d1b3dd8 100644 --- a/libos/test/regression/mock_syscalls.manifest.template +++ b/libos/test/regression/mock_syscalls.manifest.template @@ -33,6 +33,7 @@ sys.debug__mock_syscalls = [ sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ gramine.libos }}", diff --git a/libos/test/regression/multi_pthread.manifest.template b/libos/test/regression/multi_pthread.manifest.template index 2c6240bd7a..884c234811 100644 --- a/libos/test/regression/multi_pthread.manifest.template +++ b/libos/test/regression/multi_pthread.manifest.template @@ -12,6 +12,7 @@ sgx.max_threads = {{ '1' if env.get('EDMM', '0') == '1' else '8' }} sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ gramine.runtimedir(libc) }}/", diff --git a/libos/test/regression/multi_pthread_exitless.manifest.template b/libos/test/regression/multi_pthread_exitless.manifest.template index f2f92753db..64216c24d1 100644 --- a/libos/test/regression/multi_pthread_exitless.manifest.template +++ b/libos/test/regression/multi_pthread_exitless.manifest.template @@ -13,6 +13,7 @@ sgx.insecure__rpc_thread_num = 8 sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ gramine.runtimedir(libc) }}/", diff --git a/libos/test/regression/openmp.manifest.template b/libos/test/regression/openmp.manifest.template index cfcc63bb41..26e4bf8e5b 100644 --- a/libos/test/regression/openmp.manifest.template +++ b/libos/test/regression/openmp.manifest.template @@ -24,6 +24,7 @@ fs.mounts = [ sgx.max_threads = {{ '1' if env.get('EDMM', '0') == '1' else '32' }} sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ gramine.runtimedir(libc) }}/", diff --git a/libos/test/regression/rlimit_nofile_4k.manifest.template b/libos/test/regression/rlimit_nofile_4k.manifest.template index 6f6fe02396..31ce232140 100644 --- a/libos/test/regression/rlimit_nofile_4k.manifest.template +++ b/libos/test/regression/rlimit_nofile_4k.manifest.template @@ -15,6 +15,7 @@ sgx.max_threads = {{ '1' if env.get('EDMM', '0') == '1' else '4' }} sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} sgx.use_exinfo = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ gramine.runtimedir(libc) }}/", diff --git a/libos/test/regression/rwlock.manifest.template b/libos/test/regression/rwlock.manifest.template index 3900ba9dba..a7aac5b7a6 100644 --- a/libos/test/regression/rwlock.manifest.template +++ b/libos/test/regression/rwlock.manifest.template @@ -11,6 +11,7 @@ fs.mounts = [ sgx.max_threads = {{ '1' if env.get('EDMM', '0') == '1' else '200' }} sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ gramine.runtimedir(libc) }}/", diff --git a/libos/test/regression/shadow_pseudo_fs.manifest.template b/libos/test/regression/shadow_pseudo_fs.manifest.template index b0ab21ac02..ff00ed6437 100644 --- a/libos/test/regression/shadow_pseudo_fs.manifest.template +++ b/libos/test/regression/shadow_pseudo_fs.manifest.template @@ -15,6 +15,7 @@ fs.mounts = [ sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ binary_dir }}/{{ entrypoint }}", diff --git a/libos/test/regression/shebang_test_script.manifest.template b/libos/test/regression/shebang_test_script.manifest.template index 1b3b4e3b55..2abfe305cc 100644 --- a/libos/test/regression/shebang_test_script.manifest.template +++ b/libos/test/regression/shebang_test_script.manifest.template @@ -12,6 +12,7 @@ fs.mounts = [ sgx.max_threads = {{ '1' if env.get('EDMM', '0') == '1' else '16' }} sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ gramine.runtimedir(libc) }}/", diff --git a/libos/test/regression/shm.manifest.template b/libos/test/regression/shm.manifest.template index 0d980681d0..8677c4899b 100644 --- a/libos/test/regression/shm.manifest.template +++ b/libos/test/regression/shm.manifest.template @@ -10,6 +10,7 @@ fs.mounts = [ sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.allowed_files = [ "dev:/dev/shm/shm_test", diff --git a/libos/test/regression/sigterm_multithread.manifest.template b/libos/test/regression/sigterm_multithread.manifest.template index 16bf962025..620050e0f1 100644 --- a/libos/test/regression/sigterm_multithread.manifest.template +++ b/libos/test/regression/sigterm_multithread.manifest.template @@ -12,6 +12,7 @@ fs.mounts = [ sgx.max_threads = {{ '1' if env.get('EDMM', '0') == '1' else '16' }} sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ gramine.runtimedir(libc) }}/", diff --git a/libos/test/regression/socket_ioctl.manifest.template b/libos/test/regression/socket_ioctl.manifest.template index 33201f5b38..7459b71337 100644 --- a/libos/test/regression/socket_ioctl.manifest.template +++ b/libos/test/regression/socket_ioctl.manifest.template @@ -10,6 +10,7 @@ fs.mounts = [ sgx.max_threads = {{ '1' if env.get('EDMM', '0') == '1' else '4' }} sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ gramine.runtimedir(libc) }}/", diff --git a/libos/test/regression/sysfs_common.manifest.template b/libos/test/regression/sysfs_common.manifest.template index 6850246587..15f9af4cea 100644 --- a/libos/test/regression/sysfs_common.manifest.template +++ b/libos/test/regression/sysfs_common.manifest.template @@ -9,6 +9,7 @@ fs.mounts = [ sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ gramine.runtimedir(libc) }}/", diff --git a/libos/test/regression/test_libos.py b/libos/test/regression/test_libos.py index 73a5f5f300..acb102539e 100644 --- a/libos/test/regression/test_libos.py +++ b/libos/test/regression/test_libos.py @@ -10,6 +10,7 @@ import tomli from graminelibos.regression import ( + HAS_AEXNOTIFY, HAS_AVX, HAS_EDMM, HAS_SGX, @@ -1391,6 +1392,8 @@ def test_080_close_range(self): stdout, _ = self.run_binary(['close_range']) self.assertIn('TEST OK', stdout) +@unittest.skipIf(HAS_AEXNOTIFY, + 'AEX-Notify HW feature conflicts with debugging tools (in particular, with #BP exceptions)') class TC_50_GDB(RegressionTestCase): def setUp(self): if not self.has_debug(): diff --git a/libos/test/regression/toml_parsing.manifest.template b/libos/test/regression/toml_parsing.manifest.template index a8d99e77d2..84f826c429 100644 --- a/libos/test/regression/toml_parsing.manifest.template +++ b/libos/test/regression/toml_parsing.manifest.template @@ -19,6 +19,7 @@ libos.check_invalid_pointers = false sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} # the manifest options below added only so that they have any test coverage sgx.seal_key.flags_mask = "0xffffffffffffffff" diff --git a/libos/test/regression/uid_gid.manifest.template b/libos/test/regression/uid_gid.manifest.template index be1afc1a00..04e0d4f969 100644 --- a/libos/test/regression/uid_gid.manifest.template +++ b/libos/test/regression/uid_gid.manifest.template @@ -12,6 +12,7 @@ fs.mounts = [ sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ gramine.runtimedir(libc) }}/", diff --git a/pal/regression/Bootstrap6.manifest.template b/pal/regression/Bootstrap6.manifest.template index 08bda1f2b3..a5852e7375 100644 --- a/pal/regression/Bootstrap6.manifest.template +++ b/pal/regression/Bootstrap6.manifest.template @@ -6,3 +6,4 @@ loader.log_level = "debug" sgx.enclave_size = "8192M" sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} diff --git a/pal/regression/Bootstrap7.manifest.template b/pal/regression/Bootstrap7.manifest.template index 177285ef56..0505c7dc09 100644 --- a/pal/regression/Bootstrap7.manifest.template +++ b/pal/regression/Bootstrap7.manifest.template @@ -2,6 +2,7 @@ loader.entrypoint.uri = "file:{{ binary_dir }}/{{ entrypoint }}" sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} loader.env.key1 = "na" loader.env.key2 = "na" diff --git a/pal/regression/File.manifest.template b/pal/regression/File.manifest.template index 59eb3e3c07..9d366b1f31 100644 --- a/pal/regression/File.manifest.template +++ b/pal/regression/File.manifest.template @@ -3,6 +3,7 @@ loader.log_level = "debug" sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} sgx.allowed_files = [ "file:{{ entrypoint }}.manifest", diff --git a/pal/regression/Thread2.manifest.template b/pal/regression/Thread2.manifest.template index 8e9926f044..4d3fb9a1f5 100644 --- a/pal/regression/Thread2.manifest.template +++ b/pal/regression/Thread2.manifest.template @@ -3,3 +3,4 @@ loader.entrypoint.uri = "file:{{ binary_dir }}/{{ entrypoint }}" sgx.max_threads = {{ '1' if env.get('EDMM', '0') == '1' else '2' }} sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} diff --git a/pal/regression/Thread2_edmm.manifest.template b/pal/regression/Thread2_edmm.manifest.template index 0efd657eea..b8a06c33ea 100644 --- a/pal/regression/Thread2_edmm.manifest.template +++ b/pal/regression/Thread2_edmm.manifest.template @@ -5,3 +5,4 @@ loader.entrypoint.uri = "file:{{ binary_dir }}/{{ entrypoint }}" sgx.max_threads = 1 sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} diff --git a/pal/regression/Thread2_exitless.manifest.template b/pal/regression/Thread2_exitless.manifest.template index d416edd8d2..b65a2dc3d9 100644 --- a/pal/regression/Thread2_exitless.manifest.template +++ b/pal/regression/Thread2_exitless.manifest.template @@ -6,3 +6,4 @@ sgx.max_threads = {{ '1' if env.get('EDMM', '0') == '1' else '2' }} sgx.insecure__rpc_thread_num = 2 sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} diff --git a/pal/regression/manifest.template b/pal/regression/manifest.template index 2a388e510a..4761bfa92f 100644 --- a/pal/regression/manifest.template +++ b/pal/regression/manifest.template @@ -4,6 +4,7 @@ loader.insecure__use_cmdline_argv = true sgx.debug = true sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +sgx.experimental_enable_aex_notify = {{ 'true' if env.get('AEXNOTIFY', '0') == '1' else 'false' }} # for Exception test (memfault handler) sgx.use_exinfo = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} diff --git a/pal/src/host/linux-sgx/enclave_entry.S b/pal/src/host/linux-sgx/enclave_entry.S index faeb468db2..c9cdec8a85 100644 --- a/pal/src/host/linux-sgx/enclave_entry.S +++ b/pal/src/host/linux-sgx/enclave_entry.S @@ -41,7 +41,12 @@ # Its sole purpose is to prepare the stage-2 handler by: # - copying the interrupted SSA[0] context on the stack ("CPU context") # - rewiring the SSA[0] context to point to _PalExceptionHandler() -# - invoking EEXIT (so that untrusted runtime can perform ERESUME) +# - handing over control to the SSA[0] context, in one of two ways: +# - AEX-Notify disabled or unavailable (legacy default flows): invoke EEXIT (so that untrusted +# runtime can perform ERESUME which will resume enclave execution in the SSA[0] context) +# - AEX-Notify enabled (explicit opt-in flows): manually restore SSA[0] context, invoke +# EDECCSSA instruction to go from SSA[1] to SSA[0] without exiting the enclave, and jump to +# SSA[0].GPRSGX.RIP to resume enclave execution #include "sgx_arch.h" #include "asm-offsets.h" @@ -251,8 +256,9 @@ enclave_entry: je .Lcssa1_exception_during_enclave_run # We are interrupted during the never-returning OCALL_EXIT. Because the thread is going to exit - # anyway, we can ignore this exception. - jmp .Lcssa1_exception_eexit + # anyway, we can ignore this exception. We also don't care about AEX-Notify mitigations at this + # point, that's why we don't jump to the .Lcssa1_exception_eexit label. + jmp .Lcssa1_exception_eexit_legacy .Lcssa1_exception_during_ocall_flows: # At this point, we are in the stage-1 exception handler (CSSA=1) and @@ -544,6 +550,12 @@ enclave_entry: movq %r10, %rdx .Lcssa1_exception_eexit: + cmpq $0, %gs:SGX_READY_FOR_AEX_NOTIFY + jne .Lcssa1_exception_eexit_aexnotify + +.Lcssa1_exception_eexit_legacy: + # AEX-Notify is disabled/unavailable, stage-1 exception handler follows the normal EEXIT flow + # .Lcssa0_ocall_or_cssa1_exception_eexit has an ABI that uses RSI, RDI, RSP; clear the relevant # regs (note that stage-1 handler didn't clobber RSP -- which contains an untrusted pointer to # untrusted-runtime stack -- but this flow doesn't read/write RSP at all so there is no need to @@ -555,6 +567,70 @@ enclave_entry: movq %rdx, %rbx jmp .Lcssa0_ocall_or_cssa1_exception_eexit +.Lcssa1_exception_eexit_aexnotify: + # AEX-Notify is enabled, stage-1 exception handler doesn't invoke EEXIT but instead the new + # EDECCSSA instruction (before this, need to manually restore SSA[0] context) + + # After restoring SSA[0] context into GPRs, we'll need to jump to the stage-2 handler, so + # memorize SSA[0].GPRSGX.RIP in an otherwise-unused R11. There is a corner case of the stage-1 + # handler's final jmp instruction, see comment at .Lcssa1_exception_eexit_aexnotify_finaljmp. + leaq .Lcssa1_exception_eexit_aexnotify_finaljmp(%rip), %r11 + cmpq %r11, SGX_GPR_RIP(%rbx) + je 1f + + # not at the stage-1 handler's final jmp instruction, use SSA0's RIP directly + movq SGX_GPR_RIP(%rbx), %r11 + jmp 2f + +1: + # at the stage-1 handler's final jmp instruction, skip over this jmp instruction by directly + # jumping to the previously-saved SSA0's RIP (which was saved in R11) + movq SGX_GPR_R11(%rbx), %r11 + +2: + # Clear bit 0 within SSA[0].GPRSGX.AEXNOTIFY (so that ERESUME actually resumes stage-2 + # handler if it was interrupted by yet another AEX). The stage-2 handler, _PalExceptionHandler() + # func, will re-instate this bit before applying mitigations. + movb $0, SGX_GPR_AEXNOTIFY(%rbx) + + # restore context from SSA[0] (which was already modified above to jump to stage-2 C handler); + # note that XSAVE area (xregs) was already restored above, so only need to restore GPRs; + # note that we don't care about SSA[0].GPRSGX.{URSP,URBP,EXITINFO,RESERVED,GSBASE} + + leaq SGX_GPR_RFLAGS(%rbx), %rsp # trick to restore RFLAGS directly from SSA[0].GPRSGX.RFLAGS + popfq + + movq SGX_GPR_FSBASE(%rbx), %rdi + .byte 0xf3, 0x48, 0x0f, 0xae, 0xd7 # WRFSBASE %RDI + + movq SGX_GPR_RDI(%rbx), %rdi # 1st arg to _PalExceptionHandler() + movq SGX_GPR_RSI(%rbx), %rsi # 2nd arg to _PalExceptionHandler() + movq SGX_GPR_RDX(%rbx), %rdx # 3rd arg to _PalExceptionHandler() + movq SGX_GPR_RCX(%rbx), %rcx # 4th arg to _PalExceptionHandler() + movq SGX_GPR_R8(%rbx), %r8 # 5th arg to _PalExceptionHandler() + movq SGX_GPR_R9(%rbx), %r9 # not strictly needed + movq SGX_GPR_R10(%rbx), %r10 # not strictly needed + movq SGX_GPR_R12(%rbx), %r12 # not strictly needed + movq SGX_GPR_R13(%rbx), %r13 # not strictly needed + movq SGX_GPR_R14(%rbx), %r14 # not strictly needed + movq SGX_GPR_R15(%rbx), %r15 # not strictly needed + movq SGX_GPR_RBP(%rbx), %rbp # not strictly needed + movq SGX_GPR_RSP(%rbx), %rsp + xorq %rbx, %rbx # for sanity + + # go from SSA[1] to SSA[0] (more specifically, simply decrement CSSA from 1 to 0); + # must be careful after this ENCLU instruction because may be interrupted by new exceptions + movq $EDECCSSA, %rax + enclu + + # Finally jump to the stage-2 C exception handler. An async signal can arrive at this exact jmp + # instruction. At this point, SSA0 has the correct internally-consistent context for the + # "stage-2 exception handler", so in this corner case the stage-1 exception handler can skip + # over this jmp and rewire SSA0's RIP directly to _PalExceptionHandler(), which at this point is + # stored in SSA[0].GPRSGX.R11. See also code at .Lcssa1_exception_eexit_aexnotify. +.Lcssa1_exception_eexit_aexnotify_finaljmp: + jmp *%r11 + .cfi_endproc @@ -590,6 +666,15 @@ sgx_ocall: pushq %rbx .cfi_offset %rbx, -24 + # disable AEX-Notify during the ocall-exit assembly logic, as (1) there is no security benefit + # in mitigating AEX events during the ocall asm, and (2) AEX-Notify would otherwise clash with + # ocall-exit and return-from-ocall corner case flows (see .Lcssa1_exception_during_ocall_flows) + cmpq $0, %gs:SGX_READY_FOR_AEX_NOTIFY + je 1f + movq %gs:SGX_GPR, %rax + movb $0, SGX_GPR_AEXNOTIFY(%rax) + +1: CHECK_IF_SIGNAL_STACK_IS_USED %rsp, .Lon_signal_stack_ocall, .Lout_of_signal_stack_ocall .Lout_of_signal_stack_ocall: @@ -745,6 +830,13 @@ sgx_ocall: cmpq $PAL_EVENT_NUM_BOUND, %rsi jb 2f +1: + # re-enable AEX-Notify after return-from-ocall; see .Lcssa0_ocall for details + cmpq $0, %gs:SGX_READY_FOR_AEX_NOTIFY + je 1f + movq %gs:SGX_GPR, %rdi + movb $1, SGX_GPR_AEXNOTIFY(%rdi) + 1: # there was no event, simply call _restore_sgx_context(uc, xsave_area) movq %rsp, %rdi diff --git a/pal/src/host/linux-sgx/generated_offsets.c b/pal/src/host/linux-sgx/generated_offsets.c index 8ff89d06ec..d2c313df0f 100644 --- a/pal/src/host/linux-sgx/generated_offsets.c +++ b/pal/src/host/linux-sgx/generated_offsets.c @@ -56,6 +56,7 @@ const struct generated_offset generated_offsets[] = { OFFSET_T(SGX_GPR_RIP, sgx_pal_gpr_t, rip), OFFSET_T(SGX_GPR_EXITINFO, sgx_pal_gpr_t, exitinfo), OFFSET_T(SGX_GPR_AEXNOTIFY, sgx_pal_gpr_t, aexnotify), + OFFSET_T(SGX_GPR_FSBASE, sgx_pal_gpr_t, fsbase), DEFINE(SGX_GPR_SIZE, sizeof(sgx_pal_gpr_t)), /* sgx_cpu_context_t */ @@ -169,6 +170,7 @@ const struct generated_offset generated_offsets[] = { /* pal.h */ DEFINE(PAL_EVENT_NO_EVENT, PAL_EVENT_NO_EVENT), + DEFINE(PAL_EVENT_INTERRUPTED, PAL_EVENT_INTERRUPTED), DEFINE(PAL_EVENT_NUM_BOUND, PAL_EVENT_NUM_BOUND), /* errno */ diff --git a/pal/src/host/linux-sgx/host_entry.S b/pal/src/host/linux-sgx/host_entry.S index a6b24ab6df..72916a8533 100644 --- a/pal/src/host/linux-sgx/host_entry.S +++ b/pal/src/host/linux-sgx/host_entry.S @@ -134,6 +134,20 @@ async_exit_pointer: movb $0, %gs:PAL_HOST_TCB_IN_AEX .cfi_endproc + # In case of non-AEX-Notify flows, ERESUME never morphs into EENTER, so the values in RDI and + # RDX are ignored. Below code snippet becomes a no-op. + # In case of AEX-Notify flows, ERESUME will morph into EENTER. The only way we could arrive to + # this line of code is that there was no pending signal to handle inside the SGX enclave, i.e., + # maybe_raise_pending_signal() didn't do anything. Since there was no real pending signal (but + # AEX happened, so AEX-Notify must react to this), we put a dummy PAL_EVENT_INTERRUPTED (aka + # SIGCONT). By putting this dummy signal, we survive all checks inside Gramine's in-enclave + # logic, because SIGCONT can always arrive and is benign and side-effect-free. Additionally, + # we put a print-error-and-terminate EEXIT target for EENTER (into which ERESUME morphs) to + # improve error diagnostics (such flows must end with EDECCSSA instead of EEXIT, otherwise it + # indicates a bug in Gramine's AEX-Notify flows). + movq $PAL_EVENT_INTERRUPTED, %rdi + leaq .Lsgx_fail_on_morphed_eresume(%rip), %rdx + # fall-through to ERESUME .global eresume_pointer @@ -209,3 +223,19 @@ sgx_raise: # RSI - external event jmp .Ldo_ecall .cfi_endproc + + +.Lsgx_fail_on_morphed_eresume: + .cfi_startproc + + pushq %rbp + .cfi_adjust_cfa_offset 8 + movq %rsp, %rbp + .cfi_offset %rbp, -16 + .cfi_def_cfa_register %rbp + + andq $~0xF, %rsp # Required by System V AMD64 ABI. + callq fail_on_morphed_eresume + ud2 + + .cfi_endproc diff --git a/pal/src/host/linux-sgx/host_exception.c b/pal/src/host/linux-sgx/host_exception.c index 5a2c5a2022..388fe3bd02 100644 --- a/pal/src/host/linux-sgx/host_exception.c +++ b/pal/src/host/linux-sgx/host_exception.c @@ -391,3 +391,9 @@ void maybe_raise_pending_signal(void) { return; } } + +noreturn void fail_on_morphed_eresume(void) { + log_error("Bug in AEX-Notify flows: ERESUME morphed into EENTER but then the enclave performed " + "EEXIT instead of EDECCSSA. Please debug."); + BUG(); +} diff --git a/pal/src/host/linux-sgx/pal_exception.c b/pal/src/host/linux-sgx/pal_exception.c index 6f004491df..af7cf79488 100644 --- a/pal/src/host/linux-sgx/pal_exception.c +++ b/pal/src/host/linux-sgx/pal_exception.c @@ -23,6 +23,7 @@ #define ADDR_IN_PAL(addr) ((void*)(addr) > TEXT_START && (void*)(addr) < TEXT_END) bool g_aex_notify_enabled = false; +uint64_t g_aex_notify_counter = 0; void init_aex_notify_for_thread(void) { if (!g_aex_notify_enabled) @@ -30,25 +31,46 @@ void init_aex_notify_for_thread(void) { SET_ENCLAVE_TCB(ready_for_aex_notify, 1UL); MB(); -#if 0 - /* - * FIXME: Re-enable in the following commit, when all AEX-Notify flows are added. - * Currently this would fail, as the untrusted runtime expects AEX-Notify flows but - * in-enclave runtime doesn't yet implement AEX-Notify flows. - */ GET_ENCLAVE_TCB(gpr)->aexnotify = 1U; MB(); -#endif } void fini_aex_notify_for_thread(void) { if (!g_aex_notify_enabled) return; - SET_ENCLAVE_TCB(ready_for_aex_notify, 0UL); + /* + * Order is important: first the stage-2 signal handler must be informed to *not* re-enable + * AEX-Notify for this thread, then AEX-Notify must be disabled for this thread from the HW + * perspective (so that it doesn't morph ERESUME into EENTER), and finally AEX-Notify must be + * disabled from the SW perspective (so that it doesn't try EDECCSSA instead of EEXIT). + * + * Without `stopping_aex_notify`, a signal could arrive and force `restore_sgx_context()` to + * re-enable AEX-Notify, even if unsetting `aexnotify` was executed in the meantime. + * + * If `ready_for_aex_notify` would be unset before unsetting `aexnotify`, then the HW could + * morph ERESUME into EENTER, and the flow enclave_entry.S:Lcssa1_exception_eexit would choose + * the no-AEX-Notify path and perform EEXIT, which is unsupported in Gramine (Gramine assumes + * that ERESUME never returns). + */ + SET_ENCLAVE_TCB(stopping_aex_notify, 1UL); MB(); GET_ENCLAVE_TCB(gpr)->aexnotify = 0U; MB(); + SET_ENCLAVE_TCB(ready_for_aex_notify, 0UL); + MB(); +} + +static void apply_aex_notify_mitigations(sgx_cpu_context_t* uc, PAL_XREGS_STATE* xregs_state) { + /* + * TODO: introduce mitigations like atomic prefetching of the working set, see proposed + * mitigations in academic paper "AEX-Notify: Thwarting Precise Single-Stepping + * Attacks through Interrupt Awareness for Intel SGX Enclaves" + */ + __UNUSED(uc); + __UNUSED(xregs_state); + + __atomic_fetch_add(&g_aex_notify_counter, 1, __ATOMIC_RELAXED); } /* Restore an sgx_cpu_context_t as generated by .Lhandle_exception. Execution will @@ -58,13 +80,32 @@ noreturn static void restore_sgx_context(sgx_cpu_context_t* uc, PAL_XREGS_STATE* if (xregs_state == NULL) xregs_state = (PAL_XREGS_STATE*)g_xsave_reset_state; -#ifdef ASAN - /* Unpoison the signal stack before leaving it */ uintptr_t sig_stack_low = GET_ENCLAVE_TCB(sig_stack_low); uintptr_t sig_stack_high = GET_ENCLAVE_TCB(sig_stack_high); + bool restored_context_is_sighandler = (uc->rsp >= sig_stack_low && uc->rsp < sig_stack_high); + +#ifdef ASAN + /* Unpoison the signal stack before leaving it */ asan_unpoison_current_stack(sig_stack_low, sig_stack_high - sig_stack_low); #endif + if (g_aex_notify_enabled && GET_ENCLAVE_TCB(ready_for_aex_notify) + && !GET_ENCLAVE_TCB(stopping_aex_notify) && !restored_context_is_sighandler) { + /* + * AEX-Notify must be re-enabled for this enclave thread before applying any mitigations + * (and consequently before restoring the regular execution of the enclave thread). For + * details, see e.g. the official whitepaper on AEX-Notify from Intel. + * + * Note that we re-enable AEX-Notify only in the outermost signal handler (the one that will + * jump to the application code and stack). Otherwise, AEX-Notify would be enabled while + * inside this Gramine-internal signal handler, and exceptions like #PF would result in + * nested invocations of this signal handler, thus overflowing the signal stack. This is + * especially true for the EDMM flows where #PF exceptions are a norm. + */ + GET_ENCLAVE_TCB(gpr)->aexnotify = 1; + apply_aex_notify_mitigations(uc, xregs_state); + } + _restore_sgx_context(uc, xregs_state); } diff --git a/pal/src/host/linux-sgx/pal_linux.h b/pal/src/host/linux-sgx/pal_linux.h index 97060e7bc3..59adc5281e 100644 --- a/pal/src/host/linux-sgx/pal_linux.h +++ b/pal/src/host/linux-sgx/pal_linux.h @@ -96,6 +96,7 @@ void restore_xregs(const PAL_XREGS_STATE* xsave_area); noreturn void _restore_sgx_context(sgx_cpu_context_t* uc, PAL_XREGS_STATE* xsave_area); extern bool g_aex_notify_enabled; +extern uint64_t g_aex_notify_counter; void init_aex_notify_for_thread(void); void fini_aex_notify_for_thread(void); diff --git a/pal/src/host/linux-sgx/pal_process.c b/pal/src/host/linux-sgx/pal_process.c index 9f060b9519..9fde9fa00f 100644 --- a/pal/src/host/linux-sgx/pal_process.c +++ b/pal/src/host/linux-sgx/pal_process.c @@ -246,6 +246,16 @@ int init_child_process(int parent_stream_fd, PAL_HANDLE* out_parent_handle, noreturn void _PalProcessExit(int exitcode) { if (exitcode) log_debug("PalProcessExit: Returning exit code %d", exitcode); + + /* + * FIXME: remove this when proper AEX-Notify mitigations are implemented; + * see pal_exception.c:apply_aex_notify_mitigations() + */ + if (g_aex_notify_enabled) { + uint64_t aex_notify_counter = __atomic_load_n(&g_aex_notify_counter, __ATOMIC_RELAXED); + log_warning("AEX-Notify counter at process exit: %lu", aex_notify_counter); + } + ocall_exit(exitcode, /*is_exitgroup=*/true); /* Unreachable. */ } diff --git a/pal/src/host/linux-sgx/pal_tcb.h b/pal/src/host/linux-sgx/pal_tcb.h index fa6886c029..c746082609 100644 --- a/pal/src/host/linux-sgx/pal_tcb.h +++ b/pal/src/host/linux-sgx/pal_tcb.h @@ -43,6 +43,7 @@ struct pal_enclave_tcb { uint64_t thread_started; uint64_t ready_for_exceptions; uint64_t ready_for_aex_notify; + uint64_t stopping_aex_notify; uint64_t manifest_size; void* heap_min; void* heap_max; @@ -126,4 +127,6 @@ void maybe_dump_and_reset_stats(void); void maybe_raise_pending_signal(void); +noreturn void fail_on_morphed_eresume(void); + #endif /* IN_ENCLAVE */ diff --git a/python/graminelibos/regression.py b/python/graminelibos/regression.py index 5a966dbd6b..b7f9870ad0 100644 --- a/python/graminelibos/regression.py +++ b/python/graminelibos/regression.py @@ -16,6 +16,7 @@ # pylint: disable=subprocess-popen-preexec-fn,subprocess-run-check +HAS_AEXNOTIFY = os.environ.get('AEXNOTIFY') == '1' HAS_AVX = os.environ.get('AVX') == '1' HAS_EDMM = os.environ.get('EDMM') == '1' HAS_SGX = os.environ.get('SGX') == '1'