55#include "defines.h"
66
77/*
8- * Data buffer spanning two pages that will be placed first in .data
9- * segment. Even if not used internally the second page is needed by
10- * external test manipulating page permissions.
8+ * Data buffer spanning two pages that will be placed first in the .data
9+ * segment via the linker script. Even if not used internally the second page
10+ * is needed by external test manipulating page permissions, so mark
11+ * encl_buffer as "used" to make sure it is entirely preserved by the compiler.
1112 */
12- static uint8_t encl_buffer [8192 ] = { 1 };
13+ static uint8_t __used __section ( ".data.encl_buffer" ) encl_buffer [8192 ] = { 1 };
1314
1415enum sgx_enclu_function {
1516 EACCEPT = 0x5 ,
@@ -24,10 +25,11 @@ static void do_encl_emodpe(void *_op)
2425 secinfo .flags = op -> flags ;
2526
2627 asm volatile (".byte 0x0f, 0x01, 0xd7"
27- :
28+ : /* no outputs */
2829 : "a" (EMODPE ),
2930 "b" (& secinfo ),
30- "c" (op -> epc_addr ));
31+ "c" (op -> epc_addr )
32+ : "memory" /* read from secinfo pointer */ );
3133}
3234
3335static void do_encl_eaccept (void * _op )
@@ -42,7 +44,8 @@ static void do_encl_eaccept(void *_op)
4244 : "=a" (rax )
4345 : "a" (EACCEPT ),
4446 "b" (& secinfo ),
45- "c" (op -> epc_addr ));
47+ "c" (op -> epc_addr )
48+ : "memory" /* read from secinfo pointer */ );
4649
4750 op -> ret = rax ;
4851}
@@ -119,21 +122,41 @@ static void do_encl_op_nop(void *_op)
119122
120123}
121124
125+ /*
126+ * Symbol placed at the start of the enclave image by the linker script.
127+ * Declare this extern symbol with visibility "hidden" to ensure the compiler
128+ * does not access it through the GOT and generates position-independent
129+ * addressing as __encl_base(%rip), so we can get the actual enclave base
130+ * during runtime.
131+ */
132+ extern const uint8_t __attribute__((visibility ("hidden" ))) __encl_base ;
133+
134+ typedef void (* encl_op_t )(void * );
135+ static const encl_op_t encl_op_array [ENCL_OP_MAX ] = {
136+ do_encl_op_put_to_buf ,
137+ do_encl_op_get_from_buf ,
138+ do_encl_op_put_to_addr ,
139+ do_encl_op_get_from_addr ,
140+ do_encl_op_nop ,
141+ do_encl_eaccept ,
142+ do_encl_emodpe ,
143+ do_encl_init_tcs_page ,
144+ };
145+
122146void encl_body (void * rdi , void * rsi )
123147{
124- const void (* encl_op_array [ENCL_OP_MAX ])(void * ) = {
125- do_encl_op_put_to_buf ,
126- do_encl_op_get_from_buf ,
127- do_encl_op_put_to_addr ,
128- do_encl_op_get_from_addr ,
129- do_encl_op_nop ,
130- do_encl_eaccept ,
131- do_encl_emodpe ,
132- do_encl_init_tcs_page ,
133- };
134-
135- struct encl_op_header * op = (struct encl_op_header * )rdi ;
136-
137- if (op -> type < ENCL_OP_MAX )
138- (* encl_op_array [op -> type ])(op );
148+ struct encl_op_header * header = (struct encl_op_header * )rdi ;
149+ encl_op_t op ;
150+
151+ if (header -> type >= ENCL_OP_MAX )
152+ return ;
153+
154+ /*
155+ * The enclave base address needs to be added, as this call site
156+ * *cannot be* made rip-relative by the compiler, or fixed up by
157+ * any other possible means.
158+ */
159+ op = ((uint64_t )& __encl_base ) + encl_op_array [header -> type ];
160+
161+ (* op )(header );
139162}
0 commit comments