Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'x86_sgx_for_6.8' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 SGX updates from Dave Hansen:
"This time, these are entirely confined to SGX selftests fixes.

The mini SGX enclave built by the selftests has garnered some
attention because it stands alone and does not need the sizable
infrastructure of the official SGX SDK. I think that's why folks are
suddently interested in cleaning it up.

- Clean up selftest compilation issues, mostly from non-gcc compilers

- Avoid building selftests when not on x86"

* tag 'x86_sgx_for_6.8' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
selftests/sgx: Skip non X86_64 platform
selftests/sgx: Remove incomplete ABI sanitization code in test enclave
selftests/sgx: Discard unsupported ELF sections
selftests/sgx: Ensure expected location of test enclave buffer
selftests/sgx: Ensure test enclave buffer is entirely preserved
selftests/sgx: Fix linker script asserts
selftests/sgx: Handle relocations in test enclave
selftests/sgx: Produce static-pie executable for test enclave
selftests/sgx: Remove redundant enclave base address save/restore
selftests/sgx: Specify freestanding environment for enclave compilation
selftests/sgx: Separate linker options
selftests/sgx: Include memory clobber for inline asm in test enclave
selftests/sgx: Fix uninitialized pointer dereferences in encl_get_entry
selftests/sgx: Fix uninitialized pointer dereference in error path

