Commit ba7dd857 authored by Linus Torvalds's avatar Linus Torvalds

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
parents b0d326da 981cf568
...@@ -12,14 +12,16 @@ OBJCOPY := $(CROSS_COMPILE)objcopy ...@@ -12,14 +12,16 @@ OBJCOPY := $(CROSS_COMPILE)objcopy
endif endif
INCLUDES := -I$(top_srcdir)/tools/include INCLUDES := -I$(top_srcdir)/tools/include
HOST_CFLAGS := -Wall -Werror -g $(INCLUDES) -fPIC -z noexecstack HOST_CFLAGS := -Wall -Werror -g $(INCLUDES) -fPIC
ENCL_CFLAGS := -Wall -Werror -static -nostdlib -nostartfiles -fPIC \ HOST_LDFLAGS := -z noexecstack -lcrypto
ENCL_CFLAGS += -Wall -Werror -static-pie -nostdlib -ffreestanding -fPIE \
-fno-stack-protector -mrdrnd $(INCLUDES) -fno-stack-protector -mrdrnd $(INCLUDES)
ENCL_LDFLAGS := -Wl,-T,test_encl.lds,--build-id=none
ifeq ($(CAN_BUILD_X86_64), 1)
TEST_CUSTOM_PROGS := $(OUTPUT)/test_sgx TEST_CUSTOM_PROGS := $(OUTPUT)/test_sgx
TEST_FILES := $(OUTPUT)/test_encl.elf TEST_FILES := $(OUTPUT)/test_encl.elf
ifeq ($(CAN_BUILD_X86_64), 1)
all: $(TEST_CUSTOM_PROGS) $(OUTPUT)/test_encl.elf all: $(TEST_CUSTOM_PROGS) $(OUTPUT)/test_encl.elf
endif endif
...@@ -28,7 +30,7 @@ $(OUTPUT)/test_sgx: $(OUTPUT)/main.o \ ...@@ -28,7 +30,7 @@ $(OUTPUT)/test_sgx: $(OUTPUT)/main.o \
$(OUTPUT)/sigstruct.o \ $(OUTPUT)/sigstruct.o \
$(OUTPUT)/call.o \ $(OUTPUT)/call.o \
$(OUTPUT)/sign_key.o $(OUTPUT)/sign_key.o
$(CC) $(HOST_CFLAGS) -o $@ $^ -lcrypto $(CC) $(HOST_CFLAGS) -o $@ $^ $(HOST_LDFLAGS)
$(OUTPUT)/main.o: main.c $(OUTPUT)/main.o: main.c
$(CC) $(HOST_CFLAGS) -c $< -o $@ $(CC) $(HOST_CFLAGS) -c $< -o $@
...@@ -45,8 +47,8 @@ $(OUTPUT)/call.o: call.S ...@@ -45,8 +47,8 @@ $(OUTPUT)/call.o: call.S
$(OUTPUT)/sign_key.o: sign_key.S $(OUTPUT)/sign_key.o: sign_key.S
$(CC) $(HOST_CFLAGS) -c $< -o $@ $(CC) $(HOST_CFLAGS) -c $< -o $@
$(OUTPUT)/test_encl.elf: test_encl.lds test_encl.c test_encl_bootstrap.S $(OUTPUT)/test_encl.elf: test_encl.c test_encl_bootstrap.S
$(CC) $(ENCL_CFLAGS) -T $^ -o $@ -Wl,--build-id=none $(CC) $(ENCL_CFLAGS) $^ -o $@ $(ENCL_LDFLAGS)
EXTRA_CLEAN := \ EXTRA_CLEAN := \
$(OUTPUT)/test_encl.elf \ $(OUTPUT)/test_encl.elf \
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
#define __aligned(x) __attribute__((__aligned__(x))) #define __aligned(x) __attribute__((__aligned__(x)))
#define __packed __attribute__((packed)) #define __packed __attribute__((packed))
#define __used __attribute__((used))
#define __section(x)__attribute__((__section__(x)))
#include "../../../../arch/x86/include/asm/sgx.h" #include "../../../../arch/x86/include/asm/sgx.h"
#include "../../../../arch/x86/include/asm/enclu.h" #include "../../../../arch/x86/include/asm/enclu.h"
......
...@@ -136,11 +136,11 @@ static bool encl_ioc_add_pages(struct encl *encl, struct encl_segment *seg) ...@@ -136,11 +136,11 @@ static bool encl_ioc_add_pages(struct encl *encl, struct encl_segment *seg)
*/ */
uint64_t encl_get_entry(struct encl *encl, const char *symbol) uint64_t encl_get_entry(struct encl *encl, const char *symbol)
{ {
Elf64_Sym *symtab = NULL;
char *sym_names = NULL;
Elf64_Shdr *sections; Elf64_Shdr *sections;
Elf64_Sym *symtab;
Elf64_Ehdr *ehdr; Elf64_Ehdr *ehdr;
char *sym_names; int num_sym = 0;
int num_sym;
int i; int i;
ehdr = encl->bin; ehdr = encl->bin;
...@@ -161,6 +161,9 @@ uint64_t encl_get_entry(struct encl *encl, const char *symbol) ...@@ -161,6 +161,9 @@ uint64_t encl_get_entry(struct encl *encl, const char *symbol)
} }
} }
if (!symtab || !sym_names)
return 0;
for (i = 0; i < num_sym; i++) { for (i = 0; i < num_sym; i++) {
Elf64_Sym *sym = &symtab[i]; Elf64_Sym *sym = &symtab[i];
......
...@@ -318,9 +318,9 @@ bool encl_measure(struct encl *encl) ...@@ -318,9 +318,9 @@ bool encl_measure(struct encl *encl)
struct sgx_sigstruct *sigstruct = &encl->sigstruct; struct sgx_sigstruct *sigstruct = &encl->sigstruct;
struct sgx_sigstruct_payload payload; struct sgx_sigstruct_payload payload;
uint8_t digest[SHA256_DIGEST_LENGTH]; uint8_t digest[SHA256_DIGEST_LENGTH];
EVP_MD_CTX *ctx = NULL;
unsigned int siglen; unsigned int siglen;
RSA *key = NULL; RSA *key = NULL;
EVP_MD_CTX *ctx;
int i; int i;
memset(sigstruct, 0, sizeof(*sigstruct)); memset(sigstruct, 0, sizeof(*sigstruct));
...@@ -384,6 +384,7 @@ bool encl_measure(struct encl *encl) ...@@ -384,6 +384,7 @@ bool encl_measure(struct encl *encl)
return true; return true;
err: err:
if (ctx)
EVP_MD_CTX_destroy(ctx); EVP_MD_CTX_destroy(ctx);
RSA_free(key); RSA_free(key);
return false; return false;
......
...@@ -5,11 +5,12 @@ ...@@ -5,11 +5,12 @@
#include "defines.h" #include "defines.h"
/* /*
* Data buffer spanning two pages that will be placed first in .data * Data buffer spanning two pages that will be placed first in the .data
* segment. Even if not used internally the second page is needed by * segment via the linker script. Even if not used internally the second page
* external test manipulating page permissions. * is needed by external test manipulating page permissions, so mark
* encl_buffer as "used" to make sure it is entirely preserved by the compiler.
*/ */
static uint8_t encl_buffer[8192] = { 1 }; static uint8_t __used __section(".data.encl_buffer") encl_buffer[8192] = { 1 };
enum sgx_enclu_function { enum sgx_enclu_function {
EACCEPT = 0x5, EACCEPT = 0x5,
...@@ -24,10 +25,11 @@ static void do_encl_emodpe(void *_op) ...@@ -24,10 +25,11 @@ static void do_encl_emodpe(void *_op)
secinfo.flags = op->flags; secinfo.flags = op->flags;
asm volatile(".byte 0x0f, 0x01, 0xd7" asm volatile(".byte 0x0f, 0x01, 0xd7"
: : /* no outputs */
: "a" (EMODPE), : "a" (EMODPE),
"b" (&secinfo), "b" (&secinfo),
"c" (op->epc_addr)); "c" (op->epc_addr)
: "memory" /* read from secinfo pointer */);
} }
static void do_encl_eaccept(void *_op) static void do_encl_eaccept(void *_op)
...@@ -42,7 +44,8 @@ static void do_encl_eaccept(void *_op) ...@@ -42,7 +44,8 @@ static void do_encl_eaccept(void *_op)
: "=a" (rax) : "=a" (rax)
: "a" (EACCEPT), : "a" (EACCEPT),
"b" (&secinfo), "b" (&secinfo),
"c" (op->epc_addr)); "c" (op->epc_addr)
: "memory" /* read from secinfo pointer */);
op->ret = rax; op->ret = rax;
} }
...@@ -119,9 +122,17 @@ static void do_encl_op_nop(void *_op) ...@@ -119,9 +122,17 @@ static void do_encl_op_nop(void *_op)
} }
void encl_body(void *rdi, void *rsi) /*
{ * Symbol placed at the start of the enclave image by the linker script.
const void (*encl_op_array[ENCL_OP_MAX])(void *) = { * Declare this extern symbol with visibility "hidden" to ensure the compiler
* does not access it through the GOT and generates position-independent
* addressing as __encl_base(%rip), so we can get the actual enclave base
* during runtime.
*/
extern const uint8_t __attribute__((visibility("hidden"))) __encl_base;
typedef void (*encl_op_t)(void *);
static const encl_op_t encl_op_array[ENCL_OP_MAX] = {
do_encl_op_put_to_buf, do_encl_op_put_to_buf,
do_encl_op_get_from_buf, do_encl_op_get_from_buf,
do_encl_op_put_to_addr, do_encl_op_put_to_addr,
...@@ -130,10 +141,22 @@ void encl_body(void *rdi, void *rsi) ...@@ -130,10 +141,22 @@ void encl_body(void *rdi, void *rsi)
do_encl_eaccept, do_encl_eaccept,
do_encl_emodpe, do_encl_emodpe,
do_encl_init_tcs_page, do_encl_init_tcs_page,
}; };
struct encl_op_header *op = (struct encl_op_header *)rdi; void encl_body(void *rdi, void *rsi)
{
struct encl_op_header *header = (struct encl_op_header *)rdi;
encl_op_t op;
if (header->type >= ENCL_OP_MAX)
return;
/*
* The enclave base address needs to be added, as this call site
* *cannot be* made rip-relative by the compiler, or fixed up by
* any other possible means.
*/
op = ((uint64_t)&__encl_base) + encl_op_array[header->type];
if (op->type < ENCL_OP_MAX) (*op)(header);
(*encl_op_array[op->type])(op);
} }
...@@ -10,6 +10,7 @@ PHDRS ...@@ -10,6 +10,7 @@ PHDRS
SECTIONS SECTIONS
{ {
. = 0; . = 0;
__encl_base = .;
.tcs : { .tcs : {
*(.tcs*) *(.tcs*)
} : tcs } : tcs
...@@ -23,6 +24,7 @@ SECTIONS ...@@ -23,6 +24,7 @@ SECTIONS
} : text } : text
.data : { .data : {
*(.data.encl_buffer)
*(.data*) *(.data*)
} : data } : data
...@@ -31,11 +33,9 @@ SECTIONS ...@@ -31,11 +33,9 @@ SECTIONS
*(.note*) *(.note*)
*(.debug*) *(.debug*)
*(.eh_frame*) *(.eh_frame*)
*(.dyn*)
*(.gnu.hash)
} }
} }
ASSERT(!DEFINED(.altinstructions), "ALTERNATIVES are not supported in enclaves") ASSERT(!DEFINED(_GLOBAL_OFFSET_TABLE_), "Libcalls through GOT are not supported in enclaves")
ASSERT(!DEFINED(.altinstr_replacement), "ALTERNATIVES are not supported in enclaves")
ASSERT(!DEFINED(.discard.retpoline_safe), "RETPOLINE ALTERNATIVES are not supported in enclaves")
ASSERT(!DEFINED(.discard.nospec), "RETPOLINE ALTERNATIVES are not supported in enclaves")
ASSERT(!DEFINED(.got.plt), "Libcalls are not supported in enclaves")
...@@ -42,9 +42,12 @@ ...@@ -42,9 +42,12 @@
encl_entry: encl_entry:
# RBX contains the base address for TCS, which is the first address # RBX contains the base address for TCS, which is the first address
# inside the enclave for TCS #1 and one page into the enclave for # inside the enclave for TCS #1 and one page into the enclave for
# TCS #2. By adding the value of encl_stack to it, we get # TCS #2. First make it relative by substracting __encl_base and
# the absolute address for the stack. # then add the address of encl_stack to get the address for the stack.
lea (encl_stack)(%rbx), %rax lea __encl_base(%rip), %rax
sub %rax, %rbx
lea encl_stack(%rip), %rax
add %rbx, %rax
jmp encl_entry_core jmp encl_entry_core
encl_dyn_entry: encl_dyn_entry:
# Entry point for dynamically created TCS page expected to follow # Entry point for dynamically created TCS page expected to follow
...@@ -55,25 +58,12 @@ encl_entry_core: ...@@ -55,25 +58,12 @@ encl_entry_core:
push %rax push %rax
push %rcx # push the address after EENTER push %rcx # push the address after EENTER
push %rbx # push the enclave base address
# NOTE: as the selftest enclave is *not* intended for production,
# simplify the code by not initializing ABI registers on entry or
# cleansing caller-save registers on exit.
call encl_body call encl_body
pop %rbx # pop the enclave base address
/* Clear volatile GPRs, except RAX (EEXIT function). */
xor %rcx, %rcx
xor %rdx, %rdx
xor %rdi, %rdi
xor %rsi, %rsi
xor %r8, %r8
xor %r9, %r9
xor %r10, %r10
xor %r11, %r11
# Reset status flags.
add %rdx, %rdx # OF = SF = AF = CF = 0; ZF = PF = 1
# Prepare EEXIT target by popping the address of the instruction after # Prepare EEXIT target by popping the address of the instruction after
# EENTER to RBX. # EENTER to RBX.
pop %rbx pop %rbx
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment