Skip to content

Commit

Permalink
Merge tag 'x86_sgx_for_6.8' of git://git.kernel.org/pub/scm/linux/ker…
Browse files Browse the repository at this point in the history
…nel/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
  • Loading branch information
torvalds committed Jan 18, 2024
2 parents b0d326d + 981cf56 commit ba7dd85
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 57 deletions.
14 changes: 8 additions & 6 deletions tools/testing/selftests/sgx/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@ OBJCOPY := $(CROSS_COMPILE)objcopy
endif

INCLUDES := -I$(top_srcdir)/tools/include
HOST_CFLAGS := -Wall -Werror -g $(INCLUDES) -fPIC -z noexecstack
ENCL_CFLAGS := -Wall -Werror -static -nostdlib -nostartfiles -fPIC \
HOST_CFLAGS := -Wall -Werror -g $(INCLUDES) -fPIC
HOST_LDFLAGS := -z noexecstack -lcrypto
ENCL_CFLAGS += -Wall -Werror -static-pie -nostdlib -ffreestanding -fPIE \
-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_FILES := $(OUTPUT)/test_encl.elf

ifeq ($(CAN_BUILD_X86_64), 1)
all: $(TEST_CUSTOM_PROGS) $(OUTPUT)/test_encl.elf
endif

Expand All @@ -28,7 +30,7 @@ $(OUTPUT)/test_sgx: $(OUTPUT)/main.o \
$(OUTPUT)/sigstruct.o \
$(OUTPUT)/call.o \
$(OUTPUT)/sign_key.o
$(CC) $(HOST_CFLAGS) -o $@ $^ -lcrypto
$(CC) $(HOST_CFLAGS) -o $@ $^ $(HOST_LDFLAGS)

$(OUTPUT)/main.o: main.c
$(CC) $(HOST_CFLAGS) -c $< -o $@
Expand All @@ -45,8 +47,8 @@ $(OUTPUT)/call.o: call.S
$(OUTPUT)/sign_key.o: sign_key.S
$(CC) $(HOST_CFLAGS) -c $< -o $@

$(OUTPUT)/test_encl.elf: test_encl.lds test_encl.c test_encl_bootstrap.S
$(CC) $(ENCL_CFLAGS) -T $^ -o $@ -Wl,--build-id=none
$(OUTPUT)/test_encl.elf: test_encl.c test_encl_bootstrap.S
$(CC) $(ENCL_CFLAGS) $^ -o $@ $(ENCL_LDFLAGS)

EXTRA_CLEAN := \
$(OUTPUT)/test_encl.elf \
Expand Down
2 changes: 2 additions & 0 deletions tools/testing/selftests/sgx/defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

#define __aligned(x) __attribute__((__aligned__(x)))
#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/enclu.h"
Expand Down
9 changes: 6 additions & 3 deletions tools/testing/selftests/sgx/load.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Elf64_Sym *symtab = NULL;
char *sym_names = NULL;
Elf64_Shdr *sections;
Elf64_Sym *symtab;
Elf64_Ehdr *ehdr;
char *sym_names;
int num_sym;
int num_sym = 0;
int i;

ehdr = encl->bin;
Expand All @@ -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++) {
Elf64_Sym *sym = &symtab[i];

Expand Down
5 changes: 3 additions & 2 deletions tools/testing/selftests/sgx/sigstruct.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,9 +318,9 @@ bool encl_measure(struct encl *encl)
struct sgx_sigstruct *sigstruct = &encl->sigstruct;
struct sgx_sigstruct_payload payload;
uint8_t digest[SHA256_DIGEST_LENGTH];
EVP_MD_CTX *ctx = NULL;
unsigned int siglen;
RSA *key = NULL;
EVP_MD_CTX *ctx;
int i;

memset(sigstruct, 0, sizeof(*sigstruct));
Expand Down Expand Up @@ -384,7 +384,8 @@ bool encl_measure(struct encl *encl)
return true;

err:
EVP_MD_CTX_destroy(ctx);
if (ctx)
EVP_MD_CTX_destroy(ctx);
RSA_free(key);
return false;
}
67 changes: 45 additions & 22 deletions tools/testing/selftests/sgx/test_encl.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
#include "defines.h"

/*
* Data buffer spanning two pages that will be placed first in .data
* segment. Even if not used internally the second page is needed by
* external test manipulating page permissions.
* Data buffer spanning two pages that will be placed first in the .data
* segment via the linker script. Even if not used internally the second page
* 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 {
EACCEPT = 0x5,
Expand All @@ -24,10 +25,11 @@ static void do_encl_emodpe(void *_op)
secinfo.flags = op->flags;

asm volatile(".byte 0x0f, 0x01, 0xd7"
:
: /* no outputs */
: "a" (EMODPE),
"b" (&secinfo),
"c" (op->epc_addr));
"c" (op->epc_addr)
: "memory" /* read from secinfo pointer */);
}

static void do_encl_eaccept(void *_op)
Expand All @@ -42,7 +44,8 @@ static void do_encl_eaccept(void *_op)
: "=a" (rax)
: "a" (EACCEPT),
"b" (&secinfo),
"c" (op->epc_addr));
"c" (op->epc_addr)
: "memory" /* read from secinfo pointer */);

op->ret = rax;
}
Expand Down Expand Up @@ -119,21 +122,41 @@ 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 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_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;

if (op->type < ENCL_OP_MAX)
(*encl_op_array[op->type])(op);
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];

(*op)(header);
}
10 changes: 5 additions & 5 deletions tools/testing/selftests/sgx/test_encl.lds
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ PHDRS
SECTIONS
{
. = 0;
__encl_base = .;
.tcs : {
*(.tcs*)
} : tcs
Expand All @@ -23,6 +24,7 @@ SECTIONS
} : text

.data : {
*(.data.encl_buffer)
*(.data*)
} : data

Expand All @@ -31,11 +33,9 @@ SECTIONS
*(.note*)
*(.debug*)
*(.eh_frame*)
*(.dyn*)
*(.gnu.hash)
}
}

ASSERT(!DEFINED(.altinstructions), "ALTERNATIVES 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")
ASSERT(!DEFINED(_GLOBAL_OFFSET_TABLE_), "Libcalls through GOT are not supported in enclaves")
28 changes: 9 additions & 19 deletions tools/testing/selftests/sgx/test_encl_bootstrap.S
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,12 @@
encl_entry:
# 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
# TCS #2. By adding the value of encl_stack to it, we get
# the absolute address for the stack.
lea (encl_stack)(%rbx), %rax
# TCS #2. First make it relative by substracting __encl_base and
# then add the address of encl_stack to get the address for the stack.
lea __encl_base(%rip), %rax
sub %rax, %rbx
lea encl_stack(%rip), %rax
add %rbx, %rax
jmp encl_entry_core
encl_dyn_entry:
# Entry point for dynamically created TCS page expected to follow
Expand All @@ -55,25 +58,12 @@ encl_entry_core:
push %rax

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

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
# EENTER to RBX.
pop %rbx
Expand Down

0 comments on commit ba7dd85

Please sign in to comment.