From patchwork Mon Apr 22 20:42:57 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Xing, Cedric" X-Patchwork-Id: 10911609 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3163F13B5 for ; Mon, 22 Apr 2019 20:43:02 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 269D32871C for ; Mon, 22 Apr 2019 20:43:02 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 19BC72875F; Mon, 22 Apr 2019 20:43:02 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7D8652871C for ; Mon, 22 Apr 2019 20:43:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727685AbfDVUnB (ORCPT ); Mon, 22 Apr 2019 16:43:01 -0400 Received: from mga18.intel.com ([134.134.136.126]:62703 "EHLO mga18.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726421AbfDVUnB (ORCPT ); Mon, 22 Apr 2019 16:43:01 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 22 Apr 2019 13:43:00 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.60,383,1549958400"; d="scan'208";a="144785995" Received: from bxing-ubuntu.jf.intel.com ([10.23.30.27]) by orsmga003.jf.intel.com with ESMTP; 22 Apr 2019 13:42:59 -0700 From: Cedric Xing To: linux-sgx@vger.kernel.org Cc: cedric.xing@intel.com Subject: [RFC PATCH v1 1/3] selftests/x86: Fixed Makefile for SGX selftest Date: Mon, 22 Apr 2019 13:42:57 -0700 Message-Id: <4e463af695c92b6b5693b1f0d00a49b21fbf4656.1555965327.git.cedric.xing@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: References: In-Reply-To: References: <20190417103938.7762-1-jarkko.sakkinen@linux.intel.com> Sender: linux-sgx-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sgx@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The original x86/sgx/Makefile doesn't work when 'x86/sgx' is specified as the test target. This patch fixes that problem, along with minor changes to the dependencies between 'x86' and 'x86/sgx' in selftests/x86/Makefile. Signed-off-by: Cedric Xing --- tools/testing/selftests/x86/Makefile | 12 +++---- tools/testing/selftests/x86/sgx/Makefile | 45 +++++++++--------------- 2 files changed, 22 insertions(+), 35 deletions(-) diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile index 4fc9a42f56ea..1294c5f5b6ca 100644 --- a/tools/testing/selftests/x86/Makefile +++ b/tools/testing/selftests/x86/Makefile @@ -70,11 +70,11 @@ all_32: $(BINARIES_32) all_64: $(BINARIES_64) -all_64: $(SUBDIRS_64) - @for DIR in $(SUBDIRS_64); do \ - BUILD_TARGET=$(OUTPUT)/$$DIR; \ - mkdir $$BUILD_TARGET -p; \ - make OUTPUT=$$BUILD_TARGET -C $$DIR $@; \ +all_64: | $(SUBDIRS_64) + @for DIR in $|; do \ + BUILD_TARGET=$(OUTPUT)/$$DIR; \ + mkdir $$BUILD_TARGET -p; \ + $(MAKE) OUTPUT=$$BUILD_TARGET -C $$DIR $@; \ done EXTRA_CLEAN := $(BINARIES_32) $(BINARIES_64) @@ -90,7 +90,7 @@ ifeq ($(CAN_BUILD_I386)$(CAN_BUILD_X86_64),01) all: warn_32bit_failure warn_32bit_failure: - @echo "Warning: you seem to have a broken 32-bit build" 2>&1; \ + @echo "Warning: you seem to have a broken 32-bit build" 2>&1; \ echo "environment. This will reduce test coverage of 64-bit" 2>&1; \ echo "kernels. If you are using a Debian-like distribution," 2>&1; \ echo "try:"; 2>&1; \ diff --git a/tools/testing/selftests/x86/sgx/Makefile b/tools/testing/selftests/x86/sgx/Makefile index 1fd6f2708e81..3af15d7c8644 100644 --- a/tools/testing/selftests/x86/sgx/Makefile +++ b/tools/testing/selftests/x86/sgx/Makefile @@ -2,47 +2,34 @@ top_srcdir = ../../../../.. include ../../lib.mk -HOST_CFLAGS := -Wall -Werror -g $(INCLUDES) -fPIC -ENCL_CFLAGS := -Wall -Werror -static -nostdlib -nostartfiles -fPIC \ +ifeq ($(shell $(CC) -dumpmachine | cut --delimiter=- -f1),x86_64) +all: all_64 +endif + +HOST_CFLAGS := -Wall -Werror -g $(INCLUDES) +ENCL_CFLAGS := -Wall -Werror -static -nostdlib -nostartfiles -fPIE \ -fno-stack-protector -mrdrnd $(INCLUDES) TEST_CUSTOM_PROGS := $(OUTPUT)/test_sgx all_64: $(TEST_CUSTOM_PROGS) -$(TEST_CUSTOM_PROGS): $(OUTPUT)/main.o $(OUTPUT)/sgx_call.o \ - $(OUTPUT)/encl_piggy.o +$(TEST_CUSTOM_PROGS): main.c sgx_call.S $(OUTPUT)/encl_piggy.o $(CC) $(HOST_CFLAGS) -o $@ $^ -$(OUTPUT)/main.o: main.c - $(CC) $(HOST_CFLAGS) -c $< -o $@ +$(OUTPUT)/encl_piggy.o: encl_piggy.S $(OUTPUT)/encl.bin $(OUTPUT)/encl.ss + $(CC) $(HOST_CFLAGS) -I$(OUTPUT) -c $< -o $@ -$(OUTPUT)/sgx_call.o: sgx_call.S - $(CC) $(HOST_CFLAGS) -c $< -o $@ - -$(OUTPUT)/encl_piggy.o: $(OUTPUT)/encl.bin $(OUTPUT)/encl.ss - $(CC) $(HOST_CFLAGS) -c encl_piggy.S -o $@ - -$(OUTPUT)/encl.bin: $(OUTPUT)/encl.elf $(OUTPUT)/sgxsign +$(OUTPUT)/encl.bin: $(OUTPUT)/encl.elf objcopy --remove-section=.got.plt -O binary $< $@ -$(OUTPUT)/encl.elf: $(OUTPUT)/encl.o $(OUTPUT)/encl_bootstrap.o - $(CC) $(ENCL_CFLAGS) -T encl.lds -o $@ $^ +$(OUTPUT)/encl.elf: encl.lds encl.c encl_bootstrap.S + $(CC) $(ENCL_CFLAGS) -T $^ -o $@ -$(OUTPUT)/encl.o: encl.c - $(CC) $(ENCL_CFLAGS) -c $< -o $@ - -$(OUTPUT)/encl_bootstrap.o: encl_bootstrap.S - $(CC) $(ENCL_CFLAGS) -c $< -o $@ - -$(OUTPUT)/encl.ss: $(OUTPUT)/encl.bin $(OUTPUT)/sgxsign - $(OUTPUT)/sgxsign signing_key.pem $(OUTPUT)/encl.bin $(OUTPUT)/encl.ss +$(OUTPUT)/encl.ss: $(OUTPUT)/sgxsign signing_key.pem $(OUTPUT)/encl.bin + $^ $@ $(OUTPUT)/sgxsign: sgxsign.c $(CC) -o $@ $< -lcrypto -EXTRA_CLEAN := $(OUTPUT)/sgx-selftest $(OUTPUT)/sgx-selftest.o \ - $(OUTPUT)/sgx_call.o $(OUTPUT)/encl.bin $(OUTPUT)/encl.ss \ - $(OUTPUT)/encl.elf $(OUTPUT)/encl.o $(OUTPUT)/encl_bootstrap.o \ - $(OUTPUT)/sgxsign - -.PHONY: clean +EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(addprefix $(OUTPUT)/, \ + encl.elf encl.bin encl.ss encl_piggy.o sgxsign) From patchwork Mon Apr 22 20:42:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Xing, Cedric" X-Patchwork-Id: 10911613 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 38BEE186D for ; Mon, 22 Apr 2019 20:43:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2DADE2871C for ; Mon, 22 Apr 2019 20:43:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 224952873A; Mon, 22 Apr 2019 20:43:03 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B6CB228721 for ; Mon, 22 Apr 2019 20:43:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728552AbfDVUnB (ORCPT ); Mon, 22 Apr 2019 16:43:01 -0400 Received: from mga18.intel.com ([134.134.136.126]:62703 "EHLO mga18.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727571AbfDVUnB (ORCPT ); Mon, 22 Apr 2019 16:43:01 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 22 Apr 2019 13:43:00 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.60,383,1549958400"; d="scan'208";a="144785999" Received: from bxing-ubuntu.jf.intel.com ([10.23.30.27]) by orsmga003.jf.intel.com with ESMTP; 22 Apr 2019 13:43:00 -0700 From: Cedric Xing To: linux-sgx@vger.kernel.org Cc: cedric.xing@intel.com Subject: [RFC PATCH v1 2/3] x86/vdso: Modify __vdso_sgx_enter_enclave() to allow parameter passing on untrusted stack Date: Mon, 22 Apr 2019 13:42:58 -0700 Message-Id: X-Mailer: git-send-email 2.17.1 In-Reply-To: References: In-Reply-To: References: <20190417103938.7762-1-jarkko.sakkinen@linux.intel.com> Sender: linux-sgx-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sgx@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The previous __vdso_sgx_enter_enclave() requires enclaves to preserve %rsp, which prohibits enclaves from allocating and passing parameters for untrusted function calls (aka. o-calls). This patch addresses the problem above by introducing a new ABI that preserves %rbp instead of %rsp. Then __vdso_sgx_enter_enclave() can anchor its frame using %rbp so that enclaves are allowed to allocate space on the untrusted stack by decrementing %rsp. Please note that the stack space allocated in such way will be part of __vdso_sgx_enter_enclave()'s frame so will be freed after __vdso_sgx_enter_enclave() returns. Therefore, __vdso_sgx_enter_enclave() has been changed to take a callback function as an optional parameter, which if supplied, will be invoked upon enclave exits (both AEX (Asynchronous Enclave eXit) and normal exits), with the value of %rsp left off by the enclave as a parameter to the callback. Here's the summary of API/ABI changes in this patch. More details could be found in arch/x86/entry/vdso/vsgx_enter_enclave.S. * 'struct sgx_enclave_exception' is renamed to 'struct sgx_enclave_exinfo' because it is filled upon both AEX (i.e. exceptions) and normal enclave exits. * __vdso_sgx_enter_enclave() anchors its frame using %rbp (instead of %rsp in the previous implementation). * __vdso_sgx_enter_enclave() takes one more parameter - a callback function to be invoked upon enclave exits. This callback is optional, and if not supplied, will cause __vdso_sgx_enter_enclave() to return upon enclave exits (same behavior as previous implementation). * The callback function is given as a parameter the value of %rsp at enclave exit to address data "pushed" by the enclave. A positive value returned by the callback will be treated as an ENCLU leaf for re-entering the enclave, while a zero or negative value will be passed through as the return value of __vdso_sgx_enter_enclave() to its caller. It's also safe to leave callback by longjmp() or by throwing a C++ exception. Signed-off-by: Cedric Xing --- arch/x86/entry/vdso/vsgx_enter_enclave.S | 156 ++++++++++++++--------- arch/x86/include/uapi/asm/sgx.h | 14 +- 2 files changed, 100 insertions(+), 70 deletions(-) diff --git a/arch/x86/entry/vdso/vsgx_enter_enclave.S b/arch/x86/entry/vdso/vsgx_enter_enclave.S index fe0bf6671d6d..210f4366374a 100644 --- a/arch/x86/entry/vdso/vsgx_enter_enclave.S +++ b/arch/x86/entry/vdso/vsgx_enter_enclave.S @@ -14,88 +14,118 @@ .code64 .section .text, "ax" -#ifdef SGX_KERNEL_DOC /** * __vdso_sgx_enter_enclave() - Enter an SGX enclave * * @leaf: **IN \%eax** - ENCLU leaf, must be EENTER or ERESUME - * @tcs: **IN \%rbx** - TCS, must be non-NULL - * @ex_info: **IN \%rcx** - Optional 'struct sgx_enclave_exception' pointer + * @tcs: **IN 0x08(\%rsp)** - TCS, must be non-NULL + * @ex_info: **IN 0x10(\%rsp)** - Optional 'struct sgx_enclave_exinfo' + * pointer + * @callback: **IN 0x18(\%rsp)** - Optional callback function to be called on + * enclave exit or exception * * Return: * **OUT \%eax** - - * %0 on a clean entry/exit to/from the enclave, %-EINVAL if ENCLU leaf is - * not allowed or if TCS is NULL, %-EFAULT if ENCLU or the enclave faults + * %0 on a clean entry/exit to/from the enclave, %-EINVAL if ENCLU leaf is not + * allowed, %-EFAULT if ENCLU or the enclave faults, or a non-positive value + * returned from ``callback`` (if one is supplied). * * **Important!** __vdso_sgx_enter_enclave() is **NOT** compliant with the - * x86-64 ABI, i.e. cannot be called from standard C code. As noted above, - * input parameters must be passed via ``%eax``, ``%rbx`` and ``%rcx``, with - * the return value passed via ``%eax``. All registers except ``%rsp`` must - * be treated as volatile from the caller's perspective, including but not - * limited to GPRs, EFLAGS.DF, MXCSR, FCW, etc... Conversely, the enclave - * being run **must** preserve the untrusted ``%rsp`` and stack. + * x86-64 ABI, i.e. cannot be called from standard C code. As noted above, + * input parameters must be passed via ``%eax``, ``8(%rsp)``, ``0x10(%rsp)`` and + * ``0x18(%rsp)``, with the return value passed via ``%eax``. All other registers + * will be passed through to the enclave as is. All registers except ``%rbp`` + * must be treated as volatile from the caller's perspective, including but not + * limited to GPRs, EFLAGS.DF, MXCSR, FCW, etc... Conversely, the enclave being + * run **must** preserve the untrusted ``%rbp``. + * + * ``callback`` has the following signature: + * int callback(long rdi, long rsi, long rdx, + * struct sgx_enclave_exinfo *ex_info, long r8, long r9, + * void *tcs, long ursp); + * ``callback`` **shall** follow x86_64 ABI. All GPRs **except** ``%rax``, ``%rbx`` + * and ``rcx`` are passed through to ``callback``. ``%rdi``, ``%rsi``, ``%rdx``, + * ``%r8``, ``%r9``, along with the value of ``%rsp`` when the enclave exited/excepted, + * can be accessed directly as input parameters, while other GPRs can be + * accessed in assembly if needed. + * A positive value returned from ``callback`` will be treated as an ENCLU leaf + * (e.g. EENTER/ERESUME) to reenter the enclave, while 0 or a negative return + * value will be passed back to the caller of __vdso_sgx_enter_enclave(). + * It is also **safe** to ``longjmp()`` out of ``callback``. */ -__vdso_sgx_enter_enclave(u32 leaf, void *tcs, - struct sgx_enclave_exception *ex_info) -{ - if (leaf != SGX_EENTER && leaf != SGX_ERESUME) - return -EINVAL; - - if (!tcs) - return -EINVAL; - - try { - ENCLU[leaf]; - } catch (exception) { - if (e) - *e = exception; - return -EFAULT; - } - - return 0; -} -#endif ENTRY(__vdso_sgx_enter_enclave) - /* EENTER <= leaf <= ERESUME */ + /* Prolog */ + .cfi_startproc + push %rbp + .cfi_adjust_cfa_offset 8 + .cfi_rel_offset %rbp, 0 + mov %rsp, %rbp + .cfi_def_cfa_register %rbp + +1: /* EENTER <= leaf <= ERESUME */ cmp $0x2, %eax - jb bad_input - + jb 6f cmp $0x3, %eax - ja bad_input + ja 6f - /* TCS must be non-NULL */ - test %rbx, %rbx - je bad_input + /* Load TCS and AEP */ + mov 0x10(%rbp), %rbx + lea 2f(%rip), %rcx - /* Save @exception_info */ - push %rcx - - /* Load AEP for ENCLU */ - lea 1f(%rip), %rcx -1: enclu - - add $0x8, %rsp - xor %eax, %eax - ret - -bad_input: - mov $(-EINVAL), %rax - ret - -.pushsection .fixup, "ax" - /* Re-load @exception_info and fill it (if it's non-NULL) */ -2: pop %rcx - test %rcx, %rcx - je 3f + /* Single ENCLU serving as both EENTER and AEP (ERESUME) */ +2: enclu + /* EEXIT path */ + xor %ebx, %ebx +3: mov 0x18(%rbp), %rcx + jrcxz 4f mov %eax, EX_LEAF(%rcx) - mov %di, EX_TRAPNR(%rcx) - mov %si, EX_ERROR_CODE(%rcx) + jnc 4f + mov %di, EX_TRAPNR(%rcx) + mov %si, EX_ERROR_CODE(%rcx) mov %rdx, EX_ADDRESS(%rcx) -3: mov $(-EFAULT), %rax + +4: /* Call *callback if supplied */ + mov 0x20(%rbp), %rax + test %rax, %rax + cmovz %rbx, %rax + jz 7f + /* Align stack and clear RFLAGS.DF per x86_64 ABI */ + mov %rsp, %rbx + and $-0x10, %rsp + cld + /* Parameters for *callback */ + push %rbx + push 0x10(%rbp) + /* Call via retpoline */ + call 40f + /* Cleanup stack */ + mov %rbx, %rsp + jmp 1b +40: /* retpoline */ + call 42f +41: pause + lfence + jmp 41b +42: mov %rax, (%rsp) + ret + +5: /* Exception path */ + mov $-EFAULT, %ebx + stc + jmp 3b + +6: /* Unsupported ENCLU leaf */ + cmp $0, %eax + jle 7f + mov $-EINVAL, %eax + +7: /* Epilog */ + leave + .cfi_def_cfa %rsp, 8 ret -.popsection + .cfi_endproc -_ASM_VDSO_EXTABLE_HANDLE(1b, 2b) +_ASM_VDSO_EXTABLE_HANDLE(2b, 5b) ENDPROC(__vdso_sgx_enter_enclave) diff --git a/arch/x86/include/uapi/asm/sgx.h b/arch/x86/include/uapi/asm/sgx.h index 9ed690a38c70..50d2b5143e5e 100644 --- a/arch/x86/include/uapi/asm/sgx.h +++ b/arch/x86/include/uapi/asm/sgx.h @@ -24,7 +24,7 @@ /** * struct sgx_enclave_create - parameter structure for the - * %SGX_IOC_ENCLAVE_CREATE ioctl + * %SGX_IOC_ENCLAVE_CREATE ioctl * @src: address for the SECS page data */ struct sgx_enclave_create { @@ -33,7 +33,7 @@ struct sgx_enclave_create { /** * struct sgx_enclave_add_page - parameter structure for the - * %SGX_IOC_ENCLAVE_ADD_PAGE ioctl + * %SGX_IOC_ENCLAVE_ADD_PAGE ioctl * @addr: address within the ELRANGE * @src: address for the page data * @secinfo: address for the SECINFO data @@ -49,7 +49,7 @@ struct sgx_enclave_add_page { /** * struct sgx_enclave_init - parameter structure for the - * %SGX_IOC_ENCLAVE_INIT ioctl + * %SGX_IOC_ENCLAVE_INIT ioctl * @sigstruct: address for the SIGSTRUCT data */ struct sgx_enclave_init { @@ -66,16 +66,16 @@ struct sgx_enclave_set_attribute { }; /** - * struct sgx_enclave_exception - structure to report exceptions encountered in - * __vdso_sgx_enter_enclave() + * struct sgx_enclave_exinfo - structure to report exceptions encountered in + * __vdso_sgx_enter_enclave() * - * @leaf: ENCLU leaf from \%eax at time of exception + * @leaf: ENCLU leaf from \%eax at time of exception/exit * @trapnr: exception trap number, a.k.a. fault vector * @error_code: exception error code * @address: exception address, e.g. CR2 on a #PF * @reserved: reserved for future use */ -struct sgx_enclave_exception { +struct sgx_enclave_exinfo { __u32 leaf; __u16 trapnr; __u16 error_code; From patchwork Mon Apr 22 20:42:59 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Xing, Cedric" X-Patchwork-Id: 10911611 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 097361708 for ; Mon, 22 Apr 2019 20:43:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id F1F782871C for ; Mon, 22 Apr 2019 20:43:02 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E697C2874E; Mon, 22 Apr 2019 20:43:02 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 41B272871C for ; Mon, 22 Apr 2019 20:43:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726421AbfDVUnC (ORCPT ); Mon, 22 Apr 2019 16:43:02 -0400 Received: from mga18.intel.com ([134.134.136.126]:62704 "EHLO mga18.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727571AbfDVUnB (ORCPT ); Mon, 22 Apr 2019 16:43:01 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 22 Apr 2019 13:43:00 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.60,383,1549958400"; d="scan'208";a="144786001" Received: from bxing-ubuntu.jf.intel.com ([10.23.30.27]) by orsmga003.jf.intel.com with ESMTP; 22 Apr 2019 13:43:00 -0700 From: Cedric Xing To: linux-sgx@vger.kernel.org Cc: cedric.xing@intel.com Subject: [RFC PATCH v1 3/3] selftests/x86: Augment SGX selftest to test new __vdso_sgx_enter_enclave() and its callback interface Date: Mon, 22 Apr 2019 13:42:59 -0700 Message-Id: X-Mailer: git-send-email 2.17.1 In-Reply-To: References: In-Reply-To: References: <20190417103938.7762-1-jarkko.sakkinen@linux.intel.com> Sender: linux-sgx-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sgx@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Given the changes to __vdso_sgx_enter_enclave(), the selftest is augmented to test the newly added callback interface. This addtional test marks the whole enclave range as PROT_READ, and calls mprotect() upon #PFs to add necessary PTE permissions per PFEC (#PF Error Code) until the enclave finishes. Signed-off-by: Cedric Xing --- tools/testing/selftests/x86/sgx/main.c | 123 ++++++++++++++++++--- tools/testing/selftests/x86/sgx/sgx_call.S | 40 ++++++- 2 files changed, 142 insertions(+), 21 deletions(-) diff --git a/tools/testing/selftests/x86/sgx/main.c b/tools/testing/selftests/x86/sgx/main.c index e2265f841fb0..234cfbad14a5 100644 --- a/tools/testing/selftests/x86/sgx/main.c +++ b/tools/testing/selftests/x86/sgx/main.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -18,6 +19,10 @@ #include "../../../../../arch/x86/kernel/cpu/sgx/arch.h" #include "../../../../../arch/x86/include/uapi/asm/sgx.h" +#define _Q(x) __Q(x) +#define __Q(x) #x +#define ERRLN "Line " _Q(__LINE__) + static const uint64_t MAGIC = 0x1122334455667788ULL; struct vdso_symtab { @@ -138,7 +143,7 @@ static bool encl_create(int dev_fd, unsigned long bin_size, base = mmap(NULL, secs->size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, dev_fd, 0); if (base == MAP_FAILED) { - perror("mmap"); + perror(ERRLN); return false; } @@ -224,24 +229,113 @@ static bool encl_load(struct sgx_secs *secs, unsigned long bin_size) return false; } -void sgx_call(void *rdi, void *rsi, void *tcs, - struct sgx_enclave_exception *exception, - void *eenter); +int sgx_call(void *rdi, void *rsi, long rdx, void *rcx, void *r8, void *r9, + void *tcs, struct sgx_enclave_exinfo *ei, void *cb, void *eenter); + +static void show_enclave_exinfo(const struct sgx_enclave_exinfo *exinfop, + const char *header) +{ + printf("%s: leaf:%d", header, exinfop->leaf); + if (exinfop->leaf != 4) + printf(" trap#:%d ec:%d addr:0x%llx\n", exinfop->trapnr, + exinfop->error_code, exinfop->address); + else printf("\n"); +} + +static void test1(void *eenter, struct sgx_secs *secs) +{ + uint64_t result = 0; + struct sgx_enclave_exinfo exinfo; + + printf("[1] Entering the enclave without callback.\n"); + + printf("Input: 0x%lx\n Expect: Same as input\n", MAGIC); + sgx_call((void *)&MAGIC, &result, 0, NULL, NULL, NULL, + (void *)secs->base, &exinfo, NULL, eenter); + if (result != MAGIC) { + fprintf(stderr, "0x%lx != 0x%lx\n", result, MAGIC); + exit(1); + } + printf(" Output: 0x%lx\n", result); + + printf("Input: Null TCS\n Expect: #PF at EENTER\n"); + sgx_call((void *)&MAGIC, &result, 0, NULL, NULL, NULL, + NULL, &exinfo, NULL, eenter); + show_enclave_exinfo(&exinfo, " Exit"); + if (exinfo.leaf != 2 /*EENTER*/ || exinfo.trapnr != 14 /*#PF*/) + exit(1); +} + +static int enclave_ex_callback(long rdi, long rsi, long rdx, + struct sgx_enclave_exinfo *ei, long r8, long r9, void *tcs, long ursp) +{ + show_enclave_exinfo(ei, " callback"); + + switch (ei->leaf) + { + case 4: + return 0; + case 3: + case 2: + if (ei->trapnr != 14 /*#PF*/ || (ei->error_code & 1) == 0) { + fprintf(stderr, ERRLN ": Unexpected exception\n"); + exit(1); + } + + if (mprotect((void*)(ei->address & -0x1000), 0x1000, + ((ei->error_code & 2) ? PROT_WRITE : 0) | + ((ei->error_code & 0x10) ? PROT_EXEC : 0) | + PROT_READ)) { + perror(ERRLN); + exit(1); + } + + return ei->leaf == 2 ? -EAGAIN : ei->leaf; + } + return -EINVAL; +} + +static void test2(void *eenter, struct sgx_secs *secs) +{ + uint64_t result = 0; + struct sgx_enclave_exinfo exinfo; + + printf("[2] Entering the enclave with callback.\n"); + + printf("Input: 0x%lx\n Expect: Same as input\n", MAGIC); + sgx_call((void *)&MAGIC, &result, 0, NULL, NULL, NULL, + (void *)secs->base, &exinfo, enclave_ex_callback, eenter); + if (result != MAGIC) { + fprintf(stderr, "0x%lx != 0x%lx\n", result, MAGIC); + exit(1); + } + printf(" Output: 0x%lx\n", result); + + printf("Input: Read-only enclave (0x%lx-0x%lx)\n" + " Expect: #PFs to be fixed by callback\n", + secs->base, secs->base + (encl_bin_end - encl_bin) - 1); + if (mprotect((void*)secs->base, encl_bin_end - encl_bin, PROT_READ)) { + perror(ERRLN); + exit(1); + } + while (sgx_call((void *)&MAGIC, &result, 0, NULL, NULL, NULL, + (void*)secs->base, &exinfo, enclave_ex_callback, + eenter) == -EAGAIN); + show_enclave_exinfo(&exinfo, " Exit"); + if (exinfo.leaf != 4 /*EEXIT*/) + exit(1); +} int main(int argc, char *argv[], char *envp[]) { unsigned long bin_size = encl_bin_end - encl_bin; unsigned long ss_size = encl_ss_end - encl_ss; - struct sgx_enclave_exception exception; Elf64_Sym *eenter_sym; struct vdso_symtab symtab; struct sgx_secs secs; - uint64_t result = 0; void *eenter; void *addr; - memset(&exception, 0, sizeof(exception)); - addr = vdso_get_base_addr(envp); if (!addr) exit(1); @@ -266,14 +360,7 @@ int main(int argc, char *argv[], char *envp[]) if (!encl_load(&secs, bin_size)) exit(1); - printf("Input: 0x%lx\n", MAGIC); - sgx_call((void *)&MAGIC, &result, (void *)secs.base, &exception, - eenter); - if (result != MAGIC) { - fprintf(stderr, "0x%lx != 0x%lx\n", result, MAGIC); - exit(1); - } - - printf("Output: 0x%lx\n", result); - exit(0); + test1(eenter, &secs); + test2(eenter, &secs); + return 0; } diff --git a/tools/testing/selftests/x86/sgx/sgx_call.S b/tools/testing/selftests/x86/sgx/sgx_call.S index 14bd0a044199..da8f687a60d2 100644 --- a/tools/testing/selftests/x86/sgx/sgx_call.S +++ b/tools/testing/selftests/x86/sgx/sgx_call.S @@ -7,9 +7,43 @@ .global sgx_call sgx_call: + .cfi_startproc + push %r15 + .cfi_adjust_cfa_offset 8 + .cfi_rel_offset %r15, 0 + push %r14 + .cfi_adjust_cfa_offset 8 + .cfi_rel_offset %r14, 0 + push %r13 + .cfi_adjust_cfa_offset 8 + .cfi_rel_offset %r13, 0 + push %r12 + .cfi_adjust_cfa_offset 8 + .cfi_rel_offset %r12, 0 push %rbx - mov $0x02, %rax - mov %rdx, %rbx - call *%r8 + .cfi_adjust_cfa_offset 8 + .cfi_rel_offset %rbx, 0 + push $0 + .cfi_adjust_cfa_offset 8 + push 0x48(%rsp) + .cfi_adjust_cfa_offset 8 + push 0x48(%rsp) + .cfi_adjust_cfa_offset 8 + push 0x48(%rsp) + .cfi_adjust_cfa_offset 8 + mov $2, %eax + call *0x68(%rsp) + add $0x20, %rsp + .cfi_adjust_cfa_offset -0x20 pop %rbx + .cfi_adjust_cfa_offset -8 + pop %r12 + .cfi_adjust_cfa_offset -8 + pop %r13 + .cfi_adjust_cfa_offset -8 + pop %r14 + .cfi_adjust_cfa_offset -8 + pop %r15 + .cfi_adjust_cfa_offset -8 ret + .cfi_endproc