diff options
author | Jarkko Sakkinen | 2022-03-13 19:08:30 +0200 |
---|---|---|
committer | Jarkko Sakkinen | 2022-03-13 19:08:30 +0200 |
commit | 9b2edd347b4f5ce31365e5e64397c5ee9f2d1b62 (patch) | |
tree | 77dbf26660dc219fdc137633fda7f3c4003d9305 | |
parent | c3aedcb42fdf3f2539141ee0fa0a3b12e247f7a6 (diff) | |
download | aur-9b2edd347b4f5ce31365e5e64397c5ee9f2d1b62.tar.gz |
Remove SGX2 selftests.
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@iki.fi>
10 files changed, 0 insertions, 2123 deletions
diff --git a/0017-selftests-sgx-Add-test-for-EPCM-permission-changes.patch b/0017-selftests-sgx-Add-test-for-EPCM-permission-changes.patch deleted file mode 100644 index ea5c39188f31..000000000000 --- a/0017-selftests-sgx-Add-test-for-EPCM-permission-changes.patch +++ /dev/null @@ -1,401 +0,0 @@ -From c6ad8031ecdc735fb70305c95be5a54c704a9ebc Mon Sep 17 00:00:00 2001 -From: Reinette Chatre <reinette.chatre@intel.com> -Date: Mon, 7 Feb 2022 16:45:39 -0800 -Subject: [PATCH 17/34] selftests/sgx: Add test for EPCM permission changes - -EPCM permission changes could be made from within (to relax -permissions) or out (to restrict permissions) the enclave. Kernel -support is needed when permissions are restricted to be able to -call the privileged ENCLS[EMODPR] instruction and ensure PTEs -allowing the restricted permissions are flushed. EPCM permissions -can be relaxed via ENCLU[EMODPE] from within the enclave but the -enclave still depends on the kernel to install PTEs with the new -permissions. - -Add a test that exercises a few of the enclave page permission flows: -1) Test starts with a RW (from enclave and kernel perspective) - enclave page that is mapped via a RW VMA. -2) Use the SGX_IOC_ENCLAVE_RESTRICT_PERMISSIONS ioctl() to restrict - the enclave (EPCM) page permissions to read-only (kernel removes - PTE in the process). -3) Run ENCLU[EACCEPT] from within the enclave to accept the new page - permissions. -4) Attempt to write to the enclave page from within the enclave - this - should fail with a page fault on the PTE since the page - table entry accurately reflects the (read-only) EPCM permissions. -5) Restore EPCM permissions to RW by running ENCLU[EMODPE] from within - the enclave. -6) Attempt to write to the enclave page from within the enclave - this - should fail again with a page fault because even though the EPCM - permissions are RW the PTE does not yet reflect that. -7) Use the SGX_IOC_ENCLAVE_RELAX_PERMISSIONS ioctl() to inform the - kernel of new page permissions and PTEs will accurately reflect - RW EPCM permissions. -8) Writing to enclave page from within enclave succeeds. - -Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> ---- - tools/testing/selftests/sgx/defines.h | 15 ++ - tools/testing/selftests/sgx/main.c | 253 ++++++++++++++++++++++++ - tools/testing/selftests/sgx/test_encl.c | 38 ++++ - 3 files changed, 306 insertions(+) - -diff --git a/tools/testing/selftests/sgx/defines.h b/tools/testing/selftests/sgx/defines.h -index 02d775789ea7..b638eb98c80c 100644 ---- a/tools/testing/selftests/sgx/defines.h -+++ b/tools/testing/selftests/sgx/defines.h -@@ -24,6 +24,8 @@ enum encl_op_type { - ENCL_OP_PUT_TO_ADDRESS, - ENCL_OP_GET_FROM_ADDRESS, - ENCL_OP_NOP, -+ ENCL_OP_EACCEPT, -+ ENCL_OP_EMODPE, - ENCL_OP_MAX, - }; - -@@ -53,4 +55,17 @@ struct encl_op_get_from_addr { - uint64_t addr; - }; - -+struct encl_op_eaccept { -+ struct encl_op_header header; -+ uint64_t epc_addr; -+ uint64_t flags; -+ uint64_t ret; -+}; -+ -+struct encl_op_emodpe { -+ struct encl_op_header header; -+ uint64_t epc_addr; -+ uint64_t flags; -+}; -+ - #endif /* DEFINES_H */ -diff --git a/tools/testing/selftests/sgx/main.c b/tools/testing/selftests/sgx/main.c -index dd74fa42302e..4f348ed1dc29 100644 ---- a/tools/testing/selftests/sgx/main.c -+++ b/tools/testing/selftests/sgx/main.c -@@ -25,6 +25,18 @@ static const uint64_t MAGIC = 0x1122334455667788ULL; - static const uint64_t MAGIC2 = 0x8877665544332211ULL; - vdso_sgx_enter_enclave_t vdso_sgx_enter_enclave; - -+/* -+ * Security Information (SECINFO) data structure needed by a few SGX -+ * instructions (eg. ENCLU[EACCEPT] and ENCLU[EMODPE]) holds meta-data -+ * about an enclave page. &enum sgx_secinfo_page_state specifies the -+ * secinfo flags used for page state. -+ */ -+enum sgx_secinfo_page_state { -+ SGX_SECINFO_PENDING = (1 << 3), -+ SGX_SECINFO_MODIFIED = (1 << 4), -+ SGX_SECINFO_PR = (1 << 5), -+}; -+ - struct vdso_symtab { - Elf64_Sym *elf_symtab; - const char *elf_symstrtab; -@@ -555,4 +567,245 @@ TEST_F(enclave, pte_permissions) - EXPECT_EQ(self->run.exception_addr, 0); - } - -+/* -+ * Enclave page permission test. -+ * -+ * Modify and restore enclave page's EPCM (enclave) permissions from -+ * outside enclave (ENCLS[EMODPR] via kernel) as well as from within -+ * enclave (via ENCLU[EMODPE]). Kernel should ensure PTE permissions -+ * are the same as the EPCM permissions so check for page fault if -+ * VMA allows access but EPCM and PTE does not. -+ */ -+TEST_F(enclave, epcm_permissions) -+{ -+ struct sgx_enclave_restrict_perm restrict_ioc; -+ struct encl_op_get_from_addr get_addr_op; -+ struct sgx_enclave_relax_perm relax_ioc; -+ struct encl_op_put_to_addr put_addr_op; -+ struct encl_op_eaccept eaccept_op; -+ struct encl_op_emodpe emodpe_op; -+ struct sgx_secinfo secinfo; -+ unsigned long data_start; -+ int ret, errno_save; -+ -+ ASSERT_TRUE(setup_test_encl(ENCL_HEAP_SIZE_DEFAULT, &self->encl, _metadata)); -+ -+ memset(&self->run, 0, sizeof(self->run)); -+ self->run.tcs = self->encl.encl_base; -+ -+ /* -+ * Ensure kernel supports needed ioctl() and system supports needed -+ * commands. -+ */ -+ memset(&restrict_ioc, 0, sizeof(restrict_ioc)); -+ memset(&secinfo, 0, sizeof(secinfo)); -+ -+ ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_RESTRICT_PERMISSIONS, -+ &restrict_ioc); -+ errno_save = ret == -1 ? errno : 0; -+ -+ /* -+ * Invalid parameters were provided during sanity check, -+ * expect command to fail. -+ */ -+ ASSERT_EQ(ret, -1); -+ -+ /* ret == -1 */ -+ if (errno_save == ENOTTY) -+ SKIP(return, -+ "Kernel does not support SGX_IOC_ENCLAVE_RESTRICT_PERMISSIONS ioctl()"); -+ else if (errno_save == ENODEV) -+ SKIP(return, "System does not support SGX2"); -+ -+ /* -+ * Page that will have its permissions changed is the second data -+ * page in the .data segment. This forms part of the local encl_buffer -+ * within the enclave. -+ * -+ * At start of test @data_start should have EPCM as well as PTE -+ * permissions of RW. -+ */ -+ -+ data_start = self->encl.encl_base + -+ encl_get_data_offset(&self->encl) + PAGE_SIZE; -+ -+ /* -+ * Sanity check that page at @data_start is writable before making -+ * any changes to page permissions. -+ * -+ * Start by writing MAGIC to test page. -+ */ -+ put_addr_op.value = MAGIC; -+ put_addr_op.addr = data_start; -+ put_addr_op.header.type = ENCL_OP_PUT_TO_ADDRESS; -+ -+ EXPECT_EQ(ENCL_CALL(&put_addr_op, &self->run, true), 0); -+ -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ -+ /* -+ * Read memory that was just written to, confirming that -+ * page is writable. -+ */ -+ get_addr_op.value = 0; -+ get_addr_op.addr = data_start; -+ get_addr_op.header.type = ENCL_OP_GET_FROM_ADDRESS; -+ -+ EXPECT_EQ(ENCL_CALL(&get_addr_op, &self->run, true), 0); -+ -+ EXPECT_EQ(get_addr_op.value, MAGIC); -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ -+ /* -+ * Change EPCM permissions to read-only, PTE entry flushed by -+ * kernel in the process. -+ */ -+ memset(&restrict_ioc, 0, sizeof(restrict_ioc)); -+ memset(&secinfo, 0, sizeof(secinfo)); -+ -+ secinfo.flags = PROT_READ; -+ restrict_ioc.offset = encl_get_data_offset(&self->encl) + PAGE_SIZE; -+ restrict_ioc.length = PAGE_SIZE; -+ restrict_ioc.secinfo = (unsigned long)&secinfo; -+ -+ ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_RESTRICT_PERMISSIONS, -+ &restrict_ioc); -+ errno_save = ret == -1 ? errno : 0; -+ -+ EXPECT_EQ(ret, 0); -+ EXPECT_EQ(errno_save, 0); -+ EXPECT_EQ(restrict_ioc.result, 0); -+ EXPECT_EQ(restrict_ioc.count, 4096); -+ -+ /* -+ * EPCM permissions changed from kernel, need to EACCEPT from enclave. -+ */ -+ eaccept_op.epc_addr = data_start; -+ eaccept_op.flags = PROT_READ | SGX_SECINFO_REG | SGX_SECINFO_PR; -+ eaccept_op.ret = 0; -+ eaccept_op.header.type = ENCL_OP_EACCEPT; -+ -+ EXPECT_EQ(ENCL_CALL(&eaccept_op, &self->run, true), 0); -+ -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ EXPECT_EQ(eaccept_op.ret, 0); -+ -+ /* -+ * EPCM permissions of page is now read-only, expect #PF -+ * on PTE (not EPCM) when attempting to write to page from -+ * within enclave. -+ */ -+ put_addr_op.value = MAGIC2; -+ -+ EXPECT_EQ(ENCL_CALL(&put_addr_op, &self->run, true), 0); -+ -+ EXPECT_EQ(self->run.function, ERESUME); -+ EXPECT_EQ(self->run.exception_vector, 14); -+ EXPECT_EQ(self->run.exception_error_code, 0x7); -+ EXPECT_EQ(self->run.exception_addr, data_start); -+ -+ self->run.exception_vector = 0; -+ self->run.exception_error_code = 0; -+ self->run.exception_addr = 0; -+ -+ /* -+ * Received AEX but cannot return to enclave at same entrypoint, -+ * need different TCS from where EPCM permission can be made writable -+ * again. -+ */ -+ self->run.tcs = self->encl.encl_base + PAGE_SIZE; -+ -+ /* -+ * Enter enclave at new TCS to change EPCM permissions to be -+ * writable again and thus fix the page fault that triggered the -+ * AEX. -+ */ -+ -+ emodpe_op.epc_addr = data_start; -+ emodpe_op.flags = PROT_READ | PROT_WRITE; -+ emodpe_op.header.type = ENCL_OP_EMODPE; -+ -+ EXPECT_EQ(ENCL_CALL(&emodpe_op, &self->run, true), 0); -+ -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ -+ /* -+ * Attempt to return to main TCS to resume execution at faulting -+ * instruction, but PTE should still prevent writing to the page. -+ */ -+ self->run.tcs = self->encl.encl_base; -+ -+ EXPECT_EQ(vdso_sgx_enter_enclave((unsigned long)&put_addr_op, 0, 0, -+ ERESUME, 0, 0, -+ &self->run), -+ 0); -+ -+ EXPECT_EQ(self->run.function, ERESUME); -+ EXPECT_EQ(self->run.exception_vector, 14); -+ EXPECT_EQ(self->run.exception_error_code, 0x7); -+ EXPECT_EQ(self->run.exception_addr, data_start); -+ -+ self->run.exception_vector = 0; -+ self->run.exception_error_code = 0; -+ self->run.exception_addr = 0; -+ /* -+ * Inform kernel about new permissions to have PTEs match EPCM. -+ */ -+ memset(&relax_ioc, 0, sizeof(relax_ioc)); -+ memset(&secinfo, 0, sizeof(secinfo)); -+ -+ secinfo.flags = PROT_READ | PROT_WRITE; -+ relax_ioc.offset = encl_get_data_offset(&self->encl) + PAGE_SIZE; -+ relax_ioc.length = PAGE_SIZE; -+ relax_ioc.secinfo = (unsigned long)&secinfo; -+ -+ ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_RELAX_PERMISSIONS, -+ &relax_ioc); -+ errno_save = ret == -1 ? errno : 0; -+ -+ EXPECT_EQ(ret, 0); -+ EXPECT_EQ(errno_save, 0); -+ EXPECT_EQ(relax_ioc.count, 4096); -+ -+ /* -+ * Wrong page permissions that caused original fault has -+ * now been fixed via EPCM permissions as well as PTE. -+ * Resume execution in main TCS to re-attempt the memory access. -+ */ -+ self->run.tcs = self->encl.encl_base; -+ -+ EXPECT_EQ(vdso_sgx_enter_enclave((unsigned long)&put_addr_op, 0, 0, -+ ERESUME, 0, 0, -+ &self->run), -+ 0); -+ -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ -+ get_addr_op.value = 0; -+ -+ EXPECT_EQ(ENCL_CALL(&get_addr_op, &self->run, true), 0); -+ -+ EXPECT_EQ(get_addr_op.value, MAGIC2); -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.user_data, 0); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+} -+ - TEST_HARNESS_MAIN -diff --git a/tools/testing/selftests/sgx/test_encl.c b/tools/testing/selftests/sgx/test_encl.c -index 4fca01cfd898..5b6c65331527 100644 ---- a/tools/testing/selftests/sgx/test_encl.c -+++ b/tools/testing/selftests/sgx/test_encl.c -@@ -11,6 +11,42 @@ - */ - static uint8_t encl_buffer[8192] = { 1 }; - -+enum sgx_enclu_function { -+ EACCEPT = 0x5, -+ EMODPE = 0x6, -+}; -+ -+static void do_encl_emodpe(void *_op) -+{ -+ struct sgx_secinfo secinfo __aligned(sizeof(struct sgx_secinfo)) = {0}; -+ struct encl_op_emodpe *op = _op; -+ -+ secinfo.flags = op->flags; -+ -+ asm volatile(".byte 0x0f, 0x01, 0xd7" -+ : -+ : "a" (EMODPE), -+ "b" (&secinfo), -+ "c" (op->epc_addr)); -+} -+ -+static void do_encl_eaccept(void *_op) -+{ -+ struct sgx_secinfo secinfo __aligned(sizeof(struct sgx_secinfo)) = {0}; -+ struct encl_op_eaccept *op = _op; -+ int rax; -+ -+ secinfo.flags = op->flags; -+ -+ asm volatile(".byte 0x0f, 0x01, 0xd7" -+ : "=a" (rax) -+ : "a" (EACCEPT), -+ "b" (&secinfo), -+ "c" (op->epc_addr)); -+ -+ op->ret = rax; -+} -+ - static void *memcpy(void *dest, const void *src, size_t n) - { - size_t i; -@@ -62,6 +98,8 @@ void encl_body(void *rdi, void *rsi) - do_encl_op_put_to_addr, - do_encl_op_get_from_addr, - do_encl_op_nop, -+ do_encl_eaccept, -+ do_encl_emodpe, - }; - - struct encl_op_header *op = (struct encl_op_header *)rdi; --- -2.35.1 - diff --git a/0018-selftests-sgx-Add-test-for-TCS-page-permission-chang.patch b/0018-selftests-sgx-Add-test-for-TCS-page-permission-chang.patch deleted file mode 100644 index 0c23834714fc..000000000000 --- a/0018-selftests-sgx-Add-test-for-TCS-page-permission-chang.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 0b54ab006b8b54ffbeb8abf57ba07221c2eae035 Mon Sep 17 00:00:00 2001 -From: Reinette Chatre <reinette.chatre@intel.com> -Date: Mon, 7 Feb 2022 16:45:40 -0800 -Subject: [PATCH 18/34] selftests/sgx: Add test for TCS page permission changes - -Kernel should not allow permission changes on TCS pages. Add test to -confirm this behavior. - -Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> ---- - tools/testing/selftests/sgx/main.c | 74 ++++++++++++++++++++++++++++++ - 1 file changed, 74 insertions(+) - -diff --git a/tools/testing/selftests/sgx/main.c b/tools/testing/selftests/sgx/main.c -index 4f348ed1dc29..1398cd1b0983 100644 ---- a/tools/testing/selftests/sgx/main.c -+++ b/tools/testing/selftests/sgx/main.c -@@ -121,6 +121,24 @@ static Elf64_Sym *vdso_symtab_get(struct vdso_symtab *symtab, const char *name) - return NULL; - } - -+/* -+ * Return the offset in the enclave where the TCS segment can be found. -+ * The first RW segment loaded is the TCS. -+ */ -+static off_t encl_get_tcs_offset(struct encl *encl) -+{ -+ int i; -+ -+ for (i = 0; i < encl->nr_segments; i++) { -+ struct encl_segment *seg = &encl->segment_tbl[i]; -+ -+ if (i == 0 && seg->prot == (PROT_READ | PROT_WRITE)) -+ return seg->offset; -+ } -+ -+ return -1; -+} -+ - /* - * Return the offset in the enclave where the data segment can be found. - * The first RW segment loaded is the TCS, skip that to get info on the -@@ -567,6 +585,62 @@ TEST_F(enclave, pte_permissions) - EXPECT_EQ(self->run.exception_addr, 0); - } - -+/* -+ * Modifying permissions of TCS page should not be possible. -+ */ -+TEST_F(enclave, tcs_permissions) -+{ -+ struct sgx_enclave_restrict_perm ioc; -+ struct sgx_secinfo secinfo; -+ int ret, errno_save; -+ -+ ASSERT_TRUE(setup_test_encl(ENCL_HEAP_SIZE_DEFAULT, &self->encl, _metadata)); -+ -+ memset(&self->run, 0, sizeof(self->run)); -+ self->run.tcs = self->encl.encl_base; -+ -+ memset(&ioc, 0, sizeof(ioc)); -+ memset(&secinfo, 0, sizeof(secinfo)); -+ -+ /* -+ * Ensure kernel supports needed ioctl() and system supports needed -+ * commands. -+ */ -+ -+ ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_RESTRICT_PERMISSIONS, &ioc); -+ errno_save = ret == -1 ? errno : 0; -+ -+ /* -+ * Invalid parameters were provided during sanity check, -+ * expect command to fail. -+ */ -+ ASSERT_EQ(ret, -1); -+ -+ /* ret == -1 */ -+ if (errno_save == ENOTTY) -+ SKIP(return, -+ "Kernel does not support SGX_IOC_ENCLAVE_RESTRICT_PERMISSIONS ioctl()"); -+ else if (errno_save == ENODEV) -+ SKIP(return, "System does not support SGX2"); -+ -+ /* -+ * Attempt to make TCS page read-only. This is not allowed and -+ * should be prevented by the kernel. -+ */ -+ secinfo.flags = PROT_READ; -+ ioc.offset = encl_get_tcs_offset(&self->encl); -+ ioc.length = PAGE_SIZE; -+ ioc.secinfo = (unsigned long)&secinfo; -+ -+ ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_RESTRICT_PERMISSIONS, &ioc); -+ errno_save = ret == -1 ? errno : 0; -+ -+ EXPECT_EQ(ret, -1); -+ EXPECT_EQ(errno_save, EINVAL); -+ EXPECT_EQ(ioc.result, 0); -+ EXPECT_EQ(ioc.count, 0); -+} -+ - /* - * Enclave page permission test. - * --- -2.35.1 - diff --git a/0021-selftests-sgx-Test-two-different-SGX2-EAUG-flows.patch b/0021-selftests-sgx-Test-two-different-SGX2-EAUG-flows.patch deleted file mode 100644 index ef31e923a9c5..000000000000 --- a/0021-selftests-sgx-Test-two-different-SGX2-EAUG-flows.patch +++ /dev/null @@ -1,294 +0,0 @@ -From 3913725f6fcade6d3ce8139862320e48845c9ad9 Mon Sep 17 00:00:00 2001 -From: Reinette Chatre <reinette.chatre@intel.com> -Date: Mon, 7 Feb 2022 16:45:43 -0800 -Subject: [PATCH 21/34] selftests/sgx: Test two different SGX2 EAUG flows - -Enclave pages can be added to an initialized enclave when an address -belonging to the enclave but without a backing page is accessed from -within the enclave. - -Accessing memory without a backing enclave page from within an enclave -can be in different ways: -1) Pre-emptively run ENCLU[EACCEPT]. Since the addition of a page - always needs to be accepted by the enclave via ENCLU[EACCEPT] this - flow is efficient since the first execution of ENCLU[EACCEPT] - triggers the addition of the page and when execution returns to the - same instruction the second execution would be successful as an - acceptance of the page. - -2) A direct read or write. The flow where a direct read or write - triggers the page addition execution cannot resume from the - instruction (read/write) that triggered the fault but instead - the enclave needs to be entered at a different entry point to - run needed ENCLU[EACCEPT] before execution can return to the - original entry point and the read/write instruction that faulted. - -Add tests for both flows. - -Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> ---- - tools/testing/selftests/sgx/main.c | 243 +++++++++++++++++++++++++++++ - 1 file changed, 243 insertions(+) - -diff --git a/tools/testing/selftests/sgx/main.c b/tools/testing/selftests/sgx/main.c -index 1398cd1b0983..68285603b3f0 100644 ---- a/tools/testing/selftests/sgx/main.c -+++ b/tools/testing/selftests/sgx/main.c -@@ -86,6 +86,15 @@ static bool vdso_get_symtab(void *addr, struct vdso_symtab *symtab) - return true; - } - -+static inline int sgx2_supported(void) -+{ -+ unsigned int eax, ebx, ecx, edx; -+ -+ __cpuid_count(SGX_CPUID, 0x0, eax, ebx, ecx, edx); -+ -+ return eax & 0x2; -+} -+ - static unsigned long elf_sym_hash(const char *name) - { - unsigned long h = 0, high; -@@ -882,4 +891,238 @@ TEST_F(enclave, epcm_permissions) - EXPECT_EQ(self->run.exception_addr, 0); - } - -+/* -+ * Test the addition of pages to an initialized enclave via writing to -+ * a page belonging to the enclave's address space but was not added -+ * during enclave creation. -+ */ -+TEST_F(enclave, augment) -+{ -+ struct encl_op_get_from_addr get_addr_op; -+ struct encl_op_put_to_addr put_addr_op; -+ struct encl_op_eaccept eaccept_op; -+ size_t total_size = 0; -+ void *addr; -+ int i; -+ -+ if (!sgx2_supported()) -+ SKIP(return, "SGX2 not supported"); -+ -+ ASSERT_TRUE(setup_test_encl(ENCL_HEAP_SIZE_DEFAULT, &self->encl, _metadata)); -+ -+ memset(&self->run, 0, sizeof(self->run)); -+ self->run.tcs = self->encl.encl_base; -+ -+ for (i = 0; i < self->encl.nr_segments; i++) { -+ struct encl_segment *seg = &self->encl.segment_tbl[i]; -+ -+ total_size += seg->size; -+ } -+ -+ /* -+ * Actual enclave size is expected to be larger than the loaded -+ * test enclave since enclave size must be a power of 2 in bytes -+ * and test_encl does not consume it all. -+ */ -+ EXPECT_LT(total_size + PAGE_SIZE, self->encl.encl_size); -+ -+ /* -+ * Create memory mapping for the page that will be added. New -+ * memory mapping is for one page right after all existing -+ * mappings. -+ */ -+ addr = mmap((void *)self->encl.encl_base + total_size, PAGE_SIZE, -+ PROT_READ | PROT_WRITE | PROT_EXEC, -+ MAP_SHARED | MAP_FIXED, self->encl.fd, 0); -+ EXPECT_NE(addr, MAP_FAILED); -+ -+ self->run.exception_vector = 0; -+ self->run.exception_error_code = 0; -+ self->run.exception_addr = 0; -+ -+ /* -+ * Attempt to write to the new page from within enclave. -+ * Expected to fail since page is not (yet) part of the enclave. -+ * The first #PF will trigger the addition of the page to the -+ * enclave, but since the new page needs an EACCEPT from within the -+ * enclave before it can be used it would not be possible -+ * to successfully return to the failing instruction. This is the -+ * cause of the second #PF captured here having the SGX bit set, -+ * it is from hardware preventing the page from being used. -+ */ -+ put_addr_op.value = MAGIC; -+ put_addr_op.addr = (unsigned long)addr; -+ put_addr_op.header.type = ENCL_OP_PUT_TO_ADDRESS; -+ -+ EXPECT_EQ(ENCL_CALL(&put_addr_op, &self->run, true), 0); -+ -+ EXPECT_EQ(self->run.function, ERESUME); -+ EXPECT_EQ(self->run.exception_vector, 14); -+ EXPECT_EQ(self->run.exception_addr, (unsigned long)addr); -+ -+ if (self->run.exception_error_code == 0x6) { -+ munmap(addr, PAGE_SIZE); -+ SKIP(return, "Kernel does not support adding pages to initialized enclave"); -+ } -+ -+ EXPECT_EQ(self->run.exception_error_code, 0x8007); -+ -+ self->run.exception_vector = 0; -+ self->run.exception_error_code = 0; -+ self->run.exception_addr = 0; -+ -+ /* Handle AEX by running EACCEPT from new entry point. */ -+ self->run.tcs = self->encl.encl_base + PAGE_SIZE; -+ -+ eaccept_op.epc_addr = self->encl.encl_base + total_size; -+ eaccept_op.flags = SGX_SECINFO_R | SGX_SECINFO_W | SGX_SECINFO_REG | SGX_SECINFO_PENDING; -+ eaccept_op.ret = 0; -+ eaccept_op.header.type = ENCL_OP_EACCEPT; -+ -+ EXPECT_EQ(ENCL_CALL(&eaccept_op, &self->run, true), 0); -+ -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ EXPECT_EQ(eaccept_op.ret, 0); -+ -+ /* Can now return to main TCS to resume execution. */ -+ self->run.tcs = self->encl.encl_base; -+ -+ EXPECT_EQ(vdso_sgx_enter_enclave((unsigned long)&put_addr_op, 0, 0, -+ ERESUME, 0, 0, -+ &self->run), -+ 0); -+ -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ -+ /* -+ * Read memory from newly added page that was just written to, -+ * confirming that data previously written (MAGIC) is present. -+ */ -+ get_addr_op.value = 0; -+ get_addr_op.addr = (unsigned long)addr; -+ get_addr_op.header.type = ENCL_OP_GET_FROM_ADDRESS; -+ -+ EXPECT_EQ(ENCL_CALL(&get_addr_op, &self->run, true), 0); -+ -+ EXPECT_EQ(get_addr_op.value, MAGIC); -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ -+ munmap(addr, PAGE_SIZE); -+} -+ -+/* -+ * Test for the addition of pages to an initialized enclave via a -+ * pre-emptive run of EACCEPT on page to be added. -+ */ -+TEST_F(enclave, augment_via_eaccept) -+{ -+ struct encl_op_get_from_addr get_addr_op; -+ struct encl_op_put_to_addr put_addr_op; -+ struct encl_op_eaccept eaccept_op; -+ size_t total_size = 0; -+ void *addr; -+ int i; -+ -+ if (!sgx2_supported()) -+ SKIP(return, "SGX2 not supported"); -+ -+ ASSERT_TRUE(setup_test_encl(ENCL_HEAP_SIZE_DEFAULT, &self->encl, _metadata)); -+ -+ memset(&self->run, 0, sizeof(self->run)); -+ self->run.tcs = self->encl.encl_base; -+ -+ for (i = 0; i < self->encl.nr_segments; i++) { -+ struct encl_segment *seg = &self->encl.segment_tbl[i]; -+ -+ total_size += seg->size; -+ } -+ -+ /* -+ * Actual enclave size is expected to be larger than the loaded -+ * test enclave since enclave size must be a power of 2 in bytes while -+ * test_encl does not consume it all. -+ */ -+ EXPECT_LT(total_size + PAGE_SIZE, self->encl.encl_size); -+ -+ /* -+ * mmap() a page at end of existing enclave to be used for dynamic -+ * EPC page. -+ */ -+ -+ addr = mmap((void *)self->encl.encl_base + total_size, PAGE_SIZE, -+ PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED | MAP_FIXED, -+ self->encl.fd, 0); -+ EXPECT_NE(addr, MAP_FAILED); -+ -+ self->run.exception_vector = 0; -+ self->run.exception_error_code = 0; -+ self->run.exception_addr = 0; -+ -+ /* -+ * Run EACCEPT on new page to trigger the #PF->EAUG->EACCEPT(again -+ * without a #PF). All should be transparent to userspace. -+ */ -+ eaccept_op.epc_addr = self->encl.encl_base + total_size; -+ eaccept_op.flags = SGX_SECINFO_R | SGX_SECINFO_W | SGX_SECINFO_REG | SGX_SECINFO_PENDING; -+ eaccept_op.ret = 0; -+ eaccept_op.header.type = ENCL_OP_EACCEPT; -+ -+ EXPECT_EQ(ENCL_CALL(&eaccept_op, &self->run, true), 0); -+ -+ if (self->run.exception_vector == 14 && -+ self->run.exception_error_code == 4 && -+ self->run.exception_addr == self->encl.encl_base + total_size) { -+ munmap(addr, PAGE_SIZE); -+ SKIP(return, "Kernel does not support adding pages to initialized enclave"); -+ } -+ -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ EXPECT_EQ(eaccept_op.ret, 0); -+ -+ /* -+ * New page should be accessible from within enclave - attempt to -+ * write to it. -+ */ -+ put_addr_op.value = MAGIC; -+ put_addr_op.addr = (unsigned long)addr; -+ put_addr_op.header.type = ENCL_OP_PUT_TO_ADDRESS; -+ -+ EXPECT_EQ(ENCL_CALL(&put_addr_op, &self->run, true), 0); -+ -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ -+ /* -+ * Read memory from newly added page that was just written to, -+ * confirming that data previously written (MAGIC) is present. -+ */ -+ get_addr_op.value = 0; -+ get_addr_op.addr = (unsigned long)addr; -+ get_addr_op.header.type = ENCL_OP_GET_FROM_ADDRESS; -+ -+ EXPECT_EQ(ENCL_CALL(&get_addr_op, &self->run, true), 0); -+ -+ EXPECT_EQ(get_addr_op.value, MAGIC); -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ -+ munmap(addr, PAGE_SIZE); -+} -+ - TEST_HARNESS_MAIN --- -2.35.1 - diff --git a/0025-selftests-sgx-Introduce-dynamic-entry-point.patch b/0025-selftests-sgx-Introduce-dynamic-entry-point.patch deleted file mode 100644 index 2567c11ba574..000000000000 --- a/0025-selftests-sgx-Introduce-dynamic-entry-point.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 4667ff92d36ebd3a891da823ccad82453860603d Mon Sep 17 00:00:00 2001 -From: Reinette Chatre <reinette.chatre@intel.com> -Date: Mon, 7 Feb 2022 16:45:47 -0800 -Subject: [PATCH 25/34] selftests/sgx: Introduce dynamic entry point - -The test enclave (test_encl.elf) is built with two initialized -Thread Control Structures (TCS) included in the binary. Both TCS are -initialized with the same entry point, encl_entry, that correctly -computes the absolute address of the stack based on the stack of each -TCS that is also built into the binary. - -A new TCS can be added dynamically to the enclave and requires to be -initialized with an entry point used to enter the enclave. Since the -existing entry point, encl_entry, assumes that the TCS and its stack -exists at particular offsets within the binary it is not able to handle -a dynamically added TCS and its stack. - -Introduce a new entry point, encl_dyn_entry, that initializes the -absolute address of that thread's stack to the address immediately -preceding the TCS itself. It is now possible to dynamically add a -contiguous memory region to the enclave with the new stack preceding -the new TCS. With the new TCS initialized with encl_dyn_entry as entry -point the absolute address of the stack is computed correctly on entry. - -Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> ---- - tools/testing/selftests/sgx/test_encl_bootstrap.S | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/tools/testing/selftests/sgx/test_encl_bootstrap.S b/tools/testing/selftests/sgx/test_encl_bootstrap.S -index 82fb0dfcbd23..03ae0f57e29d 100644 ---- a/tools/testing/selftests/sgx/test_encl_bootstrap.S -+++ b/tools/testing/selftests/sgx/test_encl_bootstrap.S -@@ -45,6 +45,12 @@ encl_entry: - # TCS #2. By adding the value of encl_stack to it, we get - # the absolute address for the stack. - lea (encl_stack)(%rbx), %rax -+ jmp encl_entry_core -+encl_dyn_entry: -+ # Entry point for dynamically created TCS page expected to follow -+ # its stack directly. -+ lea -1(%rbx), %rax -+encl_entry_core: - xchg %rsp, %rax - push %rax - --- -2.35.1 - diff --git a/0026-selftests-sgx-Introduce-TCS-initialization-enclave-o.patch b/0026-selftests-sgx-Introduce-TCS-initialization-enclave-o.patch deleted file mode 100644 index 90cded650823..000000000000 --- a/0026-selftests-sgx-Introduce-TCS-initialization-enclave-o.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 8144b5b0b7ada1d19f79a080aab412eb7cf04fa8 Mon Sep 17 00:00:00 2001 -From: Reinette Chatre <reinette.chatre@intel.com> -Date: Mon, 7 Feb 2022 16:45:48 -0800 -Subject: [PATCH 26/34] selftests/sgx: Introduce TCS initialization enclave - operation - -The Thread Control Structure (TCS) contains meta-data used by the -hardware to save and restore thread specific information when -entering/exiting the enclave. A TCS can be added to an initialized -enclave by first adding a new regular enclave page, initializing the -content of the new page from within the enclave, and then changing that -page's type to a TCS. - -Support the initialization of a TCS from within the enclave. -The variable information needed that should be provided from outside -the enclave is the address of the TCS, address of the State Save Area -(SSA), and the entry point that the thread should use to enter the -enclave. With this information provided all needed fields of a TCS -can be initialized. - -Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> ---- - tools/testing/selftests/sgx/defines.h | 8 +++++++ - tools/testing/selftests/sgx/test_encl.c | 30 +++++++++++++++++++++++++ - 2 files changed, 38 insertions(+) - -diff --git a/tools/testing/selftests/sgx/defines.h b/tools/testing/selftests/sgx/defines.h -index b638eb98c80c..d8587c971941 100644 ---- a/tools/testing/selftests/sgx/defines.h -+++ b/tools/testing/selftests/sgx/defines.h -@@ -26,6 +26,7 @@ enum encl_op_type { - ENCL_OP_NOP, - ENCL_OP_EACCEPT, - ENCL_OP_EMODPE, -+ ENCL_OP_INIT_TCS_PAGE, - ENCL_OP_MAX, - }; - -@@ -68,4 +69,11 @@ struct encl_op_emodpe { - uint64_t flags; - }; - -+struct encl_op_init_tcs_page { -+ struct encl_op_header header; -+ uint64_t tcs_page; -+ uint64_t ssa; -+ uint64_t entry; -+}; -+ - #endif /* DEFINES_H */ -diff --git a/tools/testing/selftests/sgx/test_encl.c b/tools/testing/selftests/sgx/test_encl.c -index 5b6c65331527..c0d6397295e3 100644 ---- a/tools/testing/selftests/sgx/test_encl.c -+++ b/tools/testing/selftests/sgx/test_encl.c -@@ -57,6 +57,35 @@ static void *memcpy(void *dest, const void *src, size_t n) - return dest; - } - -+static void *memset(void *dest, int c, size_t n) -+{ -+ size_t i; -+ -+ for (i = 0; i < n; i++) -+ ((char *)dest)[i] = c; -+ -+ return dest; -+} -+ -+static void do_encl_init_tcs_page(void *_op) -+{ -+ struct encl_op_init_tcs_page *op = _op; -+ void *tcs = (void *)op->tcs_page; -+ uint32_t val_32; -+ -+ memset(tcs, 0, 16); /* STATE and FLAGS */ -+ memcpy(tcs + 16, &op->ssa, 8); /* OSSA */ -+ memset(tcs + 24, 0, 4); /* CSSA */ -+ val_32 = 1; -+ memcpy(tcs + 28, &val_32, 4); /* NSSA */ -+ memcpy(tcs + 32, &op->entry, 8); /* OENTRY */ -+ memset(tcs + 40, 0, 24); /* AEP, OFSBASE, OGSBASE */ -+ val_32 = 0xFFFFFFFF; -+ memcpy(tcs + 64, &val_32, 4); /* FSLIMIT */ -+ memcpy(tcs + 68, &val_32, 4); /* GSLIMIT */ -+ memset(tcs + 72, 0, 4024); /* Reserved */ -+} -+ - static void do_encl_op_put_to_buf(void *op) - { - struct encl_op_put_to_buf *op2 = op; -@@ -100,6 +129,7 @@ void encl_body(void *rdi, void *rsi) - do_encl_op_nop, - do_encl_eaccept, - do_encl_emodpe, -+ do_encl_init_tcs_page, - }; - - struct encl_op_header *op = (struct encl_op_header *)rdi; --- -2.35.1 - diff --git a/0027-selftests-sgx-Test-complete-changing-of-page-type-fl.patch b/0027-selftests-sgx-Test-complete-changing-of-page-type-fl.patch deleted file mode 100644 index 2e815342d31b..000000000000 --- a/0027-selftests-sgx-Test-complete-changing-of-page-type-fl.patch +++ /dev/null @@ -1,451 +0,0 @@ -From eac764a6b526bdeed60743c0452e75d991c8a5fa Mon Sep 17 00:00:00 2001 -From: Reinette Chatre <reinette.chatre@intel.com> -Date: Mon, 7 Feb 2022 16:45:49 -0800 -Subject: [PATCH 27/34] selftests/sgx: Test complete changing of page type flow - -Support for changing an enclave page's type enables an initialized -enclave to be expanded with support for more threads by changing the -type of a regular enclave page to that of a Thread Control Structure -(TCS). Additionally, being able to change a TCS or regular enclave -page's type to be trimmed (SGX_PAGE_TYPE_TRIM) initiates the removal -of the page from the enclave. - -Test changing page type to TCS as well as page removal flows -in two phases: In the first phase support for a new thread is -dynamically added to an initialized enclave and in the second phase -the pages associated with the new thread are removed from the enclave. -As an additional sanity check after the second phase the page used as -a TCS page during the first phase is added back as a regular page and -ensured that it can be written to (which is not possible if it was a -TCS page). - -Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> ---- - tools/testing/selftests/sgx/load.c | 41 ++++ - tools/testing/selftests/sgx/main.c | 347 +++++++++++++++++++++++++++++ - tools/testing/selftests/sgx/main.h | 1 + - 3 files changed, 389 insertions(+) - -diff --git a/tools/testing/selftests/sgx/load.c b/tools/testing/selftests/sgx/load.c -index 006b464c8fc9..94bdeac1cf04 100644 ---- a/tools/testing/selftests/sgx/load.c -+++ b/tools/testing/selftests/sgx/load.c -@@ -130,6 +130,47 @@ static bool encl_ioc_add_pages(struct encl *encl, struct encl_segment *seg) - return true; - } - -+/* -+ * Parse the enclave code's symbol table to locate and return address of -+ * the provided symbol -+ */ -+uint64_t encl_get_entry(struct encl *encl, const char *symbol) -+{ -+ Elf64_Shdr *sections; -+ Elf64_Sym *symtab; -+ Elf64_Ehdr *ehdr; -+ char *sym_names; -+ int num_sym; -+ int i; -+ -+ ehdr = encl->bin; -+ sections = encl->bin + ehdr->e_shoff; -+ -+ for (i = 0; i < ehdr->e_shnum; i++) { -+ if (sections[i].sh_type == SHT_SYMTAB) { -+ symtab = (Elf64_Sym *)((char *)encl->bin + sections[i].sh_offset); -+ num_sym = sections[i].sh_size / sections[i].sh_entsize; -+ break; -+ } -+ } -+ -+ for (i = 0; i < ehdr->e_shnum; i++) { -+ if (sections[i].sh_type == SHT_STRTAB) { -+ sym_names = (char *)encl->bin + sections[i].sh_offset; -+ break; -+ } -+ } -+ -+ for (i = 0; i < num_sym; i++) { -+ Elf64_Sym *sym = &symtab[i]; -+ -+ if (!strcmp(symbol, sym_names + sym->st_name)) -+ return (uint64_t)sym->st_value; -+ } -+ -+ return 0; -+} -+ - bool encl_load(const char *path, struct encl *encl, unsigned long heap_size) - { - const char device_path[] = "/dev/sgx_enclave"; -diff --git a/tools/testing/selftests/sgx/main.c b/tools/testing/selftests/sgx/main.c -index 68285603b3f0..53a581bd56c5 100644 ---- a/tools/testing/selftests/sgx/main.c -+++ b/tools/testing/selftests/sgx/main.c -@@ -1125,4 +1125,351 @@ TEST_F(enclave, augment_via_eaccept) - munmap(addr, PAGE_SIZE); - } - -+/* -+ * SGX2 page type modification test in two phases: -+ * Phase 1: -+ * Create a new TCS, consisting out of three new pages (stack page with regular -+ * page type, SSA page with regular page type, and TCS page with TCS page -+ * type) in an initialized enclave and run a simple workload within it. -+ * Phase 2: -+ * Remove the three pages added in phase 1, add a new regular page at the -+ * same address that previously hosted the TCS page and verify that it can -+ * be modified. -+ */ -+TEST_F(enclave, tcs_create) -+{ -+ struct encl_op_init_tcs_page init_tcs_page_op; -+ struct sgx_enclave_remove_pages remove_ioc; -+ struct encl_op_get_from_addr get_addr_op; -+ struct encl_op_put_to_addr put_addr_op; -+ struct encl_op_get_from_buf get_buf_op; -+ struct encl_op_put_to_buf put_buf_op; -+ void *addr, *tcs, *stack_end, *ssa; -+ struct encl_op_eaccept eaccept_op; -+ struct sgx_enclave_modt modt_ioc; -+ struct sgx_secinfo secinfo; -+ size_t total_size = 0; -+ uint64_t val_64; -+ int errno_save; -+ int ret, i; -+ -+ ASSERT_TRUE(setup_test_encl(ENCL_HEAP_SIZE_DEFAULT, &self->encl, -+ _metadata)); -+ -+ memset(&self->run, 0, sizeof(self->run)); -+ self->run.tcs = self->encl.encl_base; -+ -+ /* -+ * Hardware (SGX2) and kernel support is needed for this test. Start -+ * with check that test has a chance of succeeding. -+ */ -+ memset(&modt_ioc, 0, sizeof(modt_ioc)); -+ ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_MODIFY_TYPE, &modt_ioc); -+ -+ if (ret == -1) { -+ if (errno == ENOTTY) -+ SKIP(return, "Kernel does not support SGX_IOC_ENCLAVE_MODIFY_TYPE ioctl()"); -+ else if (errno == ENODEV) -+ SKIP(return, "System does not support SGX2"); -+ } -+ -+ /* -+ * Invalid parameters were provided during sanity check, -+ * expect command to fail. -+ */ -+ EXPECT_EQ(ret, -1); -+ -+ /* -+ * Add three regular pages via EAUG: one will be the TCS stack, one -+ * will be the TCS SSA, and one will be the new TCS. The stack and -+ * SSA will remain as regular pages, the TCS page will need its -+ * type changed after populated with needed data. -+ */ -+ for (i = 0; i < self->encl.nr_segments; i++) { -+ struct encl_segment *seg = &self->encl.segment_tbl[i]; -+ -+ total_size += seg->size; -+ } -+ -+ /* -+ * Actual enclave size is expected to be larger than the loaded -+ * test enclave since enclave size must be a power of 2 in bytes while -+ * test_encl does not consume it all. -+ */ -+ EXPECT_LT(total_size + 3 * PAGE_SIZE, self->encl.encl_size); -+ -+ /* -+ * mmap() three pages at end of existing enclave to be used for the -+ * three new pages. -+ */ -+ addr = mmap((void *)self->encl.encl_base + total_size, 3 * PAGE_SIZE, -+ PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, -+ self->encl.fd, 0); -+ EXPECT_NE(addr, MAP_FAILED); -+ -+ self->run.exception_vector = 0; -+ self->run.exception_error_code = 0; -+ self->run.exception_addr = 0; -+ -+ stack_end = (void *)self->encl.encl_base + total_size; -+ tcs = (void *)self->encl.encl_base + total_size + PAGE_SIZE; -+ ssa = (void *)self->encl.encl_base + total_size + 2 * PAGE_SIZE; -+ -+ /* -+ * Run EACCEPT on each new page to trigger the -+ * EACCEPT->(#PF)->EAUG->EACCEPT(again without a #PF) flow. -+ */ -+ -+ eaccept_op.epc_addr = (unsigned long)stack_end; -+ eaccept_op.flags = SGX_SECINFO_R | SGX_SECINFO_W | SGX_SECINFO_REG | SGX_SECINFO_PENDING; -+ eaccept_op.ret = 0; -+ eaccept_op.header.type = ENCL_OP_EACCEPT; -+ -+ EXPECT_EQ(ENCL_CALL(&eaccept_op, &self->run, true), 0); -+ -+ if (self->run.exception_vector == 14 && -+ self->run.exception_error_code == 4 && -+ self->run.exception_addr == (unsigned long)stack_end) { -+ munmap(addr, 3 * PAGE_SIZE); -+ SKIP(return, "Kernel does not support adding pages to initialized enclave"); -+ } -+ -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ EXPECT_EQ(eaccept_op.ret, 0); -+ -+ eaccept_op.epc_addr = (unsigned long)ssa; -+ -+ EXPECT_EQ(ENCL_CALL(&eaccept_op, &self->run, true), 0); -+ -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ EXPECT_EQ(eaccept_op.ret, 0); -+ -+ eaccept_op.epc_addr = (unsigned long)tcs; -+ -+ EXPECT_EQ(ENCL_CALL(&eaccept_op, &self->run, true), 0); -+ -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ EXPECT_EQ(eaccept_op.ret, 0); -+ -+ /* -+ * Three new pages added to enclave. Now populate the TCS page with -+ * needed data. This should be done from within enclave. Provide -+ * the function that will do the actual data population with needed -+ * data. -+ */ -+ -+ /* -+ * New TCS will use the "encl_dyn_entry" entrypoint that expects -+ * stack to begin in page before TCS page. -+ */ -+ val_64 = encl_get_entry(&self->encl, "encl_dyn_entry"); -+ EXPECT_NE(val_64, 0); -+ -+ init_tcs_page_op.tcs_page = (unsigned long)tcs; -+ init_tcs_page_op.ssa = (unsigned long)total_size + 2 * PAGE_SIZE; -+ init_tcs_page_op.entry = val_64; -+ init_tcs_page_op.header.type = ENCL_OP_INIT_TCS_PAGE; -+ -+ EXPECT_EQ(ENCL_CALL(&init_tcs_page_op, &self->run, true), 0); -+ -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ -+ /* Change TCS page type to TCS. */ -+ memset(&modt_ioc, 0, sizeof(modt_ioc)); -+ memset(&secinfo, 0, sizeof(secinfo)); -+ -+ secinfo.flags = SGX_PAGE_TYPE_TCS << 8; -+ modt_ioc.offset = total_size + PAGE_SIZE; -+ modt_ioc.length = PAGE_SIZE; -+ modt_ioc.secinfo = (unsigned long)&secinfo; -+ -+ ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_MODIFY_TYPE, &modt_ioc); -+ errno_save = ret == -1 ? errno : 0; -+ -+ EXPECT_EQ(ret, 0); -+ EXPECT_EQ(errno_save, 0); -+ EXPECT_EQ(modt_ioc.result, 0); -+ EXPECT_EQ(modt_ioc.count, 4096); -+ -+ /* EACCEPT new TCS page from enclave. */ -+ eaccept_op.epc_addr = (unsigned long)tcs; -+ eaccept_op.flags = SGX_SECINFO_TCS | SGX_SECINFO_MODIFIED; -+ eaccept_op.ret = 0; -+ eaccept_op.header.type = ENCL_OP_EACCEPT; -+ -+ EXPECT_EQ(ENCL_CALL(&eaccept_op, &self->run, true), 0); -+ -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ EXPECT_EQ(eaccept_op.ret, 0); -+ -+ /* Run workload from new TCS. */ -+ self->run.tcs = (unsigned long)tcs; -+ -+ /* -+ * Simple workload to write to data buffer and read value back. -+ */ -+ put_buf_op.header.type = ENCL_OP_PUT_TO_BUFFER; -+ put_buf_op.value = MAGIC; -+ -+ EXPECT_EQ(ENCL_CALL(&put_buf_op, &self->run, true), 0); -+ -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ -+ get_buf_op.header.type = ENCL_OP_GET_FROM_BUFFER; -+ get_buf_op.value = 0; -+ -+ EXPECT_EQ(ENCL_CALL(&get_buf_op, &self->run, true), 0); -+ -+ EXPECT_EQ(get_buf_op.value, MAGIC); -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ -+ /* -+ * Phase 2 of test: -+ * Remove pages associated with new TCS, create a regular page -+ * where TCS page used to be and verify it can be used as a regular -+ * page. -+ */ -+ -+ /* Start page removal by requesting change of page type to PT_TRIM. */ -+ memset(&modt_ioc, 0, sizeof(modt_ioc)); -+ memset(&secinfo, 0, sizeof(secinfo)); -+ -+ secinfo.flags = SGX_PAGE_TYPE_TRIM << 8; -+ modt_ioc.offset = total_size; -+ modt_ioc.length = 3 * PAGE_SIZE; -+ modt_ioc.secinfo = (unsigned long)&secinfo; -+ -+ ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_MODIFY_TYPE, &modt_ioc); -+ errno_save = ret == -1 ? errno : 0; -+ -+ EXPECT_EQ(ret, 0); -+ EXPECT_EQ(errno_save, 0); -+ EXPECT_EQ(modt_ioc.result, 0); -+ EXPECT_EQ(modt_ioc.count, 3 * PAGE_SIZE); -+ -+ /* -+ * Enter enclave via TCS #1 and approve page removal by sending -+ * EACCEPT for each of three removed pages. -+ */ -+ self->run.tcs = self->encl.encl_base; -+ -+ eaccept_op.epc_addr = (unsigned long)stack_end; -+ eaccept_op.flags = SGX_SECINFO_TRIM | SGX_SECINFO_MODIFIED; -+ eaccept_op.ret = 0; -+ eaccept_op.header.type = ENCL_OP_EACCEPT; -+ -+ EXPECT_EQ(ENCL_CALL(&eaccept_op, &self->run, true), 0); -+ -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ EXPECT_EQ(eaccept_op.ret, 0); -+ -+ eaccept_op.epc_addr = (unsigned long)tcs; -+ eaccept_op.ret = 0; -+ -+ EXPECT_EQ(ENCL_CALL(&eaccept_op, &self->run, true), 0); -+ -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ EXPECT_EQ(eaccept_op.ret, 0); -+ -+ eaccept_op.epc_addr = (unsigned long)ssa; -+ eaccept_op.ret = 0; -+ -+ EXPECT_EQ(ENCL_CALL(&eaccept_op, &self->run, true), 0); -+ -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ EXPECT_EQ(eaccept_op.ret, 0); -+ -+ /* Send final ioctl() to complete page removal. */ -+ memset(&remove_ioc, 0, sizeof(remove_ioc)); -+ -+ remove_ioc.offset = total_size; -+ remove_ioc.length = 3 * PAGE_SIZE; -+ -+ ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_REMOVE_PAGES, &remove_ioc); -+ errno_save = ret == -1 ? errno : 0; -+ -+ EXPECT_EQ(ret, 0); -+ EXPECT_EQ(errno_save, 0); -+ EXPECT_EQ(remove_ioc.count, 3 * PAGE_SIZE); -+ -+ /* -+ * Enter enclave via TCS #1 and access location where TCS #3 was to -+ * trigger dynamic add of regular page at that location. -+ */ -+ eaccept_op.epc_addr = (unsigned long)tcs; -+ eaccept_op.flags = SGX_SECINFO_R | SGX_SECINFO_W | SGX_SECINFO_REG | SGX_SECINFO_PENDING; -+ eaccept_op.ret = 0; -+ eaccept_op.header.type = ENCL_OP_EACCEPT; -+ -+ EXPECT_EQ(ENCL_CALL(&eaccept_op, &self->run, true), 0); -+ -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ EXPECT_EQ(eaccept_op.ret, 0); -+ -+ /* -+ * New page should be accessible from within enclave - write to it. -+ */ -+ put_addr_op.value = MAGIC; -+ put_addr_op.addr = (unsigned long)tcs; -+ put_addr_op.header.type = ENCL_OP_PUT_TO_ADDRESS; -+ -+ EXPECT_EQ(ENCL_CALL(&put_addr_op, &self->run, true), 0); -+ -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ -+ /* -+ * Read memory from newly added page that was just written to, -+ * confirming that data previously written (MAGIC) is present. -+ */ -+ get_addr_op.value = 0; -+ get_addr_op.addr = (unsigned long)tcs; -+ get_addr_op.header.type = ENCL_OP_GET_FROM_ADDRESS; -+ -+ EXPECT_EQ(ENCL_CALL(&get_addr_op, &self->run, true), 0); -+ -+ EXPECT_EQ(get_addr_op.value, MAGIC); -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ -+ munmap(addr, 3 * PAGE_SIZE); -+} -+ - TEST_HARNESS_MAIN -diff --git a/tools/testing/selftests/sgx/main.h b/tools/testing/selftests/sgx/main.h -index b45c52ec7ab3..fc585be97e2f 100644 ---- a/tools/testing/selftests/sgx/main.h -+++ b/tools/testing/selftests/sgx/main.h -@@ -38,6 +38,7 @@ void encl_delete(struct encl *ctx); - bool encl_load(const char *path, struct encl *encl, unsigned long heap_size); - bool encl_measure(struct encl *encl); - bool encl_build(struct encl *encl); -+uint64_t encl_get_entry(struct encl *encl, const char *symbol); - - int sgx_enter_enclave(void *rdi, void *rsi, long rdx, u32 function, void *r8, void *r9, - struct sgx_enclave_run *run); --- -2.35.1 - diff --git a/0028-selftests-sgx-Test-faulty-enclave-behavior.patch b/0028-selftests-sgx-Test-faulty-enclave-behavior.patch deleted file mode 100644 index 6a2e38d86227..000000000000 --- a/0028-selftests-sgx-Test-faulty-enclave-behavior.patch +++ /dev/null @@ -1,150 +0,0 @@ -From a0c9bfe1e732cbfb9fd5f021373ac71be68daab6 Mon Sep 17 00:00:00 2001 -From: Reinette Chatre <reinette.chatre@intel.com> -Date: Mon, 7 Feb 2022 16:45:50 -0800 -Subject: [PATCH 28/34] selftests/sgx: Test faulty enclave behavior - -Removing a page from an initialized enclave involves three steps: -first the user requests changing the page type to SGX_PAGE_TYPE_TRIM -via an ioctl(), on success the ENCLU[EACCEPT] instruction needs to be -run from within the enclave to accept the page removal, finally the -user requests page removal to be completed via an ioctl(). Only after -acceptance (ENCLU[EACCEPT]) from within the enclave can the kernel -remove the page from a running enclave. - -Test the behavior when the user's request to change the page type -succeeds, but the ENCLU[EACCEPT] instruction is not run before the -ioctl() requesting page removal is run. This should not be permitted. - -Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> ---- - tools/testing/selftests/sgx/main.c | 116 +++++++++++++++++++++++++++++ - 1 file changed, 116 insertions(+) - -diff --git a/tools/testing/selftests/sgx/main.c b/tools/testing/selftests/sgx/main.c -index 53a581bd56c5..e9513ced1853 100644 ---- a/tools/testing/selftests/sgx/main.c -+++ b/tools/testing/selftests/sgx/main.c -@@ -1472,4 +1472,120 @@ TEST_F(enclave, tcs_create) - munmap(addr, 3 * PAGE_SIZE); - } - -+/* -+ * Ensure sane behavior if user requests page removal, does not run -+ * EACCEPT from within enclave but still attempts to finalize page removal -+ * with the SGX_IOC_ENCLAVE_REMOVE_PAGES ioctl(). The latter should fail -+ * because the removal was not EACCEPTed from within the enclave. -+ */ -+TEST_F(enclave, remove_added_page_no_eaccept) -+{ -+ struct sgx_enclave_remove_pages remove_ioc; -+ struct encl_op_get_from_addr get_addr_op; -+ struct encl_op_put_to_addr put_addr_op; -+ struct sgx_enclave_modt modt_ioc; -+ struct sgx_secinfo secinfo; -+ unsigned long data_start; -+ int ret, errno_save; -+ -+ ASSERT_TRUE(setup_test_encl(ENCL_HEAP_SIZE_DEFAULT, &self->encl, _metadata)); -+ -+ memset(&self->run, 0, sizeof(self->run)); -+ self->run.tcs = self->encl.encl_base; -+ -+ /* -+ * Hardware (SGX2) and kernel support is needed for this test. Start -+ * with check that test has a chance of succeeding. -+ */ -+ memset(&modt_ioc, 0, sizeof(modt_ioc)); -+ ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_MODIFY_TYPE, &modt_ioc); -+ -+ if (ret == -1) { -+ if (errno == ENOTTY) -+ SKIP(return, "Kernel does not support SGX_IOC_ENCLAVE_MODIFY_TYPE ioctl()"); -+ else if (errno == ENODEV) -+ SKIP(return, "System does not support SGX2"); -+ } -+ -+ /* -+ * Invalid parameters were provided during sanity check, -+ * expect command to fail. -+ */ -+ EXPECT_EQ(ret, -1); -+ -+ /* -+ * Page that will be removed is the second data page in the .data -+ * segment. This forms part of the local encl_buffer within the -+ * enclave. -+ */ -+ data_start = self->encl.encl_base + -+ encl_get_data_offset(&self->encl) + PAGE_SIZE; -+ -+ /* -+ * Sanity check that page at @data_start is writable before -+ * removing it. -+ * -+ * Start by writing MAGIC to test page. -+ */ -+ put_addr_op.value = MAGIC; -+ put_addr_op.addr = data_start; -+ put_addr_op.header.type = ENCL_OP_PUT_TO_ADDRESS; -+ -+ EXPECT_EQ(ENCL_CALL(&put_addr_op, &self->run, true), 0); -+ -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ -+ /* -+ * Read memory that was just written to, confirming that data -+ * previously written (MAGIC) is present. -+ */ -+ get_addr_op.value = 0; -+ get_addr_op.addr = data_start; -+ get_addr_op.header.type = ENCL_OP_GET_FROM_ADDRESS; -+ -+ EXPECT_EQ(ENCL_CALL(&get_addr_op, &self->run, true), 0); -+ -+ EXPECT_EQ(get_addr_op.value, MAGIC); -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ -+ /* Start page removal by requesting change of page type to PT_TRIM */ -+ memset(&modt_ioc, 0, sizeof(modt_ioc)); -+ memset(&secinfo, 0, sizeof(secinfo)); -+ -+ secinfo.flags = SGX_PAGE_TYPE_TRIM << 8; -+ modt_ioc.offset = encl_get_data_offset(&self->encl) + PAGE_SIZE; -+ modt_ioc.length = PAGE_SIZE; -+ modt_ioc.secinfo = (unsigned long)&secinfo; -+ -+ ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_MODIFY_TYPE, &modt_ioc); -+ errno_save = ret == -1 ? errno : 0; -+ -+ EXPECT_EQ(ret, 0); -+ EXPECT_EQ(errno_save, 0); -+ EXPECT_EQ(modt_ioc.result, 0); -+ EXPECT_EQ(modt_ioc.count, 4096); -+ -+ /* Skip EACCEPT */ -+ -+ /* Send final ioctl() to complete page removal */ -+ memset(&remove_ioc, 0, sizeof(remove_ioc)); -+ -+ remove_ioc.offset = encl_get_data_offset(&self->encl) + PAGE_SIZE; -+ remove_ioc.length = PAGE_SIZE; -+ -+ ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_REMOVE_PAGES, &remove_ioc); -+ errno_save = ret == -1 ? errno : 0; -+ -+ /* Operation not permitted since EACCEPT was omitted. */ -+ EXPECT_EQ(ret, -1); -+ EXPECT_EQ(errno_save, EPERM); -+ EXPECT_EQ(remove_ioc.count, 0); -+} -+ - TEST_HARNESS_MAIN --- -2.35.1 - diff --git a/0029-selftests-sgx-Test-invalid-access-to-removed-enclave.patch b/0029-selftests-sgx-Test-invalid-access-to-removed-enclave.patch deleted file mode 100644 index bf5b43a91dbe..000000000000 --- a/0029-selftests-sgx-Test-invalid-access-to-removed-enclave.patch +++ /dev/null @@ -1,293 +0,0 @@ -From c2acf1ff5207096387acf34a2f5f3492b626cf38 Mon Sep 17 00:00:00 2001 -From: Reinette Chatre <reinette.chatre@intel.com> -Date: Mon, 7 Feb 2022 16:45:51 -0800 -Subject: [PATCH 29/34] selftests/sgx: Test invalid access to removed enclave - page - -Removing a page from an initialized enclave involves three steps: -(1) the user requests changing the page type to SGX_PAGE_TYPE_TRIM -via the SGX_IOC_ENCLAVE_MODIFY_TYPE ioctl(), (2) on success the -ENCLU[EACCEPT] instruction is run from within the enclave to accept -the page removal, (3) the user initiates the actual removal of the -page via the SGX_IOC_ENCLAVE_REMOVE_PAGES ioctl(). - -Test two possible invalid accesses during the page removal flow: -* Test the behavior when a request to remove the page by changing its - type to SGX_PAGE_TYPE_TRIM completes successfully but instead of - executing ENCLU[EACCEPT] from within the enclave the enclave attempts - to read from the page. Even though the page is accessible from the - page table entries its type is SGX_PAGE_TYPE_TRIM and thus not - accessible according to SGX. The expected behavior is a page fault - with the SGX flag set in the error code. -* Test the behavior when the page type is changed successfully and - ENCLU[EACCEPT] was run from within the enclave. The final ioctl(), - SGX_IOC_ENCLAVE_REMOVE_PAGES, is omitted and replaced with an - attempt to access the page. Even though the page is accessible - from the page table entries its type is SGX_PAGE_TYPE_TRIM and - thus not accessible according to SGX. The expected behavior is - a page fault with the SGX flag set in the error code. - -Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> ---- - tools/testing/selftests/sgx/main.c | 247 +++++++++++++++++++++++++++++ - 1 file changed, 247 insertions(+) - -diff --git a/tools/testing/selftests/sgx/main.c b/tools/testing/selftests/sgx/main.c -index e9513ced1853..239d3c9df169 100644 ---- a/tools/testing/selftests/sgx/main.c -+++ b/tools/testing/selftests/sgx/main.c -@@ -1588,4 +1588,251 @@ TEST_F(enclave, remove_added_page_no_eaccept) - EXPECT_EQ(remove_ioc.count, 0); - } - -+/* -+ * Request enclave page removal but instead of correctly following with -+ * EACCEPT a read attempt to page is made from within the enclave. -+ */ -+TEST_F(enclave, remove_added_page_invalid_access) -+{ -+ struct encl_op_get_from_addr get_addr_op; -+ struct encl_op_put_to_addr put_addr_op; -+ struct sgx_enclave_modt ioc; -+ struct sgx_secinfo secinfo; -+ unsigned long data_start; -+ int ret, errno_save; -+ -+ ASSERT_TRUE(setup_test_encl(ENCL_HEAP_SIZE_DEFAULT, &self->encl, _metadata)); -+ -+ memset(&self->run, 0, sizeof(self->run)); -+ self->run.tcs = self->encl.encl_base; -+ -+ /* -+ * Hardware (SGX2) and kernel support is needed for this test. Start -+ * with check that test has a chance of succeeding. -+ */ -+ memset(&ioc, 0, sizeof(ioc)); -+ ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_MODIFY_TYPE, &ioc); -+ -+ if (ret == -1) { -+ if (errno == ENOTTY) -+ SKIP(return, "Kernel does not support SGX_IOC_ENCLAVE_MODIFY_TYPE ioctl()"); -+ else if (errno == ENODEV) -+ SKIP(return, "System does not support SGX2"); -+ } -+ -+ /* -+ * Invalid parameters were provided during sanity check, -+ * expect command to fail. -+ */ -+ EXPECT_EQ(ret, -1); -+ -+ /* -+ * Page that will be removed is the second data page in the .data -+ * segment. This forms part of the local encl_buffer within the -+ * enclave. -+ */ -+ data_start = self->encl.encl_base + -+ encl_get_data_offset(&self->encl) + PAGE_SIZE; -+ -+ /* -+ * Sanity check that page at @data_start is writable before -+ * removing it. -+ * -+ * Start by writing MAGIC to test page. -+ */ -+ put_addr_op.value = MAGIC; -+ put_addr_op.addr = data_start; -+ put_addr_op.header.type = ENCL_OP_PUT_TO_ADDRESS; -+ -+ EXPECT_EQ(ENCL_CALL(&put_addr_op, &self->run, true), 0); -+ -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ -+ /* -+ * Read memory that was just written to, confirming that data -+ * previously written (MAGIC) is present. -+ */ -+ get_addr_op.value = 0; -+ get_addr_op.addr = data_start; -+ get_addr_op.header.type = ENCL_OP_GET_FROM_ADDRESS; -+ -+ EXPECT_EQ(ENCL_CALL(&get_addr_op, &self->run, true), 0); -+ -+ EXPECT_EQ(get_addr_op.value, MAGIC); -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ -+ /* Start page removal by requesting change of page type to PT_TRIM. */ -+ memset(&ioc, 0, sizeof(ioc)); -+ memset(&secinfo, 0, sizeof(secinfo)); -+ -+ secinfo.flags = SGX_PAGE_TYPE_TRIM << 8; -+ ioc.offset = encl_get_data_offset(&self->encl) + PAGE_SIZE; -+ ioc.length = PAGE_SIZE; -+ ioc.secinfo = (unsigned long)&secinfo; -+ -+ ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_MODIFY_TYPE, &ioc); -+ errno_save = ret == -1 ? errno : 0; -+ -+ EXPECT_EQ(ret, 0); -+ EXPECT_EQ(errno_save, 0); -+ EXPECT_EQ(ioc.result, 0); -+ EXPECT_EQ(ioc.count, 4096); -+ -+ /* -+ * Read from page that was just removed. -+ */ -+ get_addr_op.value = 0; -+ -+ EXPECT_EQ(ENCL_CALL(&get_addr_op, &self->run, true), 0); -+ -+ /* -+ * From kernel perspective the page is present but according to SGX the -+ * page should not be accessible so a #PF with SGX bit set is -+ * expected. -+ */ -+ -+ EXPECT_EQ(self->run.function, ERESUME); -+ EXPECT_EQ(self->run.exception_vector, 14); -+ EXPECT_EQ(self->run.exception_error_code, 0x8005); -+ EXPECT_EQ(self->run.exception_addr, data_start); -+} -+ -+/* -+ * Request enclave page removal and correctly follow with -+ * EACCEPT but do not follow with removal ioctl() but instead a read attempt -+ * to removed page is made from within the enclave. -+ */ -+TEST_F(enclave, remove_added_page_invalid_access_after_eaccept) -+{ -+ struct encl_op_get_from_addr get_addr_op; -+ struct encl_op_put_to_addr put_addr_op; -+ struct encl_op_eaccept eaccept_op; -+ struct sgx_enclave_modt ioc; -+ struct sgx_secinfo secinfo; -+ unsigned long data_start; -+ int ret, errno_save; -+ -+ ASSERT_TRUE(setup_test_encl(ENCL_HEAP_SIZE_DEFAULT, &self->encl, _metadata)); -+ -+ memset(&self->run, 0, sizeof(self->run)); -+ self->run.tcs = self->encl.encl_base; -+ -+ /* -+ * Hardware (SGX2) and kernel support is needed for this test. Start -+ * with check that test has a chance of succeeding. -+ */ -+ memset(&ioc, 0, sizeof(ioc)); -+ ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_MODIFY_TYPE, &ioc); -+ -+ if (ret == -1) { -+ if (errno == ENOTTY) -+ SKIP(return, "Kernel does not support SGX_IOC_ENCLAVE_MODIFY_TYPE ioctl()"); -+ else if (errno == ENODEV) -+ SKIP(return, "System does not support SGX2"); -+ } -+ -+ /* -+ * Invalid parameters were provided during sanity check, -+ * expect command to fail. -+ */ -+ EXPECT_EQ(ret, -1); -+ -+ /* -+ * Page that will be removed is the second data page in the .data -+ * segment. This forms part of the local encl_buffer within the -+ * enclave. -+ */ -+ data_start = self->encl.encl_base + -+ encl_get_data_offset(&self->encl) + PAGE_SIZE; -+ -+ /* -+ * Sanity check that page at @data_start is writable before -+ * removing it. -+ * -+ * Start by writing MAGIC to test page. -+ */ -+ put_addr_op.value = MAGIC; -+ put_addr_op.addr = data_start; -+ put_addr_op.header.type = ENCL_OP_PUT_TO_ADDRESS; -+ -+ EXPECT_EQ(ENCL_CALL(&put_addr_op, &self->run, true), 0); -+ -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ -+ /* -+ * Read memory that was just written to, confirming that data -+ * previously written (MAGIC) is present. -+ */ -+ get_addr_op.value = 0; -+ get_addr_op.addr = data_start; -+ get_addr_op.header.type = ENCL_OP_GET_FROM_ADDRESS; -+ -+ EXPECT_EQ(ENCL_CALL(&get_addr_op, &self->run, true), 0); -+ -+ EXPECT_EQ(get_addr_op.value, MAGIC); -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ -+ /* Start page removal by requesting change of page type to PT_TRIM. */ -+ memset(&ioc, 0, sizeof(ioc)); -+ memset(&secinfo, 0, sizeof(secinfo)); -+ -+ secinfo.flags = SGX_PAGE_TYPE_TRIM << 8; -+ ioc.offset = encl_get_data_offset(&self->encl) + PAGE_SIZE; -+ ioc.length = PAGE_SIZE; -+ ioc.secinfo = (unsigned long)&secinfo; -+ -+ ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_MODIFY_TYPE, &ioc); -+ errno_save = ret == -1 ? errno : 0; -+ -+ EXPECT_EQ(ret, 0); -+ EXPECT_EQ(errno_save, 0); -+ EXPECT_EQ(ioc.result, 0); -+ EXPECT_EQ(ioc.count, 4096); -+ -+ eaccept_op.epc_addr = (unsigned long)data_start; -+ eaccept_op.ret = 0; -+ eaccept_op.flags = SGX_SECINFO_TRIM | SGX_SECINFO_MODIFIED; -+ eaccept_op.header.type = ENCL_OP_EACCEPT; -+ -+ EXPECT_EQ(ENCL_CALL(&eaccept_op, &self->run, true), 0); -+ -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ EXPECT_EQ(eaccept_op.ret, 0); -+ -+ /* Skip ioctl() to remove page. */ -+ -+ /* -+ * Read from page that was just removed. -+ */ -+ get_addr_op.value = 0; -+ -+ EXPECT_EQ(ENCL_CALL(&get_addr_op, &self->run, true), 0); -+ -+ /* -+ * From kernel perspective the page is present but according to SGX the -+ * page should not be accessible so a #PF with SGX bit set is -+ * expected. -+ */ -+ -+ EXPECT_EQ(self->run.function, ERESUME); -+ EXPECT_EQ(self->run.exception_vector, 14); -+ EXPECT_EQ(self->run.exception_error_code, 0x8005); -+ EXPECT_EQ(self->run.exception_addr, data_start); -+} -+ - TEST_HARNESS_MAIN --- -2.35.1 - diff --git a/0030-selftests-sgx-Test-reclaiming-of-untouched-page.patch b/0030-selftests-sgx-Test-reclaiming-of-untouched-page.patch deleted file mode 100644 index 76b5d00101ae..000000000000 --- a/0030-selftests-sgx-Test-reclaiming-of-untouched-page.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 88e756e4e0a3a54a226635cd8e3a1a0c26f15032 Mon Sep 17 00:00:00 2001 -From: Reinette Chatre <reinette.chatre@intel.com> -Date: Mon, 7 Feb 2022 16:45:52 -0800 -Subject: [PATCH 30/34] selftests/sgx: Test reclaiming of untouched page - -Removing a page from an initialized enclave involves three steps: -(1) the user requests changing the page type to PT_TRIM via the - SGX_IOC_ENCLAVE_MODIFY_TYPE ioctl() -(2) on success the ENCLU[EACCEPT] instruction is run from within - the enclave to accept the page removal -(3) the user initiates the actual removal of the page via the - SGX_IOC_ENCLAVE_REMOVE_PAGES ioctl(). - -Remove a page that has never been accessed. This means that when the -first ioctl() requesting page removal arrives, there will be no page -table entry, yet a valid page table entry needs to exist for the -ENCLU[EACCEPT] function to succeed. In this test it is verified that -a page table entry can still be installed for a page that is in the -process of being removed. - -Suggested-by: Haitao Huang <haitao.huang@intel.com> -Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> ---- - tools/testing/selftests/sgx/main.c | 82 ++++++++++++++++++++++++++++++ - 1 file changed, 82 insertions(+) - -diff --git a/tools/testing/selftests/sgx/main.c b/tools/testing/selftests/sgx/main.c -index 239d3c9df169..4fe5a0324c97 100644 ---- a/tools/testing/selftests/sgx/main.c -+++ b/tools/testing/selftests/sgx/main.c -@@ -1835,4 +1835,86 @@ TEST_F(enclave, remove_added_page_invalid_access_after_eaccept) - EXPECT_EQ(self->run.exception_addr, data_start); - } - -+TEST_F(enclave, remove_untouched_page) -+{ -+ struct sgx_enclave_remove_pages remove_ioc; -+ struct encl_op_eaccept eaccept_op; -+ struct sgx_enclave_modt modt_ioc; -+ struct sgx_secinfo secinfo; -+ unsigned long data_start; -+ int ret, errno_save; -+ -+ ASSERT_TRUE(setup_test_encl(ENCL_HEAP_SIZE_DEFAULT, &self->encl, _metadata)); -+ -+ /* -+ * Hardware (SGX2) and kernel support is needed for this test. Start -+ * with check that test has a chance of succeeding. -+ */ -+ memset(&modt_ioc, 0, sizeof(modt_ioc)); -+ ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_MODIFY_TYPE, &modt_ioc); -+ -+ if (ret == -1) { -+ if (errno == ENOTTY) -+ SKIP(return, "Kernel does not support SGX_IOC_ENCLAVE_MODIFY_TYPE ioctl()"); -+ else if (errno == ENODEV) -+ SKIP(return, "System does not support SGX2"); -+ } -+ -+ /* -+ * Invalid parameters were provided during sanity check, -+ * expect command to fail. -+ */ -+ EXPECT_EQ(ret, -1); -+ -+ /* SGX2 is supported by kernel and hardware, test can proceed. */ -+ memset(&self->run, 0, sizeof(self->run)); -+ self->run.tcs = self->encl.encl_base; -+ -+ data_start = self->encl.encl_base + -+ encl_get_data_offset(&self->encl) + PAGE_SIZE; -+ -+ memset(&modt_ioc, 0, sizeof(modt_ioc)); -+ memset(&secinfo, 0, sizeof(secinfo)); -+ -+ secinfo.flags = SGX_PAGE_TYPE_TRIM << 8; -+ modt_ioc.offset = encl_get_data_offset(&self->encl) + PAGE_SIZE; -+ modt_ioc.length = PAGE_SIZE; -+ modt_ioc.secinfo = (unsigned long)&secinfo; -+ ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_MODIFY_TYPE, &modt_ioc); -+ errno_save = ret == -1 ? errno : 0; -+ -+ EXPECT_EQ(ret, 0); -+ EXPECT_EQ(errno_save, 0); -+ EXPECT_EQ(modt_ioc.result, 0); -+ EXPECT_EQ(modt_ioc.count, 4096); -+ -+ /* -+ * Enter enclave via TCS #1 and approve page removal by sending -+ * EACCEPT for removed page. -+ */ -+ -+ eaccept_op.epc_addr = data_start; -+ eaccept_op.flags = SGX_SECINFO_TRIM | SGX_SECINFO_MODIFIED; -+ eaccept_op.ret = 0; -+ eaccept_op.header.type = ENCL_OP_EACCEPT; -+ -+ EXPECT_EQ(ENCL_CALL(&eaccept_op, &self->run, true), 0); -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ EXPECT_EQ(eaccept_op.ret, 0); -+ -+ memset(&remove_ioc, 0, sizeof(remove_ioc)); -+ -+ remove_ioc.offset = encl_get_data_offset(&self->encl) + PAGE_SIZE; -+ remove_ioc.length = PAGE_SIZE; -+ ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_REMOVE_PAGES, &remove_ioc); -+ errno_save = ret == -1 ? errno : 0; -+ -+ EXPECT_EQ(ret, 0); -+ EXPECT_EQ(errno_save, 0); -+ EXPECT_EQ(remove_ioc.count, 4096); -+} -+ - TEST_HARNESS_MAIN --- -2.35.1 - diff --git a/0032-selftests-sgx-Page-removal-stress-test.patch b/0032-selftests-sgx-Page-removal-stress-test.patch deleted file mode 100644 index 538943044a94..000000000000 --- a/0032-selftests-sgx-Page-removal-stress-test.patch +++ /dev/null @@ -1,156 +0,0 @@ -From b8bce2280c7d601d875229921cc6126ac55e84c3 Mon Sep 17 00:00:00 2001 -From: Reinette Chatre <reinette.chatre@intel.com> -Date: Mon, 7 Feb 2022 16:45:54 -0800 -Subject: [PATCH 32/34] selftests/sgx: Page removal stress test - -Create enclave with additional heap that consumes all physical SGX -memory and then remove it. - -Depending on the available SGX memory this test could take a -significant time to run (several minutes) as it (1) creates the -enclave, (2) changes the type of every page to be trimmed, -(3) enters the enclave once per page to run EACCEPT, before -(4) the pages are finally removed. - -Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> ---- - tools/testing/selftests/sgx/main.c | 122 +++++++++++++++++++++++++++++ - 1 file changed, 122 insertions(+) - -diff --git a/tools/testing/selftests/sgx/main.c b/tools/testing/selftests/sgx/main.c -index 4fe5a0324c97..22abda2696e2 100644 ---- a/tools/testing/selftests/sgx/main.c -+++ b/tools/testing/selftests/sgx/main.c -@@ -378,7 +378,129 @@ TEST_F(enclave, unclobbered_vdso_oversubscribed) - EXPECT_EQ(get_op.value, MAGIC); - EXPECT_EEXIT(&self->run); - EXPECT_EQ(self->run.user_data, 0); -+} -+ -+TEST_F_TIMEOUT(enclave, unclobbered_vdso_oversubscribed_remove, 900) -+{ -+ struct sgx_enclave_remove_pages remove_ioc; -+ struct encl_op_get_from_buf get_op; -+ struct encl_op_eaccept eaccept_op; -+ struct encl_op_put_to_buf put_op; -+ struct sgx_enclave_modt modt_ioc; -+ struct sgx_secinfo secinfo; -+ struct encl_segment *heap; -+ unsigned long total_mem; -+ int ret, errno_save; -+ unsigned long addr; -+ unsigned long i; -+ -+ /* -+ * Create enclave with additional heap that is as big as all -+ * available physical SGX memory. -+ */ -+ total_mem = get_total_epc_mem(); -+ ASSERT_NE(total_mem, 0); -+ TH_LOG("Creating an enclave with %lu bytes heap may take a while ...", -+ total_mem); -+ ASSERT_TRUE(setup_test_encl(total_mem, &self->encl, _metadata)); -+ -+ /* -+ * Hardware (SGX2) and kernel support is needed for this test. Start -+ * with check that test has a chance of succeeding. -+ */ -+ memset(&modt_ioc, 0, sizeof(modt_ioc)); -+ ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_MODIFY_TYPE, &modt_ioc); -+ -+ if (ret == -1) { -+ if (errno == ENOTTY) -+ SKIP(return, "Kernel does not support SGX_IOC_ENCLAVE_MODIFY_TYPE ioctl()"); -+ else if (errno == ENODEV) -+ SKIP(return, "System does not support SGX2"); -+ } -+ -+ /* -+ * Invalid parameters were provided during sanity check, -+ * expect command to fail. -+ */ -+ EXPECT_EQ(ret, -1); -+ -+ /* SGX2 is supported by kernel and hardware, test can proceed. */ -+ memset(&self->run, 0, sizeof(self->run)); -+ self->run.tcs = self->encl.encl_base; -+ -+ heap = &self->encl.segment_tbl[self->encl.nr_segments - 1]; -+ -+ put_op.header.type = ENCL_OP_PUT_TO_BUFFER; -+ put_op.value = MAGIC; -+ -+ EXPECT_EQ(ENCL_CALL(&put_op, &self->run, false), 0); -+ -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.user_data, 0); -+ -+ get_op.header.type = ENCL_OP_GET_FROM_BUFFER; -+ get_op.value = 0; -+ -+ EXPECT_EQ(ENCL_CALL(&get_op, &self->run, false), 0); -+ -+ EXPECT_EQ(get_op.value, MAGIC); -+ EXPECT_EEXIT(&self->run); -+ EXPECT_EQ(self->run.user_data, 0); -+ -+ /* Trim entire heap. */ -+ memset(&modt_ioc, 0, sizeof(modt_ioc)); -+ memset(&secinfo, 0, sizeof(secinfo)); -+ -+ secinfo.flags = SGX_PAGE_TYPE_TRIM << 8; -+ modt_ioc.offset = heap->offset; -+ modt_ioc.length = heap->size; -+ modt_ioc.secinfo = (unsigned long)&secinfo; -+ -+ TH_LOG("Changing type of %zd bytes to trimmed may take a while ...", -+ heap->size); -+ ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_MODIFY_TYPE, &modt_ioc); -+ errno_save = ret == -1 ? errno : 0; -+ -+ EXPECT_EQ(ret, 0); -+ EXPECT_EQ(errno_save, 0); -+ EXPECT_EQ(modt_ioc.result, 0); -+ EXPECT_EQ(modt_ioc.count, heap->size); -+ -+ /* EACCEPT all removed pages. */ -+ addr = self->encl.encl_base + heap->offset; -+ -+ eaccept_op.flags = SGX_SECINFO_TRIM | SGX_SECINFO_MODIFIED; -+ eaccept_op.header.type = ENCL_OP_EACCEPT; -+ -+ TH_LOG("Entering enclave to run EACCEPT for each page of %zd bytes may take a while ...", -+ heap->size); -+ for (i = 0; i < heap->size; i += 4096) { -+ eaccept_op.epc_addr = addr + i; -+ eaccept_op.ret = 0; - -+ EXPECT_EQ(ENCL_CALL(&eaccept_op, &self->run, true), 0); -+ -+ EXPECT_EQ(self->run.exception_vector, 0); -+ EXPECT_EQ(self->run.exception_error_code, 0); -+ EXPECT_EQ(self->run.exception_addr, 0); -+ ASSERT_EQ(eaccept_op.ret, 0); -+ ASSERT_EQ(self->run.function, EEXIT); -+ } -+ -+ /* Complete page removal. */ -+ memset(&remove_ioc, 0, sizeof(remove_ioc)); -+ -+ remove_ioc.offset = heap->offset; -+ remove_ioc.length = heap->size; -+ -+ TH_LOG("Removing %zd bytes from enclave may take a while ...", -+ heap->size); -+ ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_REMOVE_PAGES, &remove_ioc); -+ errno_save = ret == -1 ? errno : 0; -+ -+ EXPECT_EQ(ret, 0); -+ EXPECT_EQ(errno_save, 0); -+ EXPECT_EQ(remove_ioc.count, heap->size); - } - - TEST_F(enclave, clobbered_vdso) --- -2.35.1 - |