+76 -55
+8 -6
tools/testing/selftests/sgx/Makefile
··· 12 12 endif 13 13 14 14 INCLUDES := -I$(top_srcdir)/tools/include 15 - HOST_CFLAGS := -Wall -Werror -g $(INCLUDES) -fPIC -z noexecstack 16 - ENCL_CFLAGS := -Wall -Werror -static -nostdlib -nostartfiles -fPIC \ 15 + HOST_CFLAGS := -Wall -Werror -g $(INCLUDES) -fPIC 16 + HOST_LDFLAGS := -z noexecstack -lcrypto 17 + ENCL_CFLAGS += -Wall -Werror -static-pie -nostdlib -ffreestanding -fPIE \ 17 18 -fno-stack-protector -mrdrnd $(INCLUDES) 19 + ENCL_LDFLAGS := -Wl,-T,test_encl.lds,--build-id=none 18 20 21 + ifeq ($(CAN_BUILD_X86_64), 1) 19 22 TEST_CUSTOM_PROGS := $(OUTPUT)/test_sgx 20 23 TEST_FILES := $(OUTPUT)/test_encl.elf 21 24 22 - ifeq ($(CAN_BUILD_X86_64), 1) 23 25 all: $(TEST_CUSTOM_PROGS) $(OUTPUT)/test_encl.elf 24 26 endif 25 27 ··· 30 28 $(OUTPUT)/sigstruct.o \ 31 29 $(OUTPUT)/call.o \ 32 30 $(OUTPUT)/sign_key.o 33 - $(CC) $(HOST_CFLAGS) -o $@ $^ -lcrypto 31 + $(CC) $(HOST_CFLAGS) -o $@ $^ $(HOST_LDFLAGS) 34 32 35 33 $(OUTPUT)/main.o: main.c 36 34 $(CC) $(HOST_CFLAGS) -c $< -o $@ ··· 47 45 $(OUTPUT)/sign_key.o: sign_key.S 48 46 $(CC) $(HOST_CFLAGS) -c $< -o $@ 49 47 50 - $(OUTPUT)/test_encl.elf: test_encl.lds test_encl.c test_encl_bootstrap.S 51 - $(CC) $(ENCL_CFLAGS) -T $^ -o $@ -Wl,--build-id=none 48 + $(OUTPUT)/test_encl.elf: test_encl.c test_encl_bootstrap.S 49 + $(CC) $(ENCL_CFLAGS) $^ -o $@ $(ENCL_LDFLAGS) 52 50 53 51 EXTRA_CLEAN := \ 54 52 $(OUTPUT)/test_encl.elf \
+2
tools/testing/selftests/sgx/defines.h
··· 13 13 14 14 #define __aligned(x) __attribute__((__aligned__(x))) 15 15 #define __packed __attribute__((packed)) 16 + #define __used __attribute__((used)) 17 + #define __section(x)__attribute__((__section__(x))) 16 18 17 19 #include "../../../../arch/x86/include/asm/sgx.h" 18 20 #include "../../../../arch/x86/include/asm/enclu.h"
+6 -3
tools/testing/selftests/sgx/load.c
··· 136 136 */ 137 137 uint64_t encl_get_entry(struct encl *encl, const char *symbol) 138 138 { 139 + Elf64_Sym *symtab = NULL; 140 + char *sym_names = NULL; 139 141 Elf64_Shdr *sections; 140 - Elf64_Sym *symtab; 141 142 Elf64_Ehdr *ehdr; 142 - char *sym_names; 143 - int num_sym; 143 + int num_sym = 0; 144 144 int i; 145 145 146 146 ehdr = encl->bin; ··· 160 160 break; 161 161 } 162 162 } 163 + 164 + if (!symtab || !sym_names) 165 + return 0; 163 166 164 167 for (i = 0; i < num_sym; i++) { 165 168 Elf64_Sym *sym = &symtab[i];
+3 -2
tools/testing/selftests/sgx/sigstruct.c
··· 318 318 struct sgx_sigstruct *sigstruct = &encl->sigstruct; 319 319 struct sgx_sigstruct_payload payload; 320 320 uint8_t digest[SHA256_DIGEST_LENGTH]; 321 + EVP_MD_CTX *ctx = NULL; 321 322 unsigned int siglen; 322 323 RSA *key = NULL; 323 - EVP_MD_CTX *ctx; 324 324 int i; 325 325 326 326 memset(sigstruct, 0, sizeof(*sigstruct)); ··· 384 384 return true; 385 385 386 386 err: 387 - EVP_MD_CTX_destroy(ctx); 387 + if (ctx) 388 + EVP_MD_CTX_destroy(ctx); 388 389 RSA_free(key); 389 390 return false; 390 391 }
+43 -20
tools/testing/selftests/sgx/test_encl.c
··· 5 5 #include "defines.h" 6 6 7 7 /* 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. 11 12 */ 12 - static uint8_t encl_buffer[8192] = { 1 }; 13 + static uint8_t __used __section(".data.encl_buffer") encl_buffer[8192] = { 1 }; 13 14 14 15 enum sgx_enclu_function { 15 16 EACCEPT = 0x5, ··· 25 24 secinfo.flags = op->flags; 26 25 27 26 asm volatile(".byte 0x0f, 0x01, 0xd7" 28 - : 27 + : /* no outputs */ 29 28 : "a" (EMODPE), 30 29 "b" (&secinfo), 31 - "c" (op->epc_addr)); 30 + "c" (op->epc_addr) 31 + : "memory" /* read from secinfo pointer */); 32 32 } 33 33 34 34 static void do_encl_eaccept(void *_op) ··· 44 42 : "=a" (rax) 45 43 : "a" (EACCEPT), 46 44 "b" (&secinfo), 47 - "c" (op->epc_addr)); 45 + "c" (op->epc_addr) 46 + : "memory" /* read from secinfo pointer */); 48 47 49 48 op->ret = rax; 50 49 } ··· 122 119 123 120 } 124 121 122 + /* 123 + * Symbol placed at the start of the enclave image by the linker script. 124 + * Declare this extern symbol with visibility "hidden" to ensure the compiler 125 + * does not access it through the GOT and generates position-independent 126 + * addressing as __encl_base(%rip), so we can get the actual enclave base 127 + * during runtime. 128 + */ 129 + extern const uint8_t __attribute__((visibility("hidden"))) __encl_base; 130 + 131 + typedef void (*encl_op_t)(void *); 132 + static const encl_op_t encl_op_array[ENCL_OP_MAX] = { 133 + do_encl_op_put_to_buf, 134 + do_encl_op_get_from_buf, 135 + do_encl_op_put_to_addr, 136 + do_encl_op_get_from_addr, 137 + do_encl_op_nop, 138 + do_encl_eaccept, 139 + do_encl_emodpe, 140 + do_encl_init_tcs_page, 141 + }; 142 + 125 143 void encl_body(void *rdi, void *rsi) 126 144 { 127 - const void (*encl_op_array[ENCL_OP_MAX])(void *) = { 128 - do_encl_op_put_to_buf, 129 - do_encl_op_get_from_buf, 130 - do_encl_op_put_to_addr, 131 - do_encl_op_get_from_addr, 132 - do_encl_op_nop, 133 - do_encl_eaccept, 134 - do_encl_emodpe, 135 - do_encl_init_tcs_page, 136 - }; 145 + struct encl_op_header *header = (struct encl_op_header *)rdi; 146 + encl_op_t op; 137 147 138 - struct encl_op_header *op = (struct encl_op_header *)rdi; 148 + if (header->type >= ENCL_OP_MAX) 149 + return; 139 150 140 - if (op->type < ENCL_OP_MAX) 141 - (*encl_op_array[op->type])(op); 151 + /* 152 + * The enclave base address needs to be added, as this call site 153 + * *cannot be* made rip-relative by the compiler, or fixed up by 154 + * any other possible means. 155 + */ 156 + op = ((uint64_t)&__encl_base) + encl_op_array[header->type]; 157 + 158 + (*op)(header); 142 159 }
+5 -5
tools/testing/selftests/sgx/test_encl.lds
··· 10 10 SECTIONS 11 11 { 12 12 . = 0; 13 + __encl_base = .; 13 14 .tcs : { 14 15 *(.tcs*) 15 16 } : tcs ··· 24 23 } : text 25 24 26 25 .data : { 26 + *(.data.encl_buffer) 27 27 *(.data*) 28 28 } : data 29 29 ··· 33 31 *(.note*) 34 32 *(.debug*) 35 33 *(.eh_frame*) 34 + *(.dyn*) 35 + *(.gnu.hash) 36 36 } 37 37 } 38 38 39 - ASSERT(!DEFINED(.altinstructions), "ALTERNATIVES are not supported in enclaves") 40 - ASSERT(!DEFINED(.altinstr_replacement), "ALTERNATIVES are not supported in enclaves") 41 - ASSERT(!DEFINED(.discard.retpoline_safe), "RETPOLINE ALTERNATIVES are not supported in enclaves") 42 - ASSERT(!DEFINED(.discard.nospec), "RETPOLINE ALTERNATIVES are not supported in enclaves") 43 - ASSERT(!DEFINED(.got.plt), "Libcalls are not supported in enclaves") 39 + ASSERT(!DEFINED(_GLOBAL_OFFSET_TABLE_), "Libcalls through GOT are not supported in enclaves")
+9 -19
tools/testing/selftests/sgx/test_encl_bootstrap.S
··· 42 42 encl_entry: 43 43 # RBX contains the base address for TCS, which is the first address 44 44 # inside the enclave for TCS #1 and one page into the enclave for 45 - # TCS #2. By adding the value of encl_stack to it, we get 46 - # the absolute address for the stack. 47 - lea (encl_stack)(%rbx), %rax 45 + # TCS #2. First make it relative by substracting __encl_base and 46 + # then add the address of encl_stack to get the address for the stack. 47 + lea __encl_base(%rip), %rax 48 + sub %rax, %rbx 49 + lea encl_stack(%rip), %rax 50 + add %rbx, %rax 48 51 jmp encl_entry_core 49 52 encl_dyn_entry: 50 53 # Entry point for dynamically created TCS page expected to follow ··· 58 55 push %rax 59 56 60 57 push %rcx # push the address after EENTER 61 - push %rbx # push the enclave base address 62 58 59 + # NOTE: as the selftest enclave is *not* intended for production, 60 + # simplify the code by not initializing ABI registers on entry or 61 + # cleansing caller-save registers on exit. 63 62 call encl_body 64 - 65 - pop %rbx # pop the enclave base address 66 - 67 - /* Clear volatile GPRs, except RAX (EEXIT function). */ 68 - xor %rcx, %rcx 69 - xor %rdx, %rdx 70 - xor %rdi, %rdi 71 - xor %rsi, %rsi 72 - xor %r8, %r8 73 - xor %r9, %r9 74 - xor %r10, %r10 75 - xor %r11, %r11 76 - 77 - # Reset status flags. 78 - add %rdx, %rdx # OF = SF = AF = CF = 0; ZF = PF = 1 79 63 80 64 # Prepare EEXIT target by popping the address of the instruction after 81 65 # EENTER to RBX.