On Thu, 2023-08-31 at 15:41 +0200, Jo Van Bulck wrote: > 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. > > When keeping encl_op_array as a local variable on the stack, gcc without > optimizations generates code that explicitly gets the right function > addresses and stores them to create the array on the stack: > > encl_body: > /* snipped */ > lea do_encl_op_put_to_buf(%rip), %rax > mov %rax, -0x50(%rbp) > lea do_encl_op_get_from_buf(%rip), %rax > mov %rax,-0x48(%rbp) > lea do_encl_op_put_to_addr(%rip), %rax > /* snipped */ > > However, gcc -Os or clang generate more efficient code that initializes > encl_op_array by copying a "prepared copy" containing the absolute > addresses of the functions (i.e., relative to the image base starting from > 0) generated by the compiler/linker: > > encl_body: > /* snipped */ > lea prepared_copy(%rip), %rsi > lea -0x48(%rsp), %rdi > mov $0x10,%ecx > rep movsl %ds:(%rsi),%es:(%rdi) > /* snipped */ > > When building the enclave with -static-pie, the compiler/linker includes > relocation entries for the function symbols in the "prepared copy": > > Relocation section '.rela.dyn' at offset 0x4000 contains 12 entries: > Offset Info Type Symbol > /* snipped; "prepared_copy" starts at 0x6000 */ > 000000006000 000000000008 R_X86_64_RELATIVE <do_encl_emodpe> > 000000006008 000000000008 R_X86_64_RELATIVE <do_encl_eaccept> > 000000006010 000000000008 R_X86_64_RELATIVE <do_encl_op_put_to_buf> > 000000006018 000000000008 R_X86_64_RELATIVE <do_encl_op_get_from_buf> > 000000006020 000000000008 R_X86_64_RELATIVE <do_encl_op_put_to_addr> > 000000006028 000000000008 R_X86_64_RELATIVE <do_encl_op_get_from_addr> > 000000006030 000000000008 R_X86_64_RELATIVE <do_encl_op_nop> > 000000006038 000000000008 R_X86_64_RELATIVE <do_encl_init_tcs_page> > > Static-pie binaries normally include a glibc "_dl_relocate_static_pie" > routine that will perform these relocations as part of the startup. > However, since the enclave loading process is different and glibc is not > included, we cannot rely on these relocations to be performed. Without > relocations, the code would erroneously jump to the _absolute_ function > address loaded from the local copy. > > Thus, declare "encl_op_array" as global and manually relocate the loaded > function-pointer entries relative to the enclave base at runtime. This > generates the following code: > > encl_body: > /* snipped */ > lea encl_op_array(%rip), %rcx > lea __encl_base(%rip), %rax > add (%rcx,%rdx,8),%rax > jmp *%rax call *%rax ? > ret > > Link: https://lore.kernel.org/all/150d8ca8-2c66-60d1-f9fc-8e6279824e94@xxxxxxxxxxxxxx/ > Link: https://lore.kernel.org/all/5c22de5a-4b3b-1f38-9771-409b4ec7f96d@xxxxxxxxxxxxxx/#r > Signed-off-by: Jo Van Bulck <jo.vanbulck@xxxxxxxxxxxxxx> > Reviewed-by: Jarkko Sakkinen <jarkko@xxxxxxxxxx> Acked-by: Kai Huang <kai.huang@xxxxxxxxx>