From patchwork Thu Jul 20 22:16:20 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: 13321141 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 E19A3EB64DD for ; Thu, 20 Jul 2023 22:16:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230054AbjGTWQx (ORCPT ); Thu, 20 Jul 2023 18:16:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44336 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229529AbjGTWQs (ORCPT ); Thu, 20 Jul 2023 18:16:48 -0400 Received: from icts-p-cavuit-1.kulnet.kuleuven.be (icts-p-cavuit-1.kulnet.kuleuven.be [IPv6:2a02:2c40:0:c0::25:132]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8599B2128; Thu, 20 Jul 2023 15:16:42 -0700 (PDT) X-KULeuven-Envelope-From: jo.vanbulck@cs.kuleuven.be X-KULeuven-Scanned: Found to be clean X-KULeuven-ID: 4CDFF20164.A53FB X-KULeuven-Information: Katholieke Universiteit Leuven Received: from icts-p-ceifnet-smtps-0.kuleuven.be (icts-p-ceifnet-smtps.service.icts.svcd [IPv6:2a02:2c40:0:51:143:242:ac11:20]) by icts-p-cavuit-1.kulnet.kuleuven.be (Postfix) with ESMTP id 4CDFF20164; Fri, 21 Jul 2023 00:16:40 +0200 (CEST) BCmilterd-Mark-Subject: no BCmilterd-Errors: BCmilterd-Report: SA-HVU#DKIM_VALID_AU#0.00,SA-HVU#DKIM_SIGNED#0.00,SA-HVU#DKIM_VALID#0.00 X-CAV-Cluster: smtps DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=cs.kuleuven.be; s=cav; t=1689891400; bh=VSQyg6gzCqsY2MIdg+AbxlLyn0u+sFUpjXke7m02e5g=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=LhuuiFEwOfusGMu/EFsQQPLTgeWCF1osYI6hbEVZS8VGm0HTCsFGmAzvGOuGKm9jD WIjw439MXSlMa7C1OxlUeIZxI+gcAO3xIx6KdHAVnJlnnnk87J+BroWpoQji9ejWAF NeZRQ8o9PrE/CBNZkAgaCYoT5hObEMJJn+yJhrQY= Received: from librem.home (unknown [IPv6:2a02:1210:6c17:f000:92c2:ccf4:848b:6bf4]) (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-0.kuleuven.be (Postfix) with ESMTPSA id 04756D4EC61F5; Fri, 21 Jul 2023 00:16:39 +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: Fri, 21 Jul 2023 00:16:20 +0200 Message-Id: <20230720221623.9530-2-jo.vanbulck@cs.kuleuven.be> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230720221623.9530-1-jo.vanbulck@cs.kuleuven.be> References: <20230720221623.9530-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 | 25 +++++++++++++++++++ .../selftests/sgx/test_encl_bootstrap.S | 12 +++++++++ 3 files changed, 38 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..9a671dbc6 100644 --- a/tools/testing/selftests/sgx/main.c +++ b/tools/testing/selftests/sgx/main.c @@ -307,6 +307,31 @@ TEST_F(enclave, unclobbered_vdso) EXPECT_EQ(self->run.user_data, 0); } +/* + * Sanity check that the test enclave properly sanitizes untrusted + * CPU configuration registers. + */ +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 Thu Jul 20 22:16:21 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: 13321142 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 99297EB64DA for ; Thu, 20 Jul 2023 22:16:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229819AbjGTWQx (ORCPT ); Thu, 20 Jul 2023 18:16:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44344 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229934AbjGTWQt (ORCPT ); Thu, 20 Jul 2023 18:16:49 -0400 Received: from icts-p-cavuit-1.kulnet.kuleuven.be (icts-p-cavuit-1.kulnet.kuleuven.be [IPv6:2a02:2c40:0:c0::25:132]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1067D1719; Thu, 20 Jul 2023 15:16:43 -0700 (PDT) X-KULeuven-Envelope-From: jo.vanbulck@cs.kuleuven.be X-KULeuven-Scanned: Found to be clean X-KULeuven-ID: 33B4620164.A6B9A X-KULeuven-Information: Katholieke Universiteit Leuven Received: from icts-p-ceifnet-smtps-0.kuleuven.be (icts-p-ceifnet-smtps.service.icts.svcd [IPv6:2a02:2c40:0:51:143:242:ac11:20]) by icts-p-cavuit-1.kulnet.kuleuven.be (Postfix) with ESMTP id 33B4620164; Fri, 21 Jul 2023 00:16:41 +0200 (CEST) BCmilterd-Mark-Subject: no BCmilterd-Errors: BCmilterd-Report: SA-HVU#DKIM_VALID_AU#0.00,SA-HVU#DKIM_SIGNED#0.00,SA-HVU#DKIM_VALID#0.00 X-CAV-Cluster: smtps DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=cs.kuleuven.be; s=cav; t=1689891401; bh=fdSglpg2gn0pNgPh7u0LeMetohadIiU2uOtBPywtCXU=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=CI1UMu98AM9NUyRAAMK+LeizxOpyb6xAj3bTuykZgQ01HHu0bI3IG5U6OSFRb0ud1 FgLtAET6wh3TDYwzY2Az4E1TbA2LSOIlx0V/UZ70hIxSA5CkO4Z8qXPdilEAmynexm OKwX2/uexspiU+XHlShu1n865IjtVbz7S4dl3sZU= Received: from librem.home (unknown [IPv6:2a02:1210:6c17:f000:92c2:ccf4:848b:6bf4]) (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-0.kuleuven.be (Postfix) with ESMTPSA id E1244D4EB0CF8; Fri, 21 Jul 2023 00:16:40 +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: Fri, 21 Jul 2023 00:16:21 +0200 Message-Id: <20230720221623.9530-3-jo.vanbulck@cs.kuleuven.be> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230720221623.9530-1-jo.vanbulck@cs.kuleuven.be> References: <20230720221623.9530-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 | 32 +++++++++++++++++++ tools/testing/selftests/sgx/test_encl.lds | 1 + .../selftests/sgx/test_encl_bootstrap.S | 17 ++++++++++ 4 files changed, 52 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 9a671dbc6..b1a7988c1 100644 --- a/tools/testing/selftests/sgx/main.c +++ b/tools/testing/selftests/sgx/main.c @@ -178,6 +178,7 @@ static bool setup_test_encl(unsigned long heap_size, struct encl *encl, Elf64_Sym *sgx_enter_enclave_sym = NULL; struct vdso_symtab symtab; struct encl_segment *seg; + uint64_t encl_size_pt; char maps_line[256]; FILE *maps_file; unsigned int i; @@ -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_pt = encl_get_entry(encl, "__enclave_size"); + if (encl_size_pt) { + encl_size_pt += (uint64_t) encl->src; + *((uint64_t *) encl_size_pt) = encl->encl_size; + } + if (!encl_measure(encl)) goto err; @@ -307,6 +318,27 @@ TEST_F(enclave, unclobbered_vdso) EXPECT_EQ(self->run.user_data, 0); } +/* + * Sanity check that the loader correctly initializes __enclave_size in the + * measured enclave image. + */ +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; + + 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); +} + /* * Sanity check that the test enclave properly sanitizes untrusted * CPU configuration registers. 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 Thu Jul 20 22:16:22 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: 13321144 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 B63A9C001DC for ; Thu, 20 Jul 2023 22:16:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229936AbjGTWQy (ORCPT ); Thu, 20 Jul 2023 18:16:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44382 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230038AbjGTWQx (ORCPT ); Thu, 20 Jul 2023 18:16:53 -0400 Received: from icts-p-cavuit-2.kulnet.kuleuven.be (icts-p-cavuit-2.kulnet.kuleuven.be [IPv6:2a02:2c40:0:c0::25:131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9D5902709; Thu, 20 Jul 2023 15:16:44 -0700 (PDT) X-KULeuven-Envelope-From: jo.vanbulck@cs.kuleuven.be X-KULeuven-Scanned: Found to be clean X-KULeuven-ID: 11AB72017E.AD805 X-KULeuven-Information: Katholieke Universiteit Leuven Received: from icts-p-ceifnet-smtps-0.kuleuven.be (icts-p-ceifnet-smtps.service.icts.svcd [IPv6:2a02:2c40:0:51:143:242:ac11:20]) by icts-p-cavuit-2.kulnet.kuleuven.be (Postfix) with ESMTP id 11AB72017E; Fri, 21 Jul 2023 00:16:42 +0200 (CEST) BCmilterd-Mark-Subject: no BCmilterd-Errors: BCmilterd-Report: SA-HVU#DKIM_VALID_AU#0.00,SA-HVU#DKIM_SIGNED#0.00,SA-HVU#DKIM_VALID#0.00 X-CAV-Cluster: smtps DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=cs.kuleuven.be; s=cav; t=1689891402; bh=zgFp9luiS/nACLf5WfG0kxqQ7DKIThEPGSwRSk6PYmQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=e/tQt9yC57l7W9JTjgCTYdgxtEKddhAVbHbpqyNBQyD2r+myj1dMPXzGoBL+wMOJl NiRCynQdIkdbet8tM5eXXpaRG0mCJJNWPbnBbEftRkmREvIMX+jSWoINBmB9bW3m4Z vMV2gwBkA1zVHo+5qL5OoernET6+2KsxHPuwmfkk= Received: from librem.home (unknown [IPv6:2a02:1210:6c17:f000:92c2:ccf4:848b:6bf4]) (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-0.kuleuven.be (Postfix) with ESMTPSA id B0E3FD4EC61F5; Fri, 21 Jul 2023 00:16: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 3/4] selftests/sgx: Harden test enclave API Date: Fri, 21 Jul 2023 00:16:22 +0200 Message-Id: <20230720221623.9530-4-jo.vanbulck@cs.kuleuven.be> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230720221623.9530-1-jo.vanbulck@cs.kuleuven.be> References: <20230720221623.9530-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 | 7 +- tools/testing/selftests/sgx/test_encl.c | 190 ++++++++++++++++++------ 2 files changed, 152 insertions(+), 45 deletions(-) diff --git a/tools/testing/selftests/sgx/main.c b/tools/testing/selftests/sgx/main.c index b1a7988c1..5919f5759 100644 --- a/tools/testing/selftests/sgx/main.c +++ b/tools/testing/selftests/sgx/main.c @@ -341,7 +341,7 @@ TEST_F(enclave, init_size) /* * Sanity check that the test enclave properly sanitizes untrusted - * CPU configuration registers. + * CPU configuration registers and pointer arguments. */ TEST_F(enclave, poison_args) { @@ -362,6 +362,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..ea24cdf9e 100644 --- a/tools/testing/selftests/sgx/test_encl.c +++ b/tools/testing/selftests/sgx/test_encl.c @@ -16,69 +16,148 @@ enum sgx_enclu_function { EMODPE = 0x6, }; +uint64_t get_enclave_base(void); +uint64_t get_enclave_size(void); + +static void *memcpy(void *dest, const void *src, size_t n) +{ + size_t i; + + for (i = 0; i < n; i++) + ((char *)dest)[i] = ((char *)src)[i]; + + return dest; +} + +static void *memset(void *dest, int c, size_t n) +{ + size_t i; + + for (i = 0; i < n; i++) + ((char *)dest)[i] = c; + + return dest; +} + +static int is_outside_enclave(void *addr, size_t len) +{ + /* 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(); + + /* check for integer overflow with untrusted length */ + if (start > end) + return 0; + + return (start > enclave_end || end < get_enclave_base()); +} + +static int is_inside_enclave(void *addr, size_t len) +{ + /* 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(); + + /* check for integer overflow with untrusted length */ + if (start > end) + return 0; + + return (start >= get_enclave_base() && end <= enclave_end); +} + +static inline void panic(void) +{ + asm("ud2\n\t"); +} + +/* + * Asserts the buffer @src of @len bytes lies entirely outside the enclave + * and copies it to @dst to prevent TOCTOU issues. + */ +static inline void copy_inside_enclave(void *dst, void *src, size_t len) +{ + if (!is_outside_enclave(src, len)) + panic(); + + memcpy(dst, src, len); +} + +/* + * Asserts the buffer @dst of @len bytes lies entirely outside the enclave + * and fills it with @len bytes from @src. + */ +static inline void copy_outside_enclave(void *dst, void *src, size_t len) +{ + if (!is_outside_enclave(dst, len)) + panic(); + + memcpy(dst, src, len); +} + +static inline void assert_inside_enclave(uint64_t arg, size_t len) +{ + if (!is_inside_enclave((void *) arg, len)) + panic(); +} + static void do_encl_emodpe(void *_op) { + struct encl_op_emodpe op; struct sgx_secinfo secinfo __aligned(sizeof(struct sgx_secinfo)) = {0}; - struct encl_op_emodpe *op = _op; - secinfo.flags = op->flags; + copy_inside_enclave(&op, _op, sizeof(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)); + "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}; - struct encl_op_eaccept *op = _op; int rax; - secinfo.flags = op->flags; + copy_inside_enclave(&op, _op, sizeof(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; -} - -static void *memcpy(void *dest, const void *src, size_t n) -{ - size_t i; + "c" (op.epc_addr)); - for (i = 0; i < n; i++) - ((char *)dest)[i] = ((char *)src)[i]; - - return dest; -} - -static void *memset(void *dest, int c, size_t n) -{ - size_t i; - - for (i = 0; i < n; i++) - ((char *)dest)[i] = c; - - return dest; + op.ret = rax; + copy_outside_enclave(_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; + copy_inside_enclave(&op, _op, sizeof(op)); + assert_inside_enclave(get_enclave_base() + op.ssa, PAGE_SIZE); + assert_inside_enclave(get_enclave_base() + op.entry, 1); + assert_inside_enclave(op.tcs_page, PAGE_SIZE); + + tcs = (void *)op.tcs_page; 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 +165,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; - memcpy(&encl_buffer[0], &op2->value, 8); + copy_inside_enclave(&op, _op, sizeof(op)); + memcpy(&encl_buffer[0], &op.value, 8); + copy_outside_enclave(_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); + copy_inside_enclave(&op, _op, sizeof(op)); + memcpy(&op.value, &encl_buffer[0], 8); + copy_outside_enclave(_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; - memcpy((void *)op->addr, &op->value, 8); + copy_inside_enclave(&op, _op, sizeof(op)); + + /* + * 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); + + copy_outside_enclave(_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; + + copy_inside_enclave(&op, _op, sizeof(op)); + + /* + * 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->value, (void *)op->addr, 8); + copy_outside_enclave(_op, &op, sizeof(op)); } static void do_encl_op_nop(void *_op) @@ -131,9 +232,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; + copy_inside_enclave(&op, rdi, sizeof(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 Thu Jul 20 22:16:23 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: 13321143 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 6CBF8C001E0 for ; Thu, 20 Jul 2023 22:16:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230080AbjGTWQz (ORCPT ); Thu, 20 Jul 2023 18:16:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44384 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230074AbjGTWQx (ORCPT ); Thu, 20 Jul 2023 18:16:53 -0400 Received: from icts-p-cavuit-1.kulnet.kuleuven.be (icts-p-cavuit-1.kulnet.kuleuven.be [134.58.240.132]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DD11C271C; Thu, 20 Jul 2023 15:16:44 -0700 (PDT) X-KULeuven-Envelope-From: jo.vanbulck@cs.kuleuven.be X-KULeuven-Scanned: Found to be clean X-KULeuven-ID: BE83920062.A53EC X-KULeuven-Information: Katholieke Universiteit Leuven Received: from icts-p-ceifnet-smtps-0.kuleuven.be (icts-p-ceifnet-smtps.service.icts.svcd [IPv6:2a02:2c40:0:51:143:242:ac11:20]) by icts-p-cavuit-1.kulnet.kuleuven.be (Postfix) with ESMTP id BE83920062; Fri, 21 Jul 2023 00:16:42 +0200 (CEST) BCmilterd-Mark-Subject: no BCmilterd-Errors: BCmilterd-Report: SA-HVU#DKIM_VALID_AU#0.00,SA-HVU#DKIM_SIGNED#0.00,SA-HVU#DKIM_VALID#0.00 X-CAV-Cluster: smtps DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=cs.kuleuven.be; s=cav; t=1689891402; bh=p/mHGCHU9khZV4ahP2OfNg5iVtTSORj6dJBV/UvLFD4=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=WXR1gBZvHSMCVKOSkVSDLVNQ1HqnPY8CT9/76KL/3whkSnHuXNkqfdd0Pin3e69FP jXOwtWjl+KRvQwEexQUvXINBHyxmzHTYFA8by+yDR2Tp7x+Ght8cCpB03r3SZp4ciT xAt+sCneVAMTgRLgsRMP7hMRbmRXbD1KcBNdTgvo= Received: from librem.home (unknown [IPv6:2a02:1210:6c17:f000:92c2:ccf4:848b:6bf4]) (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-0.kuleuven.be (Postfix) with ESMTPSA id 77134D4EC61F5; Fri, 21 Jul 2023 00:16: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 4/4] selftests/sgx: Fix compiler optimizations in test enclave Date: Fri, 21 Jul 2023 00:16:23 +0200 Message-Id: <20230720221623.9530-5-jo.vanbulck@cs.kuleuven.be> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230720221623.9530-1-jo.vanbulck@cs.kuleuven.be> References: <20230720221623.9530-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 ea24cdf9e..b580c37f3 100644 --- a/tools/testing/selftests/sgx/test_encl.c +++ b/tools/testing/selftests/sgx/test_encl.c @@ -105,7 +105,8 @@ static inline void assert_inside_enclave(uint64_t arg, size_t len) 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}; copy_inside_enclave(&op, _op, sizeof(op)); assert_inside_enclave(op.epc_addr, PAGE_SIZE); @@ -122,8 +123,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}; copy_inside_enclave(&op, _op, sizeof(op)); assert_inside_enclave(op.epc_addr, PAGE_SIZE); @@ -222,7 +224,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, @@ -237,5 +239,5 @@ void encl_body(void *rdi, void *rsi) copy_inside_enclave(&op, rdi, sizeof(op)); if (op.type < ENCL_OP_MAX) - (*encl_op_array[op.type])(rdi); + (*(get_enclave_base() + encl_op_array[op.type]))(rdi); }