[PATCH 3/8] selftests/sgx: Handle relocations in test enclave

From: Jo Van Bulck
Date: Tue Aug 08 2023 - 16:23:45 EST


Static-pie binaries normally include a startup routine to perform any ELF
relocations from .rela.dyn. Since the enclave loading process is different
and glibc is not included, do the necessary relocation for encl_op_array
entries manually at runtime relative to the enclave base to ensure correct
function pointers.

Signed-off-by: Jo Van Bulck <jo.vanbulck@xxxxxxxxxxxxxx>
---
tools/testing/selftests/sgx/test_encl.c | 35 +++++++++++++++--------
tools/testing/selftests/sgx/test_encl.lds | 3 ++
2 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/tools/testing/selftests/sgx/test_encl.c b/tools/testing/selftests/sgx/test_encl.c
index c0d6397295e3..c71dfbadd2d9 100644
--- a/tools/testing/selftests/sgx/test_encl.c
+++ b/tools/testing/selftests/sgx/test_encl.c
@@ -119,21 +119,32 @@ static void do_encl_op_nop(void *_op)

}

+/*
+ * Symbol placed at the start of the enclave image by the linker script.
+ * Declare this extern symbol with visibility "hidden" to ensure the
+ * compiler does not access it through the GOT.
+ */
+extern uint8_t __attribute__((visibility("hidden"))) __enclave_base;
+
+void (*encl_op_array[ENCL_OP_MAX])(void *) = {
+ do_encl_op_put_to_buf,
+ do_encl_op_get_from_buf,
+ do_encl_op_put_to_addr,
+ do_encl_op_get_from_addr,
+ do_encl_op_nop,
+ do_encl_eaccept,
+ do_encl_emodpe,
+ do_encl_init_tcs_page,
+};
+
void encl_body(void *rdi, void *rsi)
{
- const void (*encl_op_array[ENCL_OP_MAX])(void *) = {
- do_encl_op_put_to_buf,
- do_encl_op_get_from_buf,
- do_encl_op_put_to_addr,
- do_encl_op_get_from_addr,
- 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;

+ /*
+ * Manually rebase the loaded function pointer as enclaves cannot
+ * rely on startup routines to perform static pie relocations.
+ */
if (op->type < ENCL_OP_MAX)
- (*encl_op_array[op->type])(op);
+ (*(((uint64_t) &__enclave_base) + encl_op_array[op->type]))(op);
}
diff --git a/tools/testing/selftests/sgx/test_encl.lds b/tools/testing/selftests/sgx/test_encl.lds
index ca659db2a534..73d9c8bbe7de 100644
--- a/tools/testing/selftests/sgx/test_encl.lds
+++ b/tools/testing/selftests/sgx/test_encl.lds
@@ -32,6 +32,9 @@ SECTIONS
*(.note*)
*(.debug*)
*(.eh_frame*)
+ /* Dynamic symbol table not supported in enclaves */
+ *(.dyn*)
+ *(.gnu.hash)
}
}

--
2.34.1