From patchwork Wed Jul 19 14:24:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jo Van Bulck X-Patchwork-Id: 13319077 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 877F2C001B0 for ; Wed, 19 Jul 2023 14:49:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231176AbjGSOt1 (ORCPT ); Wed, 19 Jul 2023 10:49:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42054 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229622AbjGSOtZ (ORCPT ); Wed, 19 Jul 2023 10:49:25 -0400 Received: from icts-p-cavspool-1.kulnet.kuleuven.be (icts-p-cavspool-1.kulnet.kuleuven.be [134.58.240.194]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E7EEA1718; Wed, 19 Jul 2023 07:49:19 -0700 (PDT) Received: from icts-p-cavuit-1.kulnet.kuleuven.be (icts-p-cavuit-1.kulnet.kuleuven.be [IPv6:2a02:2c40:0:c0::25:132]) by icts-p-cavspool-1.kulnet.kuleuven.be (Postfix) with ESMTP id DC6521EFB; Wed, 19 Jul 2023 16:25:46 +0200 (CEST) X-KULeuven-Envelope-From: jo.vanbulck@cs.kuleuven.be X-KULeuven-Scanned: Found to be clean X-KULeuven-ID: 9E8CF2016D.A65EC X-KULeuven-Information: Katholieke Universiteit Leuven Received: from icts-p-ceifnet-smtps-1.kuleuven.be (icts-p-ceifnet-smtps.service.icts.svcd [IPv6:2a02:2c40:0:51:136:242:ac11:f]) by icts-p-cavuit-1.kulnet.kuleuven.be (Postfix) with ESMTP id 9E8CF2016D; Wed, 19 Jul 2023 16:25:41 +0200 (CEST) BCmilterd-Mark-Subject: no BCmilterd-Errors: BCmilterd-Report: SA-HVU#DKIM_VALID_AU#0.00,SA-HVU#DKIM_VALID#0.00,SA-HVU#DKIM_SIGNED#0.00 X-CAV-Cluster: smtps DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=cs.kuleuven.be; s=cav; t=1689776741; bh=U7po882eCFHMo5UgaOdm+hXgmwg0dG234LXIyMqCMnk=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=ZYKJNQ3RNt8RXjFnwCz62eX70YXD+r3tmpyKaoKsyF/SrJGDhrvSkYabD+w40nb1l MQiFnDDUEpLFPbrn5Yky34C/yk+SaOCHaEQ0xyo+0JRVDL8fu2tUWcs1/gRMep8weX gpXWUsRksKfgy2fO9fwbnd+upNcprggvJsWXwcCI= Received: from librem.epfl.ch (eduroam-269-1-126.epfl.ch [192.33.197.126]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by icts-p-ceifnet-smtps-1.kuleuven.be (Postfix) with ESMTPSA id 6B089D4EB0D01; Wed, 19 Jul 2023 16:25:41 +0200 (CEST) X-Kuleuven: This mail passed the K.U.Leuven mailcluster From: Jo Van Bulck To: jarkko@kernel.org, linux-sgx@vger.kernel.org, linux-kernel@vger.kernel.org Cc: dave.hansen@linux.intel.com, Jo Van Bulck Subject: [PATCH 1/4] selftests/sgx: Harden test enclave ABI Date: Wed, 19 Jul 2023 16:24:57 +0200 Message-Id: <20230719142500.13623-2-jo.vanbulck@cs.kuleuven.be> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230719142500.13623-1-jo.vanbulck@cs.kuleuven.be> References: <20230719142500.13623-1-jo.vanbulck@cs.kuleuven.be> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-sgx@vger.kernel.org The System V x86-64 ABI used by the C compiler defines certain low-level CPU configuration registers to be set to expected values upon function entry. However, SGX enclaves cannot expect the untrusted caller to respect these ABI conventions. Therefore, adhere to SGX runtime best practices by sanitizing RFLAGS.DF=0 before transitioning to C code. Additionally sanitize RFLAGS.AC=0 to protect against known #AC-fault side channels for unaligned memory accesses. Note that the test enclave does currently not use any floating-point instructions (-mno-sse). Hence, keep the code simple by _not_ using XRSTOR to cleanse extended x87/SSE state. Signed-off-by: Jo Van Bulck --- tools/testing/selftests/sgx/Makefile | 2 +- tools/testing/selftests/sgx/main.c | 21 +++++++++++++++++++ .../selftests/sgx/test_encl_bootstrap.S | 12 +++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/sgx/Makefile b/tools/testing/selftests/sgx/Makefile index 50aab6b57..c2a13bc6e 100644 --- a/tools/testing/selftests/sgx/Makefile +++ b/tools/testing/selftests/sgx/Makefile @@ -14,7 +14,7 @@ endif INCLUDES := -I$(top_srcdir)/tools/include HOST_CFLAGS := -Wall -Werror -g $(INCLUDES) -fPIC -z noexecstack ENCL_CFLAGS := -Wall -Werror -static -nostdlib -nostartfiles -fPIC \ - -fno-stack-protector -mrdrnd $(INCLUDES) + -fno-stack-protector -mrdrnd -mno-sse $(INCLUDES) TEST_CUSTOM_PROGS := $(OUTPUT)/test_sgx TEST_FILES := $(OUTPUT)/test_encl.elf diff --git a/tools/testing/selftests/sgx/main.c b/tools/testing/selftests/sgx/main.c index 9820b3809..d3c7a39f4 100644 --- a/tools/testing/selftests/sgx/main.c +++ b/tools/testing/selftests/sgx/main.c @@ -307,6 +307,27 @@ TEST_F(enclave, unclobbered_vdso) EXPECT_EQ(self->run.user_data, 0); } +TEST_F(enclave, poison_args) +{ + struct encl_op_header nop_op; + uint64_t flags = -1; + + ASSERT_TRUE(setup_test_encl(ENCL_HEAP_SIZE_DEFAULT, &self->encl, _metadata)); + + memset(&self->run, 0, sizeof(self->run)); + self->run.tcs = self->encl.encl_base; + + /* attempt ABI register poisoning */ + nop_op.type = ENCL_OP_NOP; + asm("std\n\t"); + EXPECT_EQ(ENCL_CALL(&nop_op, &self->run, false), 0); + asm("pushfq\n\t" \ + "popq %0\n\t" \ + : "=m"(flags) : : ); + EXPECT_EEXIT(&self->run); + EXPECT_EQ(flags & 0x40400, 0); +} + /* * A section metric is concatenated in a way that @low bits 12-31 define the * bits 12-31 of the metric and @high bits 0-19 define the bits 32-51 of the diff --git a/tools/testing/selftests/sgx/test_encl_bootstrap.S b/tools/testing/selftests/sgx/test_encl_bootstrap.S index 03ae0f57e..3b69fea61 100644 --- a/tools/testing/selftests/sgx/test_encl_bootstrap.S +++ b/tools/testing/selftests/sgx/test_encl_bootstrap.S @@ -57,6 +57,18 @@ encl_entry_core: push %rcx # push the address after EENTER push %rbx # push the enclave base address + # Sanitize CPU state: x86-64 ABI requires RFLAGS.DF=0 on function + # entry, and we additionally clear RFLAGS.AC to prevent #AC-fault side + # channels. + # NOTE: Real-world enclave runtimes should also cleanse extended CPU + # state (i.e., x87 FPU and SSE/AVX/...) configuration registers, + # preferably using XRSTOR. This is _not_ done below to simplify the + # test enclave, which does not use any floating-point instructions. + cld + pushfq + andq $~0x40000, (%rsp) + popfq + call encl_body pop %rbx # pop the enclave base address From patchwork Wed Jul 19 14:24:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jo Van Bulck X-Patchwork-Id: 13319078 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 128ABC0015E for ; Wed, 19 Jul 2023 14:49:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230392AbjGSOt2 (ORCPT ); Wed, 19 Jul 2023 10:49:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42074 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230413AbjGSOt0 (ORCPT ); Wed, 19 Jul 2023 10:49:26 -0400 Received: from icts-p-cavspool-1.kulnet.kuleuven.be (icts-p-cavspool-1.kulnet.kuleuven.be [134.58.240.194]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 652AD171D; Wed, 19 Jul 2023 07:49:21 -0700 (PDT) Received: from icts-p-cavuit-3.kulnet.kuleuven.be (icts-p-cavuit-3.kulnet.kuleuven.be [134.58.240.133]) by icts-p-cavspool-1.kulnet.kuleuven.be (Postfix) with ESMTP id 48E5A1EDB; Wed, 19 Jul 2023 16:25:46 +0200 (CEST) X-KULeuven-Envelope-From: jo.vanbulck@cs.kuleuven.be X-KULeuven-Scanned: Found to be clean X-KULeuven-ID: 86997201C4.A879C X-KULeuven-Information: Katholieke Universiteit Leuven Received: from icts-p-ceifnet-smtps-1.kuleuven.be (icts-p-ceifnet-smtps.service.icts.svcd [IPv6:2a02:2c40:0:51:136:242:ac11:f]) by icts-p-cavuit-3.kulnet.kuleuven.be (Postfix) with ESMTP id 86997201C4; Wed, 19 Jul 2023 16:25:42 +0200 (CEST) BCmilterd-Mark-Subject: no BCmilterd-Errors: BCmilterd-Report: SA-HVU#DKIM_VALID#0.00,SA-HVU#DKIM_SIGNED#0.00,SA-HVU#DKIM_VALID_AU#0.00 X-CAV-Cluster: smtps DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=cs.kuleuven.be; s=cav; t=1689776742; bh=Nv3EyBGczwLEZB8AWa6Fp/AcP4hw5HdF1V+cNhE8Nuo=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=X4Iucye8FCdaJb5+iAqfdDzW+CSJGmK/Ux8lQa4MrogF7/czdvRq6SbLwAzA4mmuU xyHLw1rWBhp8fp5O1xBoj4DSMf053Nl/anKrqOuy8e3fZvE33oQRiu2R3CaryrCsEl JABKmMjoBQRMcfWaOuJgZxX76FOAoYCQAIHOWb1o= Received: from librem.epfl.ch (eduroam-269-1-126.epfl.ch [192.33.197.126]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by icts-p-ceifnet-smtps-1.kuleuven.be (Postfix) with ESMTPSA id 5227CD4E6AFDA; Wed, 19 Jul 2023 16:25:42 +0200 (CEST) X-Kuleuven: This mail passed the K.U.Leuven mailcluster From: Jo Van Bulck To: jarkko@kernel.org, linux-sgx@vger.kernel.org, linux-kernel@vger.kernel.org Cc: dave.hansen@linux.intel.com, Jo Van Bulck Subject: [PATCH 2/4] selftests/sgx: Store base address and size in test enclave Date: Wed, 19 Jul 2023 16:24:58 +0200 Message-Id: <20230719142500.13623-3-jo.vanbulck@cs.kuleuven.be> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230719142500.13623-1-jo.vanbulck@cs.kuleuven.be> References: <20230719142500.13623-1-jo.vanbulck@cs.kuleuven.be> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-sgx@vger.kernel.org Make the test enclave aware of its protected virtual address range to allow untrusted pointer argument range checks. Add a linker symbol for __enclave_base at the start of the enclave binary. Similar to real-world enclave runtimes, rely on the untrusted loader to fill in __enclave_size (measured as part of MRENCLAVE), as the final size of the enclave image is determined during loading. Signed-off-by: Jo Van Bulck --- tools/testing/selftests/sgx/load.c | 3 +- tools/testing/selftests/sgx/main.c | 29 +++++++++++++++++++ tools/testing/selftests/sgx/test_encl.lds | 1 + .../selftests/sgx/test_encl_bootstrap.S | 17 +++++++++++ 4 files changed, 49 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/sgx/load.c b/tools/testing/selftests/sgx/load.c index 94bdeac1c..968a656a3 100644 --- a/tools/testing/selftests/sgx/load.c +++ b/tools/testing/selftests/sgx/load.c @@ -60,7 +60,8 @@ static bool encl_map_bin(const char *path, struct encl *encl) goto err; } - bin = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + /* NOTE: map read|write to allow __enclave_size to be filled in */ + bin = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); if (bin == MAP_FAILED) { perror("enclave executable mmap()"); goto err; diff --git a/tools/testing/selftests/sgx/main.c b/tools/testing/selftests/sgx/main.c index d3c7a39f4..bad963c79 100644 --- a/tools/testing/selftests/sgx/main.c +++ b/tools/testing/selftests/sgx/main.c @@ -182,6 +182,7 @@ static bool setup_test_encl(unsigned long heap_size, struct encl *encl, FILE *maps_file; unsigned int i; void *addr; + uint64_t encl_size_addr; if (!encl_load("test_encl.elf", encl, heap_size)) { encl_delete(encl); @@ -189,6 +190,16 @@ static bool setup_test_encl(unsigned long heap_size, struct encl *encl, return false; } + /* + * Fill in the expected symbol location with the final size of the + * constructed enclave image. + */ + encl_size_addr = encl_get_entry(encl, "__enclave_size"); + if (encl_size_addr) { + encl_size_addr += (uint64_t) encl->src; + *((uint64_t *) encl_size_addr) = encl->encl_size; + } + if (!encl_measure(encl)) goto err; @@ -307,6 +318,24 @@ TEST_F(enclave, unclobbered_vdso) EXPECT_EQ(self->run.user_data, 0); } +TEST_F(enclave, init_size) +{ + struct encl_op_get_from_addr get_addr_op; + + ASSERT_TRUE(setup_test_encl(ENCL_HEAP_SIZE_DEFAULT, &self->encl, _metadata)); + + memset(&self->run, 0, sizeof(self->run)); + self->run.tcs = self->encl.encl_base; + + /* __enclave_size is initialized by loader in measured enclave image */ + get_addr_op.value = 0; + get_addr_op.addr = self->encl.encl_base + encl_get_entry(&self->encl, "__enclave_size"); + get_addr_op.header.type = ENCL_OP_GET_FROM_ADDRESS; + EXPECT_EQ(ENCL_CALL(&get_addr_op, &self->run, false), 0); + EXPECT_EEXIT(&self->run); + EXPECT_EQ(get_addr_op.value, self->encl.encl_size); +} + TEST_F(enclave, poison_args) { struct encl_op_header nop_op; diff --git a/tools/testing/selftests/sgx/test_encl.lds b/tools/testing/selftests/sgx/test_encl.lds index a1ec64f7d..ca659db2a 100644 --- a/tools/testing/selftests/sgx/test_encl.lds +++ b/tools/testing/selftests/sgx/test_encl.lds @@ -10,6 +10,7 @@ PHDRS SECTIONS { . = 0; + __enclave_base = .; .tcs : { *(.tcs*) } : tcs diff --git a/tools/testing/selftests/sgx/test_encl_bootstrap.S b/tools/testing/selftests/sgx/test_encl_bootstrap.S index 3b69fea61..444a075c0 100644 --- a/tools/testing/selftests/sgx/test_encl_bootstrap.S +++ b/tools/testing/selftests/sgx/test_encl_bootstrap.S @@ -98,6 +98,23 @@ encl_entry_core: mov $4, %rax enclu + .global get_enclave_base +get_enclave_base: + lea __enclave_base(%rip), %rax + ret + + .global get_enclave_size +get_enclave_size: + mov __enclave_size(%rip), %rax + ret + + # The following 8 bytes (measured as part of MRENCLAVE) will be + # filled in by the untrusted loader with the total size of the + # loaded enclave. + .global __enclave_size +__enclave_size: + .quad 0x0 + .section ".data", "aw" encl_ssa_tcs1: From patchwork Wed Jul 19 14:24:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jo Van Bulck X-Patchwork-Id: 13319080 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 53B5EC001E0 for ; Wed, 19 Jul 2023 14:49:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231389AbjGSOt2 (ORCPT ); Wed, 19 Jul 2023 10:49:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42078 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231133AbjGSOt0 (ORCPT ); Wed, 19 Jul 2023 10:49:26 -0400 Received: from icts-p-cavspool-1.kulnet.kuleuven.be (icts-p-cavspool-1.kulnet.kuleuven.be [134.58.240.194]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E7CE41711; Wed, 19 Jul 2023 07:49:19 -0700 (PDT) Received: from icts-p-cavuit-1.kulnet.kuleuven.be (icts-p-cavuit-1.kulnet.kuleuven.be [IPv6:2a02:2c40:0:c0::25:132]) by icts-p-cavspool-1.kulnet.kuleuven.be (Postfix) with ESMTP id D37361EE6; Wed, 19 Jul 2023 16:25:46 +0200 (CEST) X-KULeuven-Envelope-From: jo.vanbulck@cs.kuleuven.be X-KULeuven-Scanned: Found to be clean X-KULeuven-ID: 6D14C2005F.A9FE9 X-KULeuven-Information: Katholieke Universiteit Leuven Received: from icts-p-ceifnet-smtps-1.kuleuven.be (icts-p-ceifnet-smtps.service.icts.svcd [IPv6:2a02:2c40:0:51:136:242:ac11:f]) by icts-p-cavuit-1.kulnet.kuleuven.be (Postfix) with ESMTP id 6D14C2005F; Wed, 19 Jul 2023 16:25:43 +0200 (CEST) BCmilterd-Mark-Subject: no BCmilterd-Errors: BCmilterd-Report: SA-HVU#DKIM_VALID#0.00,SA-HVU#DKIM_SIGNED#0.00,SA-HVU#DKIM_VALID_AU#0.00 X-CAV-Cluster: smtps DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=cs.kuleuven.be; s=cav; t=1689776743; bh=JFhy+W9SL4/6R8071U2QocEnLT8+xt0+g+pWSvUXX9k=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Hhzi3i/uMiFwBe7GYuJ3TV0euVZshQF4DQT4iTIPKPeb932A2pz8lo1INjScAFfF3 1jVRFL+J6VR0Oe8fjbDcZR6w0oKND8jRxKF/t9Nvqh6SMEDtENPATZUE427952p8S8 F8s7c24HiXWJcpDzVPVo9+Ix7qPD9HkHOAg5Xw1s= Received: from librem.epfl.ch (eduroam-269-1-126.epfl.ch [192.33.197.126]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by icts-p-ceifnet-smtps-1.kuleuven.be (Postfix) with ESMTPSA id 36769D4E66FFB; Wed, 19 Jul 2023 16:25:43 +0200 (CEST) X-Kuleuven: This mail passed the K.U.Leuven mailcluster From: Jo Van Bulck To: jarkko@kernel.org, linux-sgx@vger.kernel.org, linux-kernel@vger.kernel.org Cc: dave.hansen@linux.intel.com, Jo Van Bulck Subject: [PATCH 3/4] selftests/sgx: Harden test enclave API Date: Wed, 19 Jul 2023 16:24:59 +0200 Message-Id: <20230719142500.13623-4-jo.vanbulck@cs.kuleuven.be> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230719142500.13623-1-jo.vanbulck@cs.kuleuven.be> References: <20230719142500.13623-1-jo.vanbulck@cs.kuleuven.be> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-sgx@vger.kernel.org Adhere to enclave programming best practices and prevent confused-deputy attacks on the test enclave by validating that untrusted pointer arguments do not fall inside the protected enclave range. Note that the test enclave deliberately allows arbitrary reads/writes in enclave memory through the get_from_addr/put_to_addr operations for explicit testing purposes. Hence, only allow remaining unchecked pointer dereferences in these functions. Signed-off-by: Jo Van Bulck --- tools/testing/selftests/sgx/main.c | 5 + tools/testing/selftests/sgx/test_encl.c | 161 ++++++++++++++++++------ 2 files changed, 128 insertions(+), 38 deletions(-) diff --git a/tools/testing/selftests/sgx/main.c b/tools/testing/selftests/sgx/main.c index bad963c79..8d60f8dcd 100644 --- a/tools/testing/selftests/sgx/main.c +++ b/tools/testing/selftests/sgx/main.c @@ -355,6 +355,11 @@ TEST_F(enclave, poison_args) : "=m"(flags) : : ); EXPECT_EEXIT(&self->run); EXPECT_EQ(flags & 0x40400, 0); + + /* attempt API pointer poisoning */ + EXPECT_EQ(ENCL_CALL(self->encl.encl_base + self->encl.encl_size - 1, &self->run, false), 0); + EXPECT_EQ((&self->run)->function, ERESUME); + EXPECT_EQ((&self->run)->exception_vector, 6 /* expect ud2 */); } /* diff --git a/tools/testing/selftests/sgx/test_encl.c b/tools/testing/selftests/sgx/test_encl.c index c0d639729..5531f5d48 100644 --- a/tools/testing/selftests/sgx/test_encl.c +++ b/tools/testing/selftests/sgx/test_encl.c @@ -16,37 +16,55 @@ enum sgx_enclu_function { EMODPE = 0x6, }; -static void do_encl_emodpe(void *_op) +uint64_t get_enclave_base(void); +uint64_t get_enclave_size(void); + +static int is_outside_enclave(void *addr, size_t len) { - struct sgx_secinfo secinfo __aligned(sizeof(struct sgx_secinfo)) = {0}; - struct encl_op_emodpe *op = _op; + /* need cast since void pointer arithmetics are undefined in C */ + size_t start = (size_t) addr; + size_t end = start + len - 1; + size_t enclave_end = get_enclave_base() + get_enclave_size(); - secinfo.flags = op->flags; + /* check for integer overflow with untrusted length */ + if (start > end) + return 0; - asm volatile(".byte 0x0f, 0x01, 0xd7" - : - : "a" (EMODPE), - "b" (&secinfo), - "c" (op->epc_addr)); + return (start > enclave_end || end < get_enclave_base()); } -static void do_encl_eaccept(void *_op) +static int is_inside_enclave(void *addr, size_t len) { - struct sgx_secinfo secinfo __aligned(sizeof(struct sgx_secinfo)) = {0}; - struct encl_op_eaccept *op = _op; - int rax; + /* need cast since void pointer arithmetics are undefined in C */ + size_t start = (size_t) addr; + size_t end = start + len - 1; + size_t enclave_end = get_enclave_base() + get_enclave_size(); - secinfo.flags = op->flags; + /* check for integer overflow with untrusted length */ + if (start > end) + return 0; - asm volatile(".byte 0x0f, 0x01, 0xd7" - : "=a" (rax) - : "a" (EACCEPT), - "b" (&secinfo), - "c" (op->epc_addr)); - - op->ret = rax; + return (start >= get_enclave_base() && end <= enclave_end); } +#define PANIC() \ + asm("ud2\n\t") + +#define SAFE_COPY_STRUCT(u_arg, t_cp) \ + do { \ + /* 1. check if the argument lies entirely outside */ \ + if (!is_outside_enclave((void *)u_arg, sizeof(*t_cp))) \ + PANIC(); \ + /* 2. copy the argument inside to prevent TOCTOU */ \ + memcpy(t_cp, u_arg, sizeof(*t_cp)); \ + } while (0) + +#define ASSERT_INSIDE_ENCLAVE(u_arg, size) \ + do { \ + if (!is_inside_enclave(((void *)(u_arg)), size)) \ + PANIC(); \ + } while (0) + static void *memcpy(void *dest, const void *src, size_t n) { size_t i; @@ -67,18 +85,62 @@ static void *memset(void *dest, int c, size_t n) return dest; } +static void do_encl_emodpe(void *_op) +{ + struct encl_op_emodpe op; + struct sgx_secinfo secinfo __aligned(sizeof(struct sgx_secinfo)) = {0}; + + SAFE_COPY_STRUCT(_op, &op); + ASSERT_INSIDE_ENCLAVE(op.epc_addr, PAGE_SIZE); + + secinfo.flags = op.flags; + + asm volatile(".byte 0x0f, 0x01, 0xd7" + : + : "a" (EMODPE), + "b" (&secinfo), + "c" (op.epc_addr)); +} + +static void do_encl_eaccept(void *_op) +{ + struct encl_op_eaccept op; + struct sgx_secinfo secinfo __aligned(sizeof(struct sgx_secinfo)) = {0}; + int rax; + + SAFE_COPY_STRUCT(_op, &op); + ASSERT_INSIDE_ENCLAVE(op.epc_addr, PAGE_SIZE); + + secinfo.flags = op.flags; + + asm volatile(".byte 0x0f, 0x01, 0xd7" + : "=a" (rax) + : "a" (EACCEPT), + "b" (&secinfo), + "c" (op.epc_addr)); + + op.ret = rax; + memcpy(_op, &op, sizeof(op)); +} + static void do_encl_init_tcs_page(void *_op) { - struct encl_op_init_tcs_page *op = _op; - void *tcs = (void *)op->tcs_page; + struct encl_op_init_tcs_page op; + void *tcs; uint32_t val_32; + SAFE_COPY_STRUCT(_op, &op); + tcs = (void *)op.tcs_page; + ASSERT_INSIDE_ENCLAVE(tcs, PAGE_SIZE); + ASSERT_INSIDE_ENCLAVE(get_enclave_base() + op.ssa, PAGE_SIZE); + ASSERT_INSIDE_ENCLAVE(get_enclave_base() + op.entry, 1); + memset(tcs, 0, 16); /* STATE and FLAGS */ - memcpy(tcs + 16, &op->ssa, 8); /* OSSA */ + memcpy(tcs + 16, &op.ssa, 8); /* OSSA */ memset(tcs + 24, 0, 4); /* CSSA */ val_32 = 1; memcpy(tcs + 28, &val_32, 4); /* NSSA */ - memcpy(tcs + 32, &op->entry, 8); /* OENTRY */ + memcpy(tcs + 32, &op.entry, 8); /* OENTRY */ memset(tcs + 40, 0, 24); /* AEP, OFSBASE, OGSBASE */ val_32 = 0xFFFFFFFF; memcpy(tcs + 64, &val_32, 4); /* FSLIMIT */ @@ -86,32 +148,54 @@ static void do_encl_init_tcs_page(void *_op) memset(tcs + 72, 0, 4024); /* Reserved */ } -static void do_encl_op_put_to_buf(void *op) +static void do_encl_op_put_to_buf(void *_op) { - struct encl_op_put_to_buf *op2 = op; + struct encl_op_get_from_buf op; + + SAFE_COPY_STRUCT(_op, &op); - memcpy(&encl_buffer[0], &op2->value, 8); + memcpy(&encl_buffer[0], &op.value, 8); + memcpy(_op, &op, sizeof(op)); } -static void do_encl_op_get_from_buf(void *op) +static void do_encl_op_get_from_buf(void *_op) { - struct encl_op_get_from_buf *op2 = op; + struct encl_op_get_from_buf op; - memcpy(&op2->value, &encl_buffer[0], 8); + SAFE_COPY_STRUCT(_op, &op); + + memcpy(&op.value, &encl_buffer[0], 8); + memcpy(_op, &op, sizeof(op)); } static void do_encl_op_put_to_addr(void *_op) { - struct encl_op_put_to_addr *op = _op; + struct encl_op_put_to_addr op; + + SAFE_COPY_STRUCT(_op, &op); - memcpy((void *)op->addr, &op->value, 8); + /* + * NOTE: not checking is_outside_enclave(op.addr, 8) here + * deliberately allows arbitrary writes to enclave memory for + * testing purposes. + */ + memcpy((void *)op.addr, &op.value, 8); + memcpy(_op, &op, sizeof(op)); } static void do_encl_op_get_from_addr(void *_op) { - struct encl_op_get_from_addr *op = _op; + struct encl_op_get_from_addr op; + + SAFE_COPY_STRUCT(_op, &op); - memcpy(&op->value, (void *)op->addr, 8); + /* + * NOTE: not checking is_outside_enclave(op.addr, 8) here + * deliberately allows arbitrary reads from enclave memory for + * testing purposes. + */ + memcpy(&op.value, (void *)op.addr, 8); + memcpy(_op, &op, sizeof(op)); } static void do_encl_op_nop(void *_op) @@ -131,9 +215,10 @@ void encl_body(void *rdi, void *rsi) do_encl_emodpe, do_encl_init_tcs_page, }; + struct encl_op_header op; - struct encl_op_header *op = (struct encl_op_header *)rdi; + SAFE_COPY_STRUCT(rdi, &op); - if (op->type < ENCL_OP_MAX) - (*encl_op_array[op->type])(op); + if (op.type < ENCL_OP_MAX) + (*encl_op_array[op.type])(rdi); } From patchwork Wed Jul 19 14:25:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jo Van Bulck X-Patchwork-Id: 13319076 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 953ADEB64DA for ; Wed, 19 Jul 2023 14:49:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230513AbjGSOt0 (ORCPT ); Wed, 19 Jul 2023 10:49:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42052 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229646AbjGSOtZ (ORCPT ); Wed, 19 Jul 2023 10:49:25 -0400 X-Greylist: delayed 1420 seconds by postgrey-1.37 at lindbergh.monkeyblade.net; Wed, 19 Jul 2023 07:49:19 PDT Received: from icts-p-cavspool-1.kulnet.kuleuven.be (icts-p-cavspool-1.kulnet.kuleuven.be [134.58.240.194]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7EBC111B; Wed, 19 Jul 2023 07:49:19 -0700 (PDT) Received: from icts-p-cavuit-1.kulnet.kuleuven.be (icts-p-cavuit-1.kulnet.kuleuven.be [IPv6:2a02:2c40:0:c0::25:132]) by icts-p-cavspool-1.kulnet.kuleuven.be (Postfix) with ESMTP id 40DAF1EFF; Wed, 19 Jul 2023 16:25:49 +0200 (CEST) X-KULeuven-Envelope-From: jo.vanbulck@cs.kuleuven.be X-KULeuven-Scanned: Found to be clean X-KULeuven-ID: 6937920172.A944A X-KULeuven-Information: Katholieke Universiteit Leuven Received: from icts-p-ceifnet-smtps-1.kuleuven.be (icts-p-ceifnet-smtps.service.icts.svcd [IPv6:2a02:2c40:0:51:136:242:ac11:f]) by icts-p-cavuit-1.kulnet.kuleuven.be (Postfix) with ESMTP id 6937920172; Wed, 19 Jul 2023 16:25:44 +0200 (CEST) BCmilterd-Mark-Subject: no BCmilterd-Errors: BCmilterd-Report: SA-HVU#DKIM_VALID#0.00,SA-HVU#DKIM_SIGNED#0.00,SA-HVU#DKIM_VALID_AU#0.00 X-CAV-Cluster: smtps DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=cs.kuleuven.be; s=cav; t=1689776744; bh=5z6MJatlb5WblaaYzgRyXrmUXZWjDHrlu7vyGhgqg2I=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=JW9DEm3ick7ApuOSP3FNiVODaBf8i7CQPoKihhhoq4aq3yujoarkCscviGKf4LiRa Chx/DxULB9XMJrWOxWqE4/3s1yFnTzVWgoig3LH1JTBDiHWHBjo2kyxopHIHrObpWY mxl7HaNM0k//MZBtY4JyWBqI5CvniiaQGuAffKdM= Received: from librem.epfl.ch (eduroam-269-1-126.epfl.ch [192.33.197.126]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by icts-p-ceifnet-smtps-1.kuleuven.be (Postfix) with ESMTPSA id 38BBBD4EC4971; Wed, 19 Jul 2023 16:25:44 +0200 (CEST) X-Kuleuven: This mail passed the K.U.Leuven mailcluster From: Jo Van Bulck To: jarkko@kernel.org, linux-sgx@vger.kernel.org, linux-kernel@vger.kernel.org Cc: dave.hansen@linux.intel.com, Jo Van Bulck Subject: [PATCH 4/4] selftests/sgx: Fix compiler optimizations in test enclave Date: Wed, 19 Jul 2023 16:25:00 +0200 Message-Id: <20230719142500.13623-5-jo.vanbulck@cs.kuleuven.be> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230719142500.13623-1-jo.vanbulck@cs.kuleuven.be> References: <20230719142500.13623-1-jo.vanbulck@cs.kuleuven.be> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-sgx@vger.kernel.org Relocate encl_op_array entries at runtime relative to the enclave base to ensure correct function pointer when compiling the test enclave with -Os. Declare the secinfo struct as volatile to prevent compiler optimizations from passing an unaligned pointer to ENCLU. Signed-off-by: Jo Van Bulck --- tools/testing/selftests/sgx/test_encl.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/testing/selftests/sgx/test_encl.c b/tools/testing/selftests/sgx/test_encl.c index 5531f5d48..d78596ccf 100644 --- a/tools/testing/selftests/sgx/test_encl.c +++ b/tools/testing/selftests/sgx/test_encl.c @@ -88,7 +88,8 @@ static void *memset(void *dest, int c, size_t n) static void do_encl_emodpe(void *_op) { struct encl_op_emodpe op; - struct sgx_secinfo secinfo __aligned(sizeof(struct sgx_secinfo)) = {0}; + /* declare secinfo volatile to preserve alignment */ + volatile struct __aligned(sizeof(struct sgx_secinfo)) sgx_secinfo secinfo = {0}; SAFE_COPY_STRUCT(_op, &op); ASSERT_INSIDE_ENCLAVE(op.epc_addr, PAGE_SIZE); @@ -105,8 +106,9 @@ static void do_encl_emodpe(void *_op) static void do_encl_eaccept(void *_op) { struct encl_op_eaccept op; - struct sgx_secinfo secinfo __aligned(sizeof(struct sgx_secinfo)) = {0}; int rax; + /* declare secinfo volatile to preserve alignment */ + volatile struct __aligned(sizeof(struct sgx_secinfo)) sgx_secinfo secinfo = {0}; SAFE_COPY_STRUCT(_op, &op); ASSERT_INSIDE_ENCLAVE(op.epc_addr, PAGE_SIZE); @@ -205,7 +207,7 @@ static void do_encl_op_nop(void *_op) void encl_body(void *rdi, void *rsi) { - const void (*encl_op_array[ENCL_OP_MAX])(void *) = { + static 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, @@ -220,5 +222,5 @@ void encl_body(void *rdi, void *rsi) SAFE_COPY_STRUCT(rdi, &op); if (op.type < ENCL_OP_MAX) - (*encl_op_array[op.type])(rdi); + (*(get_enclave_base() + encl_op_array[op.type]))(rdi); }