From patchwork Sun Mar 17 21:14:30 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 10856595 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 351911390 for ; Sun, 17 Mar 2019 21:15:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1C18029071 for ; Sun, 17 Mar 2019 21:15:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0FC96290BA; Sun, 17 Mar 2019 21:15:21 +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 8E2DC29071 for ; Sun, 17 Mar 2019 21:15:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726452AbfCQVPU (ORCPT ); Sun, 17 Mar 2019 17:15:20 -0400 Received: from mga04.intel.com ([192.55.52.120]:14766 "EHLO mga04.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726446AbfCQVPU (ORCPT ); Sun, 17 Mar 2019 17:15:20 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Mar 2019 14:15:19 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,491,1544515200"; d="scan'208";a="142816601" Received: from vanderss-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.254.193]) by orsmga002.jf.intel.com with ESMTP; 17 Mar 2019 14:15:10 -0700 From: Jarkko Sakkinen To: x86@kernel.org, linux-sgx@vger.kernel.org Cc: akpm@linux-foundation.org, dave.hansen@intel.com, sean.j.christopherson@intel.com, nhorman@redhat.com, npmccallum@redhat.com, serge.ayoun@intel.com, shay.katz-zamir@intel.com, haitao.huang@intel.com, andriy.shevchenko@linux.intel.com, tglx@linutronix.de, kai.svahn@intel.com, bp@alien8.de, josh@joshtriplett.org, luto@kernel.org, kai.huang@intel.com, rientjes@google.com, Kai Huang , Jarkko Sakkinen Subject: [PATCH v19 01/27] x86/cpufeatures: Add Intel-defined SGX feature bit Date: Sun, 17 Mar 2019 23:14:30 +0200 Message-Id: <20190317211456.13927-2-jarkko.sakkinen@linux.intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> References: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> MIME-Version: 1.0 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 From: Kai Huang X86_FEATURE_SGX reflects whether or not the CPU supports Intel's Software Guard eXtensions (SGX). Signed-off-by: Kai Huang Co-developed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen Reviewed-by: Borislav Petkov --- arch/x86/include/asm/cpufeatures.h | 1 + arch/x86/include/asm/disabled-features.h | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index 981ff9479648..a16325db4cff 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -236,6 +236,7 @@ /* Intel-defined CPU features, CPUID level 0x00000007:0 (EBX), word 9 */ #define X86_FEATURE_FSGSBASE ( 9*32+ 0) /* RDFSBASE, WRFSBASE, RDGSBASE, WRGSBASE instructions*/ #define X86_FEATURE_TSC_ADJUST ( 9*32+ 1) /* TSC adjustment MSR 0x3B */ +#define X86_FEATURE_SGX ( 9*32+ 2) /* Software Guard Extensions */ #define X86_FEATURE_BMI1 ( 9*32+ 3) /* 1st group bit manipulation extensions */ #define X86_FEATURE_HLE ( 9*32+ 4) /* Hardware Lock Elision */ #define X86_FEATURE_AVX2 ( 9*32+ 5) /* AVX2 instructions */ diff --git a/arch/x86/include/asm/disabled-features.h b/arch/x86/include/asm/disabled-features.h index a5ea841cc6d2..74de07d0f390 100644 --- a/arch/x86/include/asm/disabled-features.h +++ b/arch/x86/include/asm/disabled-features.h @@ -62,6 +62,12 @@ # define DISABLE_PTI (1 << (X86_FEATURE_PTI & 31)) #endif +#ifdef CONFIG_INTEL_SGX +# define DISABLE_SGX_CORE 0 +#else +# define DISABLE_SGX_CORE (1 << (X86_FEATURE_SGX & 31)) +#endif + /* * Make sure to add features to the correct mask */ @@ -74,7 +80,7 @@ #define DISABLED_MASK6 0 #define DISABLED_MASK7 (DISABLE_PTI) #define DISABLED_MASK8 0 -#define DISABLED_MASK9 (DISABLE_MPX|DISABLE_SMAP) +#define DISABLED_MASK9 (DISABLE_MPX|DISABLE_SMAP|DISABLE_SGX_CORE) #define DISABLED_MASK10 0 #define DISABLED_MASK11 0 #define DISABLED_MASK12 0 From patchwork Sun Mar 17 21:14:31 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 10856597 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 ED1CB1390 for ; Sun, 17 Mar 2019 21:15:31 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D562A29071 for ; Sun, 17 Mar 2019 21:15:31 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C98EA290BA; Sun, 17 Mar 2019 21:15:31 +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 3B4D129071 for ; Sun, 17 Mar 2019 21:15:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726452AbfCQVPb (ORCPT ); Sun, 17 Mar 2019 17:15:31 -0400 Received: from mga18.intel.com ([134.134.136.126]:64624 "EHLO mga18.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726446AbfCQVPa (ORCPT ); Sun, 17 Mar 2019 17:15:30 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Mar 2019 14:15:30 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,491,1544515200"; d="scan'208";a="142816617" Received: from vanderss-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.254.193]) by orsmga002.jf.intel.com with ESMTP; 17 Mar 2019 14:15:21 -0700 From: Jarkko Sakkinen To: x86@kernel.org, linux-sgx@vger.kernel.org Cc: akpm@linux-foundation.org, dave.hansen@intel.com, sean.j.christopherson@intel.com, nhorman@redhat.com, npmccallum@redhat.com, serge.ayoun@intel.com, shay.katz-zamir@intel.com, haitao.huang@intel.com, andriy.shevchenko@linux.intel.com, tglx@linutronix.de, kai.svahn@intel.com, bp@alien8.de, josh@joshtriplett.org, luto@kernel.org, kai.huang@intel.com, rientjes@google.com, Jarkko Sakkinen Subject: [PATCH v19 02/27] x86/cpufeatures: Add SGX sub-features (as Linux-defined bits) Date: Sun, 17 Mar 2019 23:14:31 +0200 Message-Id: <20190317211456.13927-3-jarkko.sakkinen@linux.intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> References: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> MIME-Version: 1.0 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 From: Sean Christopherson CPUID_12_EAX is an Intel-defined feature bits leaf dedicated for SGX that enumerates the SGX instruction sets that are supported by the CPU, e.g. SGX1, SGX2, etc... Because Linux currently only cares about two bits (SGX1 and SGX2) and there are currently only four documented bits in total, relocate the bits to Linux-defined word 8 to conserve space. But, keep the bit positions identical between the Intel-defined value and the Linux-defined value, e.g. keep SGX1 at bit 0. This allows KVM to use its existing code for probing guest CPUID bits using Linux's X86_FEATURE_* definitions. To do so, shift around some existing bits to effectively reserve bits 0-7 of word 8 for SGX sub-features. Signed-off-by: Sean Christopherson Signed-off-by: Jarkko Sakkinen --- arch/x86/include/asm/cpufeatures.h | 22 ++++++++++++++++------ arch/x86/include/asm/disabled-features.h | 6 +++++- arch/x86/kernel/cpu/scattered.c | 2 ++ tools/arch/x86/include/asm/cpufeatures.h | 21 +++++++++++++++------ 4 files changed, 38 insertions(+), 13 deletions(-) diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index a16325db4cff..313c58c04b51 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -222,12 +222,22 @@ #define X86_FEATURE_L1TF_PTEINV ( 7*32+29) /* "" L1TF workaround PTE inversion */ #define X86_FEATURE_IBRS_ENHANCED ( 7*32+30) /* Enhanced IBRS */ -/* Virtualization flags: Linux defined, word 8 */ -#define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */ -#define X86_FEATURE_VNMI ( 8*32+ 1) /* Intel Virtual NMI */ -#define X86_FEATURE_FLEXPRIORITY ( 8*32+ 2) /* Intel FlexPriority */ -#define X86_FEATURE_EPT ( 8*32+ 3) /* Intel Extended Page Table */ -#define X86_FEATURE_VPID ( 8*32+ 4) /* Intel Virtual Processor ID */ +/* + * Scattered Intel features: Linux defined, word 8. + * + * Note that the bit location of the SGX features is meaningful as KVM expects + * the Linux defined bit to match the Intel defined bit, e.g. X86_FEATURE_SGX1 + * must remain at bit 0, SGX2 at bit 1, etc... + */ +#define X86_FEATURE_SGX1 ( 8*32+ 0) /* SGX1 leaf functions */ +#define X86_FEATURE_SGX2 ( 8*32+ 1) /* SGX2 leaf functions */ +/* Bits [0:7] are reserved for SGX */ + +#define X86_FEATURE_TPR_SHADOW ( 8*32+ 8) /* Intel TPR Shadow */ +#define X86_FEATURE_VNMI ( 8*32+ 9) /* Intel Virtual NMI */ +#define X86_FEATURE_FLEXPRIORITY ( 8*32+10) /* Intel FlexPriority */ +#define X86_FEATURE_EPT ( 8*32+11) /* Intel Extended Page Table */ +#define X86_FEATURE_VPID ( 8*32+12) /* Intel Virtual Processor ID */ #define X86_FEATURE_VMMCALL ( 8*32+15) /* Prefer VMMCALL to VMCALL */ #define X86_FEATURE_XENPV ( 8*32+16) /* "" Xen paravirtual guest */ diff --git a/arch/x86/include/asm/disabled-features.h b/arch/x86/include/asm/disabled-features.h index 74de07d0f390..926f9dc4d75a 100644 --- a/arch/x86/include/asm/disabled-features.h +++ b/arch/x86/include/asm/disabled-features.h @@ -34,12 +34,16 @@ # define DISABLE_CYRIX_ARR (1<<(X86_FEATURE_CYRIX_ARR & 31)) # define DISABLE_CENTAUR_MCR (1<<(X86_FEATURE_CENTAUR_MCR & 31)) # define DISABLE_PCID 0 +# define DISABLE_SGX1 0 +# define DISABLE_SGX2 0 #else # define DISABLE_VME 0 # define DISABLE_K6_MTRR 0 # define DISABLE_CYRIX_ARR 0 # define DISABLE_CENTAUR_MCR 0 # define DISABLE_PCID (1<<(X86_FEATURE_PCID & 31)) +# define DISABLE_SGX1 (1<<(X86_FEATURE_SGX1 & 31)) +# define DISABLE_SGX2 (1<<(X86_FEATURE_SGX2 & 31)) #endif /* CONFIG_X86_64 */ #ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS @@ -79,7 +83,7 @@ #define DISABLED_MASK5 0 #define DISABLED_MASK6 0 #define DISABLED_MASK7 (DISABLE_PTI) -#define DISABLED_MASK8 0 +#define DISABLED_MASK8 (DISABLE_SGX1|DISABLE_SGX2) #define DISABLED_MASK9 (DISABLE_MPX|DISABLE_SMAP|DISABLE_SGX_CORE) #define DISABLED_MASK10 0 #define DISABLED_MASK11 0 diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c index 94aa1c72ca98..9a5f6cf947b9 100644 --- a/arch/x86/kernel/cpu/scattered.c +++ b/arch/x86/kernel/cpu/scattered.c @@ -31,6 +31,8 @@ static const struct cpuid_bit cpuid_bits[] = { { X86_FEATURE_CDP_L3, CPUID_ECX, 2, 0x00000010, 1 }, { X86_FEATURE_CDP_L2, CPUID_ECX, 2, 0x00000010, 2 }, { X86_FEATURE_MBA, CPUID_EBX, 3, 0x00000010, 0 }, + { X86_FEATURE_SGX1, CPUID_EAX, 0, 0x00000012, 0 }, + { X86_FEATURE_SGX2, CPUID_EAX, 1, 0x00000012, 0 }, { X86_FEATURE_HW_PSTATE, CPUID_EDX, 7, 0x80000007, 0 }, { X86_FEATURE_CPB, CPUID_EDX, 9, 0x80000007, 0 }, { X86_FEATURE_PROC_FEEDBACK, CPUID_EDX, 11, 0x80000007, 0 }, diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h index 6d6122524711..f3a936c7fed4 100644 --- a/tools/arch/x86/include/asm/cpufeatures.h +++ b/tools/arch/x86/include/asm/cpufeatures.h @@ -222,12 +222,21 @@ #define X86_FEATURE_L1TF_PTEINV ( 7*32+29) /* "" L1TF workaround PTE inversion */ #define X86_FEATURE_IBRS_ENHANCED ( 7*32+30) /* Enhanced IBRS */ -/* Virtualization flags: Linux defined, word 8 */ -#define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */ -#define X86_FEATURE_VNMI ( 8*32+ 1) /* Intel Virtual NMI */ -#define X86_FEATURE_FLEXPRIORITY ( 8*32+ 2) /* Intel FlexPriority */ -#define X86_FEATURE_EPT ( 8*32+ 3) /* Intel Extended Page Table */ -#define X86_FEATURE_VPID ( 8*32+ 4) /* Intel Virtual Processor ID */ +/* + * Scattered Intel features: Linux defined, word 8. + * + * Note that the bit numbers of the SGX features are meaningful as KVM expects + * the Linux defined bit to match the Intel defined bit, e.g. X86_FEATURE_SGX1 + * must remain at bit 0, SGX2 at bit 1, etc... + */ +#define X86_FEATURE_SGX1 ( 8*32+ 0) /* SGX1 leaf functions */ +#define X86_FEATURE_SGX2 ( 8*32+ 1) /* SGX2 leaf functions */ + +#define X86_FEATURE_TPR_SHADOW ( 8*32+ 8) /* Intel TPR Shadow */ +#define X86_FEATURE_VNMI ( 8*32+ 9) /* Intel Virtual NMI */ +#define X86_FEATURE_FLEXPRIORITY ( 8*32+10) /* Intel FlexPriority */ +#define X86_FEATURE_EPT ( 8*32+11) /* Intel Extended Page Table */ +#define X86_FEATURE_VPID ( 8*32+12) /* Intel Virtual Processor ID */ #define X86_FEATURE_VMMCALL ( 8*32+15) /* Prefer VMMCALL to VMCALL */ #define X86_FEATURE_XENPV ( 8*32+16) /* "" Xen paravirtual guest */ From patchwork Sun Mar 17 21:14:32 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 10856599 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 4D6031390 for ; Sun, 17 Mar 2019 21:15:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 33FD1291EE for ; Sun, 17 Mar 2019 21:15:42 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 26A4F29214; Sun, 17 Mar 2019 21:15:42 +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 CB405291EE for ; Sun, 17 Mar 2019 21:15:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726452AbfCQVPl (ORCPT ); Sun, 17 Mar 2019 17:15:41 -0400 Received: from mga17.intel.com ([192.55.52.151]:38482 "EHLO mga17.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726446AbfCQVPl (ORCPT ); Sun, 17 Mar 2019 17:15:41 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga107.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Mar 2019 14:15:41 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,491,1544515200"; d="scan'208";a="142816641" Received: from vanderss-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.254.193]) by orsmga002.jf.intel.com with ESMTP; 17 Mar 2019 14:15:32 -0700 From: Jarkko Sakkinen To: x86@kernel.org, linux-sgx@vger.kernel.org Cc: akpm@linux-foundation.org, dave.hansen@intel.com, sean.j.christopherson@intel.com, nhorman@redhat.com, npmccallum@redhat.com, serge.ayoun@intel.com, shay.katz-zamir@intel.com, haitao.huang@intel.com, andriy.shevchenko@linux.intel.com, tglx@linutronix.de, kai.svahn@intel.com, bp@alien8.de, josh@joshtriplett.org, luto@kernel.org, kai.huang@intel.com, rientjes@google.com, Jarkko Sakkinen Subject: [PATCH v19 03/27] x86/msr: Add IA32_FEATURE_CONTROL.SGX_ENABLE definition Date: Sun, 17 Mar 2019 23:14:32 +0200 Message-Id: <20190317211456.13927-4-jarkko.sakkinen@linux.intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> References: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> MIME-Version: 1.0 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 From: Sean Christopherson Add a new IA32_FEATURE_CONTROL bit, SGX_ENABLE, which must be set in order to execute SGX instructions, i.e. ENCL{S,U,V}. The existence of the bit is enumerated by CPUID as X86_FEATURE_SGX. Like all other flags in IA32_FEATURE_CONTROL, the MSR must be locked for SGX_ENABLE to take effect. Signed-off-by: Sean Christopherson Signed-off-by: Jarkko Sakkinen --- arch/x86/include/asm/msr-index.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index ca5bc0eacb95..6efaa8026c64 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -525,6 +525,7 @@ #define FEATURE_CONTROL_LOCKED (1<<0) #define FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX (1<<1) #define FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX (1<<2) +#define FEATURE_CONTROL_SGX_ENABLE (1<<18) #define FEATURE_CONTROL_LMCE (1<<20) #define MSR_IA32_APICBASE 0x0000001b From patchwork Sun Mar 17 21:14:33 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 10856601 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 690DA1390 for ; Sun, 17 Mar 2019 21:15:51 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 51C83291EE for ; Sun, 17 Mar 2019 21:15:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4571929214; Sun, 17 Mar 2019 21:15:51 +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 DF73B291EE for ; Sun, 17 Mar 2019 21:15:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726452AbfCQVPu (ORCPT ); Sun, 17 Mar 2019 17:15:50 -0400 Received: from mga17.intel.com ([192.55.52.151]:38487 "EHLO mga17.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726446AbfCQVPu (ORCPT ); Sun, 17 Mar 2019 17:15:50 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga107.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Mar 2019 14:15:50 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,491,1544515200"; d="scan'208";a="142816668" Received: from vanderss-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.254.193]) by orsmga002.jf.intel.com with ESMTP; 17 Mar 2019 14:15:42 -0700 From: Jarkko Sakkinen To: x86@kernel.org, linux-sgx@vger.kernel.org Cc: akpm@linux-foundation.org, dave.hansen@intel.com, sean.j.christopherson@intel.com, nhorman@redhat.com, npmccallum@redhat.com, serge.ayoun@intel.com, shay.katz-zamir@intel.com, haitao.huang@intel.com, andriy.shevchenko@linux.intel.com, tglx@linutronix.de, kai.svahn@intel.com, bp@alien8.de, josh@joshtriplett.org, luto@kernel.org, kai.huang@intel.com, rientjes@google.com, Kai Huang , Jarkko Sakkinen Subject: [PATCH v19 04/27] x86/cpufeatures: Add Intel-defined SGX_LC feature bit Date: Sun, 17 Mar 2019 23:14:33 +0200 Message-Id: <20190317211456.13927-5-jarkko.sakkinen@linux.intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> References: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> MIME-Version: 1.0 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 From: Kai Huang X86_FEATURE_SGX_LC reflects whether or not the CPU supports SGX Launch Control, i.e. enumerates the existence of IA32_FEATURE_CONTROL's SGX_LE_WR bit and the IA32_SGXLEPUBKEYHASH MSRs. Signed-off-by: Kai Huang Signed-off-by: Jarkko Sakkinen --- arch/x86/include/asm/cpufeatures.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index 313c58c04b51..c5080842ecad 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -346,6 +346,7 @@ #define X86_FEATURE_CLDEMOTE (16*32+25) /* CLDEMOTE instruction */ #define X86_FEATURE_MOVDIRI (16*32+27) /* MOVDIRI instruction */ #define X86_FEATURE_MOVDIR64B (16*32+28) /* MOVDIR64B instruction */ +#define X86_FEATURE_SGX_LC (16*32+30) /* Software Guard Extensions Launch Control */ /* AMD-defined CPU features, CPUID level 0x80000007 (EBX), word 17 */ #define X86_FEATURE_OVERFLOW_RECOV (17*32+ 0) /* MCA overflow recovery support */ From patchwork Sun Mar 17 21:14:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 10856603 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 CE7711575 for ; Sun, 17 Mar 2019 21:16:02 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B566A291EE for ; Sun, 17 Mar 2019 21:16:02 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A9BC929214; Sun, 17 Mar 2019 21:16: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 996D5291EE for ; Sun, 17 Mar 2019 21:16:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726452AbfCQVQB (ORCPT ); Sun, 17 Mar 2019 17:16:01 -0400 Received: from mga06.intel.com ([134.134.136.31]:23830 "EHLO mga06.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726446AbfCQVQB (ORCPT ); Sun, 17 Mar 2019 17:16:01 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Mar 2019 14:16:00 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,491,1544515200"; d="scan'208";a="142816679" Received: from vanderss-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.254.193]) by orsmga002.jf.intel.com with ESMTP; 17 Mar 2019 14:15:52 -0700 From: Jarkko Sakkinen To: x86@kernel.org, linux-sgx@vger.kernel.org Cc: akpm@linux-foundation.org, dave.hansen@intel.com, sean.j.christopherson@intel.com, nhorman@redhat.com, npmccallum@redhat.com, serge.ayoun@intel.com, shay.katz-zamir@intel.com, haitao.huang@intel.com, andriy.shevchenko@linux.intel.com, tglx@linutronix.de, kai.svahn@intel.com, bp@alien8.de, josh@joshtriplett.org, luto@kernel.org, kai.huang@intel.com, rientjes@google.com, Haim Cohen , Jarkko Sakkinen Subject: [PATCH v19 05/27] x86/msr: Add SGX Launch Control MSR definitions Date: Sun, 17 Mar 2019 23:14:34 +0200 Message-Id: <20190317211456.13927-6-jarkko.sakkinen@linux.intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> References: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> MIME-Version: 1.0 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 From: Sean Christopherson Add a new IA32_FEATURE_CONTROL bit, SGX_LE_WR. When set, SGX_LE_WR allows software to write the SGXLEPUBKEYHASH MSRs (see below). The The existence of the bit is enumerated by CPUID as X86_FEATURE_SGX_LC. Like all other flags in IA32_FEATURE_CONTROL, the MSR must be locked for SGX_LE_WR to take effect. Add four MSRs, SGXLEPUBKEYHASH{0,1,2,3}, or in human readable form, the SGX Launch Enclave Public Key Hash MSRs. These MSRs correspond to the key that is used by the CPU to determine whether or not to allow software to enter an enclave. When ENCLS[EINIT] is executed, which is a prerequisite to entering the enclave, the CPU compares the key (technically its hash) used to sign the enclave with the key hash stored in the MSRs, and will reject EINIT if the keys do not match. Enclaves can also be blessed by proxy, in which case a Launch Enclave generates and signs an EINIT TOKEN. If a valid token is provided, ENCLS[EINIT] compares the signer of the token against the MSRs instead of the signer of the enclave. The SGXLEPUBKEYHASH MSRs only exist on CPUs that support SGX Launch Control, enumerated by X86_FEATURE_SGX_LC. CPUs without Launch Control use a hardcoded key for the ENCLS[EINIT] checks. An internal hardcoded key is also used as the reset value for the hash MSRs when they exist. As a final note, the SGX_LEPUBKEYHASH MSRs can also be written by pre-boot firmware prior to activating SGX (SGX activation is done by setting bit 0 in MSR 0x7A). Thus, firmware can lock the MSRs to a non-Intel value by writing the MSRs and locking IA32_FEATURE_CONTROL without setting SGX_LE_WR. Signed-off-by: Sean Christopherson Co-developed-by: Haim Cohen Signed-off-by: Haim Cohen Signed-off-by: Jarkko Sakkinen --- arch/x86/include/asm/msr-index.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 6efaa8026c64..a4a22441d000 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -525,6 +525,7 @@ #define FEATURE_CONTROL_LOCKED (1<<0) #define FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX (1<<1) #define FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX (1<<2) +#define FEATURE_CONTROL_SGX_LE_WR (1<<17) #define FEATURE_CONTROL_SGX_ENABLE (1<<18) #define FEATURE_CONTROL_LMCE (1<<20) @@ -538,6 +539,12 @@ #define MSR_IA32_UCODE_WRITE 0x00000079 #define MSR_IA32_UCODE_REV 0x0000008b +/* Intel SGX Launch Enclave Public Key Hash MSRs */ +#define MSR_IA32_SGXLEPUBKEYHASH0 0x0000008C +#define MSR_IA32_SGXLEPUBKEYHASH1 0x0000008D +#define MSR_IA32_SGXLEPUBKEYHASH2 0x0000008E +#define MSR_IA32_SGXLEPUBKEYHASH3 0x0000008F + #define MSR_IA32_SMM_MONITOR_CTL 0x0000009b #define MSR_IA32_SMBASE 0x0000009e From patchwork Sun Mar 17 21:14:35 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 10856605 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 1DE141575 for ; Sun, 17 Mar 2019 21:16:13 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0491629200 for ; Sun, 17 Mar 2019 21:16:13 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E7C52291EE; Sun, 17 Mar 2019 21:16:12 +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 86C41291EE for ; Sun, 17 Mar 2019 21:16:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726452AbfCQVQM (ORCPT ); Sun, 17 Mar 2019 17:16:12 -0400 Received: from mga09.intel.com ([134.134.136.24]:9044 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726446AbfCQVQM (ORCPT ); Sun, 17 Mar 2019 17:16:12 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Mar 2019 14:16:11 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,491,1544515200"; d="scan'208";a="142816704" Received: from vanderss-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.254.193]) by orsmga002.jf.intel.com with ESMTP; 17 Mar 2019 14:16:02 -0700 From: Jarkko Sakkinen To: x86@kernel.org, linux-sgx@vger.kernel.org Cc: akpm@linux-foundation.org, dave.hansen@intel.com, sean.j.christopherson@intel.com, nhorman@redhat.com, npmccallum@redhat.com, serge.ayoun@intel.com, shay.katz-zamir@intel.com, haitao.huang@intel.com, andriy.shevchenko@linux.intel.com, tglx@linutronix.de, kai.svahn@intel.com, bp@alien8.de, josh@joshtriplett.org, luto@kernel.org, kai.huang@intel.com, rientjes@google.com, Dave Hansen , Jarkko Sakkinen Subject: [PATCH v19 06/27] x86/mm: x86/sgx: Add new 'PF_SGX' page fault error code bit Date: Sun, 17 Mar 2019 23:14:35 +0200 Message-Id: <20190317211456.13927-7-jarkko.sakkinen@linux.intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> References: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> MIME-Version: 1.0 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 From: Sean Christopherson The SGX bit is set in the #PF error code if and only if the fault is detected by the Enclave Page Cache Map (EPCM), a hardware-managed table that enforces the paging permissions defined by the enclave, e.g. to prevent the kernel from changing the permissions of an enclave's page(s). Despite triggering a #PF, a #PF with PF_SGX has nothing to do with paging. Cc: Dave Hansen Signed-off-by: Sean Christopherson Signed-off-by: Jarkko Sakkinen --- arch/x86/include/asm/traps.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h index 7d6f3f3fad78..c3e02912e9c7 100644 --- a/arch/x86/include/asm/traps.h +++ b/arch/x86/include/asm/traps.h @@ -171,5 +171,6 @@ enum x86_pf_error_code { X86_PF_RSVD = 1 << 3, X86_PF_INSTR = 1 << 4, X86_PF_PK = 1 << 5, + X86_PF_SGX = 1 << 15, }; #endif /* _ASM_X86_TRAPS_H */ From patchwork Sun Mar 17 21:14:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 10856607 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 5A6991390 for ; Sun, 17 Mar 2019 21:16:27 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3FF70291EE for ; Sun, 17 Mar 2019 21:16:27 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 345B629214; Sun, 17 Mar 2019 21:16:27 +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 B1580291EE for ; Sun, 17 Mar 2019 21:16:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726452AbfCQVQ0 (ORCPT ); Sun, 17 Mar 2019 17:16:26 -0400 Received: from mga04.intel.com ([192.55.52.120]:14837 "EHLO mga04.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726446AbfCQVQ0 (ORCPT ); Sun, 17 Mar 2019 17:16:26 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Mar 2019 14:16:25 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,491,1544515200"; d="scan'208";a="142816715" Received: from vanderss-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.254.193]) by orsmga002.jf.intel.com with ESMTP; 17 Mar 2019 14:16:13 -0700 From: Jarkko Sakkinen To: x86@kernel.org, linux-sgx@vger.kernel.org Cc: akpm@linux-foundation.org, dave.hansen@intel.com, sean.j.christopherson@intel.com, nhorman@redhat.com, npmccallum@redhat.com, serge.ayoun@intel.com, shay.katz-zamir@intel.com, haitao.huang@intel.com, andriy.shevchenko@linux.intel.com, tglx@linutronix.de, kai.svahn@intel.com, bp@alien8.de, josh@joshtriplett.org, luto@kernel.org, kai.huang@intel.com, rientjes@google.com, Andy Lutomirski , Dave Hansen , Jarkko Sakkinen Subject: [PATCH v19 07/27] x86/mm: x86/sgx: Signal SIGSEGV for userspace #PFs w/ PF_SGX Date: Sun, 17 Mar 2019 23:14:36 +0200 Message-Id: <20190317211456.13927-8-jarkko.sakkinen@linux.intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> References: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> MIME-Version: 1.0 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 From: Sean Christopherson The PF_SGX bit is set if and only if the #PF is detected by the SGX Enclave Page Cache Map (EPCM). The EPCM is a hardware-managed table that enforces accesses to an enclave's EPC pages in addition to the software-managed kernel page tables, i.e. the effective permissions for an EPC page are a logical AND of the kernel's page tables and the corresponding EPCM entry. The EPCM is consulted only after an access walks the kernel's page tables, i.e.: a. the access was allowed by the kernel b. the kernel's tables have become less restrictive than the EPCM c. the kernel cannot fixup the cause of the fault Noteably, (b) implies that either the kernel has botched the EPC mappings or the EPCM has been invalidated (see below). Regardless of why the fault occurred, userspace needs to be alerted so that it can take appropriate action, e.g. restart the enclave. This is reinforced by (c) as the kernel doesn't really have any other reasonable option, i.e. signalling SIGSEGV is actually the least severe action possible. Although the primary purpose of the EPCM is to prevent a malicious or compromised kernel from attacking an enclave, e.g. by modifying the enclave's page tables, do not WARN on a #PF w/ PF_SGX set. The SGX architecture effectively allows the CPU to invalidate all EPCM entries at will and requires that software be prepared to handle an EPCM fault at any time. The architecture defines this behavior because the EPCM is encrypted with an ephemeral key that isn't exposed to software. As such, the EPCM entries cannot be preserved across transitions that result in a new key being used, e.g. CPU power down as part of an S3 transition or when a VM is live migrated to a new physical system. Cc: Andy Lutomirski Cc: Dave Hansen Signed-off-by: Sean Christopherson Signed-off-by: Jarkko Sakkinen --- arch/x86/mm/fault.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 667f1da36208..78e2807fbede 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -1214,6 +1214,19 @@ access_error(unsigned long error_code, struct vm_area_struct *vma) if (error_code & X86_PF_PK) return 1; + /* + * Access is blocked by the Enclave Page Cache Map (EPCM), i.e. the + * access is allowed by the PTE but not the EPCM. This usually happens + * when the EPCM is yanked out from under us, e.g. by hardware after a + * suspend/resume cycle. In any case, software, i.e. the kernel, can't + * fix the source of the fault as the EPCM can't be directly modified + * by software. Handle the fault as an access error in order to signal + * userspace, e.g. so that userspace can rebuild their enclave(s), even + * though userspace may not have actually violated access permissions. + */ + if (unlikely(error_code & X86_PF_SGX)) + return 1; + /* * Make sure to check the VMA so that we do not perform * faults just to hit a X86_PF_PK as soon as we fill in a From patchwork Sun Mar 17 21:14:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 10856609 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 B43C51390 for ; Sun, 17 Mar 2019 21:16:36 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9B8DA291EE for ; Sun, 17 Mar 2019 21:16:36 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8F9E529214; Sun, 17 Mar 2019 21:16:36 +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 28FB9291EE for ; Sun, 17 Mar 2019 21:16:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727425AbfCQVQg (ORCPT ); Sun, 17 Mar 2019 17:16:36 -0400 Received: from mga03.intel.com ([134.134.136.65]:57841 "EHLO mga03.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726735AbfCQVQf (ORCPT ); Sun, 17 Mar 2019 17:16:35 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Mar 2019 14:16:35 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,491,1544515200"; d="scan'208";a="142816733" Received: from vanderss-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.254.193]) by orsmga002.jf.intel.com with ESMTP; 17 Mar 2019 14:16:26 -0700 From: Jarkko Sakkinen To: x86@kernel.org, linux-sgx@vger.kernel.org Cc: akpm@linux-foundation.org, dave.hansen@intel.com, sean.j.christopherson@intel.com, nhorman@redhat.com, npmccallum@redhat.com, serge.ayoun@intel.com, shay.katz-zamir@intel.com, haitao.huang@intel.com, andriy.shevchenko@linux.intel.com, tglx@linutronix.de, kai.svahn@intel.com, bp@alien8.de, josh@joshtriplett.org, luto@kernel.org, kai.huang@intel.com, rientjes@google.com, Jarkko Sakkinen Subject: [PATCH v19 08/27] x86/cpu/intel: Detect SGX support and update caps appropriately Date: Sun, 17 Mar 2019 23:14:37 +0200 Message-Id: <20190317211456.13927-9-jarkko.sakkinen@linux.intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> References: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> MIME-Version: 1.0 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 From: Sean Christopherson Similar to other large Intel features such as VMX and TXT, SGX must be explicitly enabled in IA32_FEATURE_CONTROL MSR to be truly usable. Clear all SGX related capabilities if SGX is not fully enabled in IA32_FEATURE_CONTROL or if the SGX1 instruction set isn't supported (impossible on bare metal, theoretically possible in a VM if the VMM is doing something weird). Like SGX itself, SGX Launch Control must be explicitly enabled via a flag in IA32_FEATURE_CONTROL. Clear the SGX_LC capability if Launch Control is not fully enabled (or obviously if SGX itself is disabled). Note that clearing X86_FEATURE_SGX_LC creates a bit of a conundrum regarding the SGXLEPUBKEYHASH MSRs, as it may be desirable to read the MSRs even if they are not writable, e.g. to query the configured key, but clearing the capability leaves no breadcrum for discerning whether or not the MSRs exist. But, such usage will be rare (KVM is the only known case at this time) and not performance critical, so it's not unreasonable to require the use of rdmsr_safe(). Clearing the cap bit eliminates the need for an additional flag to track whether or not Launch Control is truly enabled, which is what we care about the vast majority of the time. Signed-off-by: Sean Christopherson Co-developed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen --- arch/x86/kernel/cpu/intel.c | 39 +++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index fc3c07fe7df5..702497f34a96 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -596,6 +596,42 @@ static void detect_tme(struct cpuinfo_x86 *c) c->x86_phys_bits -= keyid_bits; } +static void __maybe_unused detect_sgx(struct cpuinfo_x86 *c) +{ + unsigned long long fc; + + rdmsrl(MSR_IA32_FEATURE_CONTROL, fc); + if (!(fc & FEATURE_CONTROL_LOCKED)) { + pr_err_once("sgx: The feature control MSR is not locked\n"); + goto err_unsupported; + } + + if (!(fc & FEATURE_CONTROL_SGX_ENABLE)) { + pr_err_once("sgx: SGX is not enabled in IA32_FEATURE_CONTROL MSR\n"); + goto err_unsupported; + } + + if (!cpu_has(c, X86_FEATURE_SGX1)) { + pr_err_once("sgx: SGX1 instruction set is not supported\n"); + goto err_unsupported; + } + + if (!(fc & FEATURE_CONTROL_SGX_LE_WR)) { + pr_info_once("sgx: The launch control MSRs are not writable\n"); + goto err_msrs_rdonly; + } + + return; + +err_unsupported: + setup_clear_cpu_cap(X86_FEATURE_SGX); + setup_clear_cpu_cap(X86_FEATURE_SGX1); + setup_clear_cpu_cap(X86_FEATURE_SGX2); + +err_msrs_rdonly: + setup_clear_cpu_cap(X86_FEATURE_SGX_LC); +} + static void init_intel_energy_perf(struct cpuinfo_x86 *c) { u64 epb; @@ -763,6 +799,9 @@ static void init_intel(struct cpuinfo_x86 *c) if (cpu_has(c, X86_FEATURE_TME)) detect_tme(c); + if (IS_ENABLED(CONFIG_INTEL_SGX) && cpu_has(c, X86_FEATURE_SGX)) + detect_sgx(c); + init_intel_energy_perf(c); init_intel_misc_features(c); From patchwork Sun Mar 17 21:14:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 10856611 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 B2FE01575 for ; Sun, 17 Mar 2019 21:16:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9AC34291EE for ; Sun, 17 Mar 2019 21:16:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8E6D329214; Sun, 17 Mar 2019 21:16:47 +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 0EA83291EE for ; Sun, 17 Mar 2019 21:16:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726452AbfCQVQq (ORCPT ); Sun, 17 Mar 2019 17:16:46 -0400 Received: from mga05.intel.com ([192.55.52.43]:8257 "EHLO mga05.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726446AbfCQVQq (ORCPT ); Sun, 17 Mar 2019 17:16:46 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Mar 2019 14:16:46 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,491,1544515200"; d="scan'208";a="142816783" Received: from vanderss-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.254.193]) by orsmga002.jf.intel.com with ESMTP; 17 Mar 2019 14:16:37 -0700 From: Jarkko Sakkinen To: x86@kernel.org, linux-sgx@vger.kernel.org Cc: akpm@linux-foundation.org, dave.hansen@intel.com, sean.j.christopherson@intel.com, nhorman@redhat.com, npmccallum@redhat.com, serge.ayoun@intel.com, shay.katz-zamir@intel.com, haitao.huang@intel.com, andriy.shevchenko@linux.intel.com, tglx@linutronix.de, kai.svahn@intel.com, bp@alien8.de, josh@joshtriplett.org, luto@kernel.org, kai.huang@intel.com, rientjes@google.com, Jarkko Sakkinen Subject: [PATCH v19 09/27] x86/sgx: Add ENCLS architectural error codes Date: Sun, 17 Mar 2019 23:14:38 +0200 Message-Id: <20190317211456.13927-10-jarkko.sakkinen@linux.intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> References: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> MIME-Version: 1.0 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 SGX architecture defines an extensive set of error codes that are used by ENCL{S,U,V} instructions to provide software with (somewhat) precise error information. Though they are architectural, define the known error codes in a separate file from sgx_arch.h so that they can be exposed to userspace. For some ENCLS leafs, e.g. EINIT, returning the exact error code on failure can enable userspace to make informed decisions when an operation fails. Signed-off-by: Jarkko Sakkinen Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson --- arch/x86/include/uapi/asm/sgx_errno.h | 91 +++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 arch/x86/include/uapi/asm/sgx_errno.h diff --git a/arch/x86/include/uapi/asm/sgx_errno.h b/arch/x86/include/uapi/asm/sgx_errno.h new file mode 100644 index 000000000000..48b87aed58d7 --- /dev/null +++ b/arch/x86/include/uapi/asm/sgx_errno.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* + * Copyright(c) 2018 Intel Corporation. + * + * Contains the architecturally defined error codes that are returned by SGX + * instructions, e.g. ENCLS, and may be propagated to userspace via errno. + */ + +#ifndef _UAPI_ASM_X86_SGX_ERRNO_H +#define _UAPI_ASM_X86_SGX_ERRNO_H + +/** + * enum sgx_encls_leaves - return codes for ENCLS, ENCLU and ENCLV + * %SGX_SUCCESS: No error. + * %SGX_INVALID_SIG_STRUCT: SIGSTRUCT contains an invalid value. + * %SGX_INVALID_ATTRIBUTE: Enclave is not attempting to access a resource + * for which it is not authorized. + * %SGX_BLKSTATE: EPC page is already blocked. + * %SGX_INVALID_MEASUREMENT: SIGSTRUCT or EINITTOKEN contains an incorrect + * measurement. + * %SGX_NOTBLOCKABLE: EPC page type is not one which can be blocked. + * %SGX_PG_INVLD: EPC page is invalid (and cannot be blocked). + * %SGX_EPC_PAGE_CONFLICT: EPC page in use by another SGX instruction. + * %SGX_INVALID_SIGNATURE: Enclave's signature does not validate with + * public key enclosed in SIGSTRUCT. + * %SGX_MAC_COMPARE_FAIL: MAC check failed when reloading EPC page. + * %SGX_PAGE_NOT_BLOCKED: EPC page is not marked as blocked. + * %SGX_NOT_TRACKED: ETRACK has not been completed on the EPC page. + * %SGX_VA_SLOT_OCCUPIED: Version array slot contains a valid entry. + * %SGX_CHILD_PRESENT: Enclave has child pages present in the EPC. + * %SGX_ENCLAVE_ACT: Logical processors are currently executing + * inside the enclave. + * %SGX_ENTRYEPOCH_LOCKED: SECS locked for EPOCH update, i.e. an ETRACK is + * currently executing on the SECS. + * %SGX_INVALID_EINITTOKEN: EINITTOKEN is invalid and enclave signer's + * public key does not match IA32_SGXLEPUBKEYHASH. + * %SGX_PREV_TRK_INCMPL: All processors did not complete the previous + * tracking sequence. + * %SGX_PG_IS_SECS: Target EPC page is an SECS and cannot be + * blocked. + * %SGX_PAGE_ATTRIBUTES_MISMATCH: Attributes of the EPC page do not match + * the expected values. + * %SGX_PAGE_NOT_MODIFIABLE: EPC page cannot be modified because it is in + * the PENDING or MODIFIED state. + * %SGX_PAGE_NOT_DEBUGGABLE: EPC page cannot be modified because it is in + * the PENDING or MODIFIED state. + * %SGX_INVALID_COUNTER: {In,De}crementing a counter would cause it to + * {over,under}flow. + * %SGX_PG_NONEPC: Target page is not an EPC page. + * %SGX_TRACK_NOT_REQUIRED: Target page type does not require tracking. + * %SGX_INVALID_CPUSVN: Security version number reported by CPU is less + * than what is required by the enclave. + * %SGX_INVALID_ISVSVN: Security version number of enclave is less than + * what is required by the KEYREQUEST struct. + * %SGX_UNMASKED_EVENT: An unmasked event, e.g. INTR, was received + * while the instruction was executing. + * %SGX_INVALID_KEYNAME: Requested key is not supported by hardware. + */ +enum sgx_return_codes { + SGX_SUCCESS = 0, + SGX_INVALID_SIG_STRUCT = 1, + SGX_INVALID_ATTRIBUTE = 2, + SGX_BLKSTATE = 3, + SGX_INVALID_MEASUREMENT = 4, + SGX_NOTBLOCKABLE = 5, + SGX_PG_INVLD = 6, + SGX_EPC_PAGE_CONFLICT = 7, + SGX_INVALID_SIGNATURE = 8, + SGX_MAC_COMPARE_FAIL = 9, + SGX_PAGE_NOT_BLOCKED = 10, + SGX_NOT_TRACKED = 11, + SGX_VA_SLOT_OCCUPIED = 12, + SGX_CHILD_PRESENT = 13, + SGX_ENCLAVE_ACT = 14, + SGX_ENTRYEPOCH_LOCKED = 15, + SGX_INVALID_EINITTOKEN = 16, + SGX_PREV_TRK_INCMPL = 17, + SGX_PG_IS_SECS = 18, + SGX_PAGE_ATTRIBUTES_MISMATCH = 19, + SGX_PAGE_NOT_MODIFIABLE = 20, + SGX_PAGE_NOT_DEBUGGABLE = 21, + SGX_INVALID_COUNTER = 25, + SGX_PG_NONEPC = 26, + SGX_TRACK_NOT_REQUIRED = 27, + SGX_INVALID_CPUSVN = 32, + SGX_INVALID_ISVSVN = 64, + SGX_UNMASKED_EVENT = 128, + SGX_INVALID_KEYNAME = 256, +}; + +#endif /* _UAPI_ASM_X86_SGX_ERRNO_H */ From patchwork Sun Mar 17 21:14:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 10856613 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 C31011390 for ; Sun, 17 Mar 2019 21:17:00 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A9F11291EE for ; Sun, 17 Mar 2019 21:17:00 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9B1FF29214; Sun, 17 Mar 2019 21:17:00 +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 840FC291EE for ; Sun, 17 Mar 2019 21:16:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726452AbfCQVQ7 (ORCPT ); Sun, 17 Mar 2019 17:16:59 -0400 Received: from mga18.intel.com ([134.134.136.126]:64752 "EHLO mga18.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726446AbfCQVQ7 (ORCPT ); Sun, 17 Mar 2019 17:16:59 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Mar 2019 14:16:56 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,491,1544515200"; d="scan'208";a="142816830" Received: from vanderss-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.254.193]) by orsmga002.jf.intel.com with ESMTP; 17 Mar 2019 14:16:48 -0700 From: Jarkko Sakkinen To: x86@kernel.org, linux-sgx@vger.kernel.org Cc: akpm@linux-foundation.org, dave.hansen@intel.com, sean.j.christopherson@intel.com, nhorman@redhat.com, npmccallum@redhat.com, serge.ayoun@intel.com, shay.katz-zamir@intel.com, haitao.huang@intel.com, andriy.shevchenko@linux.intel.com, tglx@linutronix.de, kai.svahn@intel.com, bp@alien8.de, josh@joshtriplett.org, luto@kernel.org, kai.huang@intel.com, rientjes@google.com, Jarkko Sakkinen Subject: [PATCH v19 10/27] x86/sgx: Add SGX1 and SGX2 architectural data structures Date: Sun, 17 Mar 2019 23:14:39 +0200 Message-Id: <20190317211456.13927-11-jarkko.sakkinen@linux.intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> References: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> MIME-Version: 1.0 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 Define the data structures used by various ENCLS functions needed for Linux to support all SGX1 and SGX2 ENCLS leaf functions. This is not an exhaustive representation of all SGX data structures as several are only consumed by ENCLU (userspace), e.g. REPORT and KEYREQUEST, while others are only consumed by future features, e.g. RDINFO. Signed-off-by: Jarkko Sakkinen Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson --- arch/x86/kernel/cpu/sgx/arch.h | 409 +++++++++++++++++++++++++++++++++ 1 file changed, 409 insertions(+) create mode 100644 arch/x86/kernel/cpu/sgx/arch.h diff --git a/arch/x86/kernel/cpu/sgx/arch.h b/arch/x86/kernel/cpu/sgx/arch.h new file mode 100644 index 000000000000..7a2f293db32c --- /dev/null +++ b/arch/x86/kernel/cpu/sgx/arch.h @@ -0,0 +1,409 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/** + * Copyright(c) 2016-18 Intel Corporation. + * + * Contains data structures defined by the SGX architecture. Data structures + * defined by the Linux software stack should not be placed here. + */ +#ifndef _ASM_X86_SGX_ARCH_H +#define _ASM_X86_SGX_ARCH_H + +#include + +/** + * enum sgx_encls_leaves - ENCLS leaf functions + * %SGX_ECREATE: Create an enclave. + * %SGX_EADD: Add a page to an uninitialized enclave. + * %SGX_EINIT: Initialize an enclave, i.e. launch an enclave. + * %SGX_EREMOVE: Remove a page from an enclave. + * %SGX_EDBGRD: Read a word from an enclve (peek). + * %SGX_EDBGWR: Write a word to an enclave (poke). + * %SGX_EEXTEND: Measure 256 bytes of an added enclave page. + * %SGX_ELDB: Load a swapped page in blocked state. + * %SGX_ELDU: Load a swapped page in unblocked state. + * %SGX_EBLOCK: Change page state to blocked i.e. entering hardware + * threads cannot access it and create new TLB entries. + * %SGX_EPA: Create a Version Array (VA) page used to store isvsvn + * number for a swapped EPC page. + * %SGX_EWB: Swap an enclave page to the regular memory. Checks that + * all threads have exited that were in the previous + * shoot-down sequence. + * %SGX_ETRACK: Start a new shoot down sequence. Used to together with + * EBLOCK to make sure that a page is safe to swap. + * %SGX_EAUG: Add a page to an initialized enclave. + * %SGX_EMODPR: Restrict an EPC page's permissions. + * %SGX_EMODT: Modify the page type of an EPC page. + */ +enum sgx_encls_leaves { + SGX_ECREATE = 0x00, + SGX_EADD = 0x01, + SGX_EINIT = 0x02, + SGX_EREMOVE = 0x03, + SGX_EDGBRD = 0x04, + SGX_EDGBWR = 0x05, + SGX_EEXTEND = 0x06, + SGX_ELDB = 0x07, + SGX_ELDU = 0x08, + SGX_EBLOCK = 0x09, + SGX_EPA = 0x0A, + SGX_EWB = 0x0B, + SGX_ETRACK = 0x0C, + SGX_EAUG = 0x0D, + SGX_EMODPR = 0x0E, + SGX_EMODT = 0x0F, +}; + +#define SGX_MODULUS_SIZE 384 + +/** + * enum sgx_miscselect - additional information to an SSA frame + * %SGX_MISC_EXINFO: Report #PF or #GP to the SSA frame. + * + * Save State Area (SSA) is a stack inside the enclave used to store processor + * state when an exception or interrupt occurs. This enum defines additional + * information stored to an SSA frame. + */ +enum sgx_miscselect { + SGX_MISC_EXINFO = BIT(0), + SGX_MISC_RESERVED_MASK = GENMASK_ULL(63, 1) +}; + +#define SGX_SSA_GPRS_SIZE 182 +#define SGX_SSA_MISC_EXINFO_SIZE 16 + +/** + * enum sgx_attributes - the attributes field in &struct sgx_secs + * %SGX_ATTR_INIT: Enclave can be entered (is initialized). + * %SGX_ATTR_DEBUG: Allow ENCLS(EDBGRD) and ENCLS(EDBGWR). + * %SGX_ATTR_MODE64BIT: Tell that this a 64-bit enclave. + * %SGX_ATTR_PROVISIONKEY: Allow to use provisioning keys for remote + * attestation. + * %SGX_ATTR_KSS: Allow to use key separation and sharing (KSS). + * %SGX_ATTR_EINITTOKENKEY: Allow to use token signing key that is used to + * sign cryptographic tokens that can be passed to + * EINIT as an authorization to run an enclave. + */ +enum sgx_attribute { + SGX_ATTR_INIT = BIT(0), + SGX_ATTR_DEBUG = BIT(1), + SGX_ATTR_MODE64BIT = BIT(2), + SGX_ATTR_PROVISIONKEY = BIT(4), + SGX_ATTR_EINITTOKENKEY = BIT(5), + SGX_ATTR_KSS = BIT(7), + SGX_ATTR_RESERVED_MASK = BIT_ULL(3) | + BIT_ULL(7) | + GENMASK_ULL(63, 8), + SGX_ATTR_ALLOWED_MASK = SGX_ATTR_DEBUG | + SGX_ATTR_MODE64BIT | + SGX_ATTR_KSS, +}; + +#define SGX_SECS_RESERVED1_SIZE 24 +#define SGX_SECS_RESERVED2_SIZE 32 +#define SGX_SECS_RESERVED3_SIZE 96 +#define SGX_SECS_RESERVED4_SIZE 3836 + +/** + * struct sgx_secs - SGX Enclave Control Structure (SECS) + * @size: size of the address space + * @base: base address of the address space + * @ssa_frame_size: size of an SSA frame + * @miscselect: additional information stored to an SSA frame + * @attributes: attributes for enclave + * @xfrm: XSave-Feature Request Mask (subset of XCR0) + * @mrenclave: SHA256-hash of the enclave contents + * @mrsigner: SHA256-hash of the public key used to sign the SIGSTRUCT + * @isvprodid: a user-defined value that is used in key derivation + * @isvsvn: a user-defined value that is used in key derivation + * + * SGX Enclave Control Structure (SECS) is a special enclave page that is not + * visible in the address space. In fact, this structure defines the address + * range and other global attributes for the enclave and it is the first EPC + * page created for any enclave. It is moved from a temporary buffer to an EPC + * by the means of ENCLS(ECREATE) leaf. + */ +struct sgx_secs { + u64 size; + u64 base; + u32 ssa_frame_size; + u32 miscselect; + u8 reserved1[SGX_SECS_RESERVED1_SIZE]; + u64 attributes; + u64 xfrm; + u32 mrenclave[8]; + u8 reserved2[SGX_SECS_RESERVED2_SIZE]; + u32 mrsigner[8]; + u8 reserved3[SGX_SECS_RESERVED3_SIZE]; + u16 isvprodid; + u16 isvsvn; + u8 reserved4[SGX_SECS_RESERVED4_SIZE]; +} __packed; + +/** + * enum sgx_tcs_flags - execution flags for TCS + * %SGX_TCS_DBGOPTIN: If enabled allows single-stepping and breakpoints + * inside an enclave. It is cleared by EADD but can + * be set later with EDBGWR. + */ +enum sgx_tcs_flags { + SGX_TCS_DBGOPTIN = 0x01, + SGX_TCS_RESERVED_MASK = GENMASK_ULL(63, 1) +}; + +#define SGX_TCS_RESERVED_SIZE 4024 + +/** + * struct sgx_tcs - Thread Control Structure (TCS) + * @state: used to mark an entered TCS + * @flags: execution flags (cleared by EADD) + * @ssa_offset: SSA stack offset relative to the enclave base + * @ssa_index: the current SSA frame index (cleard by EADD) + * @nr_ssa_frames: the number of frame in the SSA stack + * @entry_offset: entry point offset relative to the enclave base + * @exit_addr: address outside the enclave to exit on an exception or + * interrupt + * @fs_offset: offset relative to the enclave base to become FS + * segment inside the enclave + * @gs_offset: offset relative to the enclave base to become GS + * segment inside the enclave + * @fs_limit: size to become a new FS-limit (only 32-bit enclaves) + * @gs_limit: size to become a new GS-limit (only 32-bit enclaves) + * + * Thread Control Structure (TCS) is an enclave page visible in its address + * space that defines an entry point inside the enclave. A thread enters inside + * an enclave by supplying address of TCS to ENCLU(EENTER). A TCS can be entered + * by only one thread at a time. + */ +struct sgx_tcs { + u64 state; + u64 flags; + u64 ssa_offset; + u32 ssa_index; + u32 nr_ssa_frames; + u64 entry_offset; + u64 exit_addr; + u64 fs_offset; + u64 gs_offset; + u32 fs_limit; + u32 gs_limit; + u8 reserved[SGX_TCS_RESERVED_SIZE]; +} __packed; + +/** + * struct sgx_pageinfo - an enclave page descriptor + * @addr: address of the enclave page + * @contents: pointer to the page contents + * @metadata: pointer either to a SECINFO or PCMD instance + * @secs: address of the SECS page + */ +struct sgx_pageinfo { + u64 addr; + u64 contents; + u64 metadata; + u64 secs; +} __packed __aligned(32); + + +/** + * enum sgx_page_type - bits in the SECINFO flags defining the page type + * %SGX_PAGE_TYPE_SECS: a SECS page + * %SGX_PAGE_TYPE_TCS: a TCS page + * %SGX_PAGE_TYPE_REG: a regular page + * %SGX_PAGE_TYPE_VA: a VA page + * %SGX_PAGE_TYPE_TRIM: a page in trimmed state + */ +enum sgx_page_type { + SGX_PAGE_TYPE_SECS = 0, + SGX_PAGE_TYPE_TCS = 1, + SGX_PAGE_TYPE_REG = 2, + SGX_PAGE_TYPE_VA = 3, + SGX_PAGE_TYPE_TRIM = 4, + SGX_PAGE_TYPE_MASK = GENMASK(7, 0) +}; + +/** + * enum sgx_secinfo_flags - the flags field in &struct sgx_secinfo + * %SGX_SECINFO_R: allow read + * %SGX_SECINFO_W: allow write + * %SGX_SECINFO_X: allow execution + * %SGX_SECINFO_SECS: a SECS page + * %SGX_SECINFO_TCS: a TCS page + * %SGX_SECINFO_REG: a regular page + * %SGX_SECINFO_VA: a VA page + * %SGX_SECINFO_TRIM: a page in trimmed state + */ +enum sgx_secinfo_flags { + SGX_SECINFO_R = BIT(0), + SGX_SECINFO_W = BIT(1), + SGX_SECINFO_X = BIT(2), + SGX_SECINFO_PERMISSION_MASK = GENMASK_ULL(2, 0), + SGX_SECINFO_SECS = (SGX_PAGE_TYPE_SECS << 8), + SGX_SECINFO_TCS = (SGX_PAGE_TYPE_TCS << 8), + SGX_SECINFO_REG = (SGX_PAGE_TYPE_REG << 8), + SGX_SECINFO_VA = (SGX_PAGE_TYPE_VA << 8), + SGX_SECINFO_TRIM = (SGX_PAGE_TYPE_TRIM << 8), + SGX_SECINFO_PAGE_TYPE_MASK = (SGX_PAGE_TYPE_MASK << 8), + SGX_SECINFO_RESERVED_MASK = ~(SGX_SECINFO_PERMISSION_MASK | + SGX_SECINFO_PAGE_TYPE_MASK) +}; + +#define SGX_SECINFO_RESERVED_SIZE 56 + +/** + * struct sgx_secinfo - describes attributes of an EPC page + * @flags: permissions and type + * + * Used together with ENCLS leaves that add or modify an EPC page to an + * enclave to define page permissions and type. + */ +struct sgx_secinfo { + u64 flags; + u8 reserved[SGX_SECINFO_RESERVED_SIZE]; +} __packed __aligned(64); + +#define SGX_PCMD_RESERVED_SIZE 40 + +/** + * struct sgx_pcmd - Paging Crypto Metadata (PCMD) + * @enclave_id: enclave identifier + * @mac: MAC over PCMD, page contents and isvsvn + * + * PCMD is stored for every swapped page to the regular memory. When ELDU loads + * the page back it recalculates the MAC by using a isvsvn number stored in a + * VA page. Together these two structures bring integrity and rollback + * protection. + */ +struct sgx_pcmd { + struct sgx_secinfo secinfo; + u64 enclave_id; + u8 reserved[SGX_PCMD_RESERVED_SIZE]; + u8 mac[16]; +} __packed __aligned(128); + +#define SGX_SIGSTRUCT_RESERVED1_SIZE 84 +#define SGX_SIGSTRUCT_RESERVED2_SIZE 20 +#define SGX_SIGSTRUCT_RESERVED3_SIZE 32 +#define SGX_SIGSTRUCT_RESERVED4_SIZE 12 + +/** + * struct sgx_sigstruct_header - defines author of the enclave + * @header1: constant byte string + * @vendor: must be either 0x0000 or 0x8086 + * @date: YYYYMMDD in BCD + * @header2: costant byte string + * @swdefined: software defined value + */ +struct sgx_sigstruct_header { + u64 header1[2]; + u32 vendor; + u32 date; + u64 header2[2]; + u32 swdefined; + u8 reserved1[84]; +} __packed; + +/** + * struct sgx_sigstruct_body - defines contents of the enclave + * @miscselect: additional information stored to an SSA frame + * @misc_mask: required miscselect in SECS + * @attributes: attributes for enclave + * @xfrm: XSave-Feature Request Mask (subset of XCR0) + * @attributes_mask: required attributes in SECS + * @xfrm_mask: required XFRM in SECS + * @mrenclave: SHA256-hash of the enclave contents + * @isvprodid: a user-defined value that is used in key derivation + * @isvsvn: a user-defined value that is used in key derivation + */ +struct sgx_sigstruct_body { + u32 miscselect; + u32 misc_mask; + u8 reserved2[20]; + u64 attributes; + u64 xfrm; + u64 attributes_mask; + u64 xfrm_mask; + u8 mrenclave[32]; + u8 reserved3[32]; + u16 isvprodid; + u16 isvsvn; +} __packed; + +/** + * struct sgx_sigstruct - an enclave signature + * @header: defines author of the enclave + * @modulus: the modulus of the public key + * @exponent: the exponent of the public key + * @signature: the signature calculated over the fields except modulus, + * @body: defines contents of the enclave + * @q1: a value used in RSA signature verification + * @q2: a value used in RSA signature verification + * + * Header and body are the parts that are actual signed. The remaining fields + * define the signature of the enclave. + */ +struct sgx_sigstruct { + struct sgx_sigstruct_header header; + u8 modulus[SGX_MODULUS_SIZE]; + u32 exponent; + u8 signature[SGX_MODULUS_SIZE]; + struct sgx_sigstruct_body body; + u8 reserved4[12]; + u8 q1[SGX_MODULUS_SIZE]; + u8 q2[SGX_MODULUS_SIZE]; +} __packed; + +#define SGX_EINITTOKEN_RESERVED1_SIZE 11 +#define SGX_EINITTOKEN_RESERVED2_SIZE 32 +#define SGX_EINITTOKEN_RESERVED3_SIZE 32 +#define SGX_EINITTOKEN_RESERVED4_SIZE 24 + +/** + * struct sgx_einittoken - a token permitting to launch an enclave + * @valid: one if valid and zero if invalid + * @attributes: attributes for enclave + * @xfrm: XSave-Feature Request Mask (subset of XCR0) + * @mrenclave: SHA256-hash of the enclave contents + * @mrsigner: SHA256-hash of the public key used to sign the + * SIGSTRUCT + * @le_cpusvn: a value that reflects the SGX implementation + * running in in the CPU + * @le_isvprodid: a user-defined value that is used in key + * derivation + * @le_isvsvn: a user-defined value that is used in key + * derivation + * @le_keyed_miscselect: LE's miscselect masked with the token keys + * miscselect + * @le_keyed_attributes: LE's attributes masked with the token keys + * attributes + * @le_keyed_xfrm: LE's XFRM masked with the token keys xfrm + * @salt: random salt for wear-out protection + * @mac: CMAC over the preceding fields + * + * An enclave with EINITTOKENKEY attribute can access a key with the same name + * by using ENCLS(EGETKEY) and use this to sign cryptographic tokens that can + * be passed to ENCLS(EINIT) to permit the launch of other enclaves. This is + * the only viable way to launch enclaves if IA32_SGXLEPUBKEYHASHn MSRs are + * locked assuming that there is a Launch Enclave (LE) available that can be + * used for generating these tokens. + */ +struct sgx_einittoken { + u32 valid; + u32 reserved1[SGX_EINITTOKEN_RESERVED1_SIZE]; + u64 attributes; + u64 xfrm; + u8 mrenclave[32]; + u8 reserved2[SGX_EINITTOKEN_RESERVED2_SIZE]; + u8 mrsigner[32]; + u8 reserved3[SGX_EINITTOKEN_RESERVED3_SIZE]; + u8 le_cpusvn[16]; + u16 le_isvprodid; + u16 le_isvsvn; + u8 reserved4[SGX_EINITTOKEN_RESERVED4_SIZE]; + u32 le_keyed_miscselect; + u64 le_keyed_attributes; + u64 le_keyed_xfrm; + u8 salt[32]; + u8 mac[16]; +} __packed __aligned(512); + +#endif /* _ASM_X86_SGX_ARCH_H */ From patchwork Sun Mar 17 21:14:40 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 10856615 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 417FB1390 for ; Sun, 17 Mar 2019 21:17:08 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2857C291EE for ; Sun, 17 Mar 2019 21:17:08 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 18B4229214; Sun, 17 Mar 2019 21:17:08 +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 B4899291EE for ; Sun, 17 Mar 2019 21:17:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726446AbfCQVRH (ORCPT ); Sun, 17 Mar 2019 17:17:07 -0400 Received: from mga07.intel.com ([134.134.136.100]:4078 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726452AbfCQVRH (ORCPT ); Sun, 17 Mar 2019 17:17:07 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Mar 2019 14:17:06 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,491,1544515200"; d="scan'208";a="142816891" Received: from vanderss-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.254.193]) by orsmga002.jf.intel.com with ESMTP; 17 Mar 2019 14:16:58 -0700 From: Jarkko Sakkinen To: x86@kernel.org, linux-sgx@vger.kernel.org Cc: akpm@linux-foundation.org, dave.hansen@intel.com, sean.j.christopherson@intel.com, nhorman@redhat.com, npmccallum@redhat.com, serge.ayoun@intel.com, shay.katz-zamir@intel.com, haitao.huang@intel.com, andriy.shevchenko@linux.intel.com, tglx@linutronix.de, kai.svahn@intel.com, bp@alien8.de, josh@joshtriplett.org, luto@kernel.org, kai.huang@intel.com, rientjes@google.com, Jarkko Sakkinen Subject: [PATCH v19 11/27] x86/sgx: Add definitions for SGX's CPUID leaf and variable sub-leafs Date: Sun, 17 Mar 2019 23:14:40 +0200 Message-Id: <20190317211456.13927-12-jarkko.sakkinen@linux.intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> References: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> MIME-Version: 1.0 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 SGX defines its own CPUID leaf, 0x12, along with a variable number of sub-leafs. Sub-leafs 0 and 1 are always available if SGX is supported and enumerate various SGX features, e.g. instruction sets and enclave capabilities. Sub-leafs 2+ are variable, both in their existence and in what they enumerate. Bits 3:0 of EAX report the sub-leaf type, with the remaining bits in EAX, EBX, ECX and EDX being type-specific. Currently, the only known sub-leaf type enumerates an EPC section. An EPC section is simply a range of EPC memory available to software. The "list" of varaible SGX sub-leafs is NULL-terminated, i.e. software is expected to query CPUID until an invalid sub-leaf is encountered. Signed-off-by: Jarkko Sakkinen Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson --- arch/x86/kernel/cpu/sgx/arch.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/x86/kernel/cpu/sgx/arch.h b/arch/x86/kernel/cpu/sgx/arch.h index 7a2f293db32c..e966cdd68040 100644 --- a/arch/x86/kernel/cpu/sgx/arch.h +++ b/arch/x86/kernel/cpu/sgx/arch.h @@ -10,6 +10,21 @@ #include +#define SGX_CPUID 0x12 +#define SGX_CPUID_FIRST_VARIABLE_SUB_LEAF 2 + +/** + * enum sgx_sub_leaf_types - SGX CPUID variable sub-leaf types + * %SGX_CPUID_SUB_LEAF_INVALID: Indicates this sub-leaf is invalid. + * %SGX_CPUID_SUB_LEAF_EPC_SECTION: Sub-leaf enumerates an EPC section. + * %SGX_CPUID_SUB_LEAF_TYPE_MASK: Mask for bits containing the type. + */ +enum sgx_sub_leaf_types { + SGX_CPUID_SUB_LEAF_INVALID = 0x0, + SGX_CPUID_SUB_LEAF_EPC_SECTION = 0x1, + SGX_CPUID_SUB_LEAF_TYPE_MASK = GENMASK(3, 0), +}; + /** * enum sgx_encls_leaves - ENCLS leaf functions * %SGX_ECREATE: Create an enclave. From patchwork Sun Mar 17 21:14:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 10856617 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 55DE11390 for ; Sun, 17 Mar 2019 21:17:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3B49C291EE for ; Sun, 17 Mar 2019 21:17:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2FA8F29214; Sun, 17 Mar 2019 21:17:20 +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 6971C291EE for ; Sun, 17 Mar 2019 21:17:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726452AbfCQVRS (ORCPT ); Sun, 17 Mar 2019 17:17:18 -0400 Received: from mga09.intel.com ([134.134.136.24]:9117 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726446AbfCQVRS (ORCPT ); Sun, 17 Mar 2019 17:17:18 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Mar 2019 14:17:17 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,491,1544515200"; d="scan'208";a="142816965" Received: from vanderss-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.254.193]) by orsmga002.jf.intel.com with ESMTP; 17 Mar 2019 14:17:08 -0700 From: Jarkko Sakkinen To: x86@kernel.org, linux-sgx@vger.kernel.org Cc: akpm@linux-foundation.org, dave.hansen@intel.com, sean.j.christopherson@intel.com, nhorman@redhat.com, npmccallum@redhat.com, serge.ayoun@intel.com, shay.katz-zamir@intel.com, haitao.huang@intel.com, andriy.shevchenko@linux.intel.com, tglx@linutronix.de, kai.svahn@intel.com, bp@alien8.de, josh@joshtriplett.org, luto@kernel.org, kai.huang@intel.com, rientjes@google.com, Jarkko Sakkinen , Suresh Siddha Subject: [PATCH v19 12/27] x86/sgx: Enumerate and track EPC sections Date: Sun, 17 Mar 2019 23:14:41 +0200 Message-Id: <20190317211456.13927-13-jarkko.sakkinen@linux.intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> References: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> MIME-Version: 1.0 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 From: Sean Christopherson Enumerate Enclave Page Cache (EPC) sections via CPUID and add the data structures necessary to track EPC pages so that they can be allocated, freed and managed. As a system may have multiple EPC sections, invoke CPUID on SGX sub-leafs until an invalid leaf is encountered. On NUMA systems, a node can have at most one bank. A bank can be at most part of two nodes. SGX supports both nodes with a single memory controller and also sub-cluster nodes with severals memory controllers on a single die. For simplicity, support a maximum of eight EPC sections. Current client hardware supports only a single section, while upcoming server hardware will support at most eight sections. Bounding the number of sections also allows the section ID to be embedded along with a page's offset in a single unsigned long, enabling easy retrieval of both the VA and PA for a given page. Signed-off-by: Sean Christopherson Co-developed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen Co-developed-by: Suresh Siddha Signed-off-by: Suresh Siddha Co-developed-by: Serge Ayoun Signed-off-by: Serge Ayoun --- arch/x86/Kconfig | 19 ++++ arch/x86/kernel/cpu/Makefile | 1 + arch/x86/kernel/cpu/sgx/Makefile | 1 + arch/x86/kernel/cpu/sgx/main.c | 149 +++++++++++++++++++++++++++++++ arch/x86/kernel/cpu/sgx/sgx.h | 62 +++++++++++++ 5 files changed, 232 insertions(+) create mode 100644 arch/x86/kernel/cpu/sgx/Makefile create mode 100644 arch/x86/kernel/cpu/sgx/main.c create mode 100644 arch/x86/kernel/cpu/sgx/sgx.h diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index c1f9b3cf437c..dc630208003f 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1921,6 +1921,25 @@ config X86_INTEL_MEMORY_PROTECTION_KEYS If unsure, say y. +config INTEL_SGX + bool "Intel SGX core functionality" + depends on X86_64 && CPU_SUP_INTEL + help + + Intel(R) SGX is a set of CPU instructions that can be used by + applications to set aside private regions of code and data. The code + outside the enclave is disallowed to access the memory inside the + enclave by the CPU access control. + + The firmware uses PRMRR registers to reserve an area of physical memory + called Enclave Page Cache (EPC). There is a hardware unit in the + processor called Memory Encryption Engine. The MEE encrypts and decrypts + the EPC pages as they enter and leave the processor package. + + For details, see Documentation/x86/intel_sgx.rst + + If unsure, say N. + config EFI bool "EFI runtime service support" depends on ACPI diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index cfd24f9f7614..d1163c0fd5d6 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile @@ -40,6 +40,7 @@ obj-$(CONFIG_X86_MCE) += mce/ obj-$(CONFIG_MTRR) += mtrr/ obj-$(CONFIG_MICROCODE) += microcode/ obj-$(CONFIG_X86_CPU_RESCTRL) += resctrl/ +obj-$(CONFIG_INTEL_SGX) += sgx/ obj-$(CONFIG_X86_LOCAL_APIC) += perfctr-watchdog.o diff --git a/arch/x86/kernel/cpu/sgx/Makefile b/arch/x86/kernel/cpu/sgx/Makefile new file mode 100644 index 000000000000..b666967fd570 --- /dev/null +++ b/arch/x86/kernel/cpu/sgx/Makefile @@ -0,0 +1 @@ +obj-y += main.o diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c new file mode 100644 index 000000000000..18ce4acdd7ef --- /dev/null +++ b/arch/x86/kernel/cpu/sgx/main.c @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// Copyright(c) 2016-17 Intel Corporation. + +#include +#include +#include +#include +#include +#include +#include +#include "arch.h" +#include "sgx.h" + +struct sgx_epc_section sgx_epc_sections[SGX_MAX_EPC_SECTIONS]; +EXPORT_SYMBOL_GPL(sgx_epc_sections); + +static int sgx_nr_epc_sections; + +static void sgx_section_put_page(struct sgx_epc_section *section, + struct sgx_epc_page *page) +{ + list_add_tail(&page->list, §ion->page_list); + section->free_cnt++; +} + +static __init void sgx_free_epc_section(struct sgx_epc_section *section) +{ + struct sgx_epc_page *page; + + while (!list_empty(§ion->page_list)) { + page = list_first_entry(§ion->page_list, + struct sgx_epc_page, list); + list_del(&page->list); + kfree(page); + } + memunmap(section->va); +} + +static __init int sgx_init_epc_section(u64 addr, u64 size, unsigned long index, + struct sgx_epc_section *section) +{ + unsigned long nr_pages = size >> PAGE_SHIFT; + struct sgx_epc_page *page; + unsigned long i; + + section->va = memremap(addr, size, MEMREMAP_WB); + if (!section->va) + return -ENOMEM; + + section->pa = addr; + spin_lock_init(§ion->lock); + INIT_LIST_HEAD(§ion->page_list); + + for (i = 0; i < nr_pages; i++) { + page = kzalloc(sizeof(*page), GFP_KERNEL); + if (!page) + goto out; + page->desc = (addr + (i << PAGE_SHIFT)) | index; + sgx_section_put_page(section, page); + } + + return 0; +out: + sgx_free_epc_section(section); + return -ENOMEM; +} + +static __init void sgx_page_cache_teardown(void) +{ + int i; + + for (i = 0; i < sgx_nr_epc_sections; i++) + sgx_free_epc_section(&sgx_epc_sections[i]); +} + +/** + * 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 + * metric. + */ +static inline u64 sgx_calc_section_metric(u64 low, u64 high) +{ + return (low & GENMASK_ULL(31, 12)) + + ((high & GENMASK_ULL(19, 0)) << 32); +} + +static __init int sgx_page_cache_init(void) +{ + u32 eax, ebx, ecx, edx, type; + u64 pa, size; + int ret; + int i; + + BUILD_BUG_ON(SGX_MAX_EPC_SECTIONS > (SGX_EPC_SECTION_MASK + 1)); + + for (i = 0; i < (SGX_MAX_EPC_SECTIONS + 1); i++) { + cpuid_count(SGX_CPUID, i + SGX_CPUID_FIRST_VARIABLE_SUB_LEAF, + &eax, &ebx, &ecx, &edx); + + type = eax & SGX_CPUID_SUB_LEAF_TYPE_MASK; + if (type == SGX_CPUID_SUB_LEAF_INVALID) + break; + if (type != SGX_CPUID_SUB_LEAF_EPC_SECTION) { + pr_err_once("sgx: Unknown sub-leaf type: %u\n", type); + return -ENODEV; + } + if (i == SGX_MAX_EPC_SECTIONS) { + pr_warn("sgx: More than " + __stringify(SGX_MAX_EPC_SECTIONS) + " EPC sections\n"); + break; + } + + pa = sgx_calc_section_metric(eax, ebx); + size = sgx_calc_section_metric(ecx, edx); + pr_info("sgx: EPC section 0x%llx-0x%llx\n", pa, pa + size - 1); + + ret = sgx_init_epc_section(pa, size, i, &sgx_epc_sections[i]); + if (ret) { + sgx_page_cache_teardown(); + return ret; + } + + sgx_nr_epc_sections++; + } + + if (!sgx_nr_epc_sections) { + pr_err("sgx: There are zero EPC sections.\n"); + return -ENODEV; + } + + return 0; +} + +static __init int sgx_init(void) +{ + int ret; + + if (!boot_cpu_has(X86_FEATURE_SGX)) + return false; + + ret = sgx_page_cache_init(); + if (ret) + return ret; + + return 0; +} + +arch_initcall(sgx_init); diff --git a/arch/x86/kernel/cpu/sgx/sgx.h b/arch/x86/kernel/cpu/sgx/sgx.h new file mode 100644 index 000000000000..228e3dae360d --- /dev/null +++ b/arch/x86/kernel/cpu/sgx/sgx.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +#ifndef _X86_SGX_H +#define _X86_SGX_H + +#include +#include +#include +#include +#include +#include +#include + +struct sgx_epc_page { + unsigned long desc; + struct list_head list; +}; + +/** + * struct sgx_epc_section + * + * The firmware can define multiple chunks of EPC to the different areas of the + * physical memory e.g. for memory areas of the each node. This structure is + * used to store EPC pages for one EPC section and virtual memory area where + * the pages have been mapped. + */ +struct sgx_epc_section { + unsigned long pa; + void *va; + struct list_head page_list; + unsigned long free_cnt; + spinlock_t lock; +}; + +#define SGX_MAX_EPC_SECTIONS 8 + +extern struct sgx_epc_section sgx_epc_sections[SGX_MAX_EPC_SECTIONS]; + +/** + * enum sgx_epc_page_desc - bits and masks for an EPC page's descriptor + * %SGX_EPC_SECTION_MASK: SGX allows to have multiple EPC sections in the + * physical memory. The existing and near-future + * hardware defines at most eight sections, hence + * three bits to hold a section. + */ +enum sgx_epc_page_desc { + SGX_EPC_SECTION_MASK = GENMASK_ULL(3, 0), + /* bits 12-63 are reserved for the physical page address of the page */ +}; + +static inline struct sgx_epc_section *sgx_epc_section(struct sgx_epc_page *page) +{ + return &sgx_epc_sections[page->desc & SGX_EPC_SECTION_MASK]; +} + +static inline void *sgx_epc_addr(struct sgx_epc_page *page) +{ + struct sgx_epc_section *section = sgx_epc_section(page); + + return section->va + (page->desc & PAGE_MASK) - section->pa; +} + +#endif /* _X86_SGX_H */ From patchwork Sun Mar 17 21:14:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 10856619 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 8809E1575 for ; Sun, 17 Mar 2019 21:17:30 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 70D1D291EE for ; Sun, 17 Mar 2019 21:17:30 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 64EBD29214; Sun, 17 Mar 2019 21:17:30 +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 8EC7C291EE for ; Sun, 17 Mar 2019 21:17:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726493AbfCQVR3 (ORCPT ); Sun, 17 Mar 2019 17:17:29 -0400 Received: from mga09.intel.com ([134.134.136.24]:9122 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726452AbfCQVR3 (ORCPT ); Sun, 17 Mar 2019 17:17:29 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Mar 2019 14:17:28 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,491,1544515200"; d="scan'208";a="142817020" Received: from vanderss-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.254.193]) by orsmga002.jf.intel.com with ESMTP; 17 Mar 2019 14:17:19 -0700 From: Jarkko Sakkinen To: x86@kernel.org, linux-sgx@vger.kernel.org Cc: akpm@linux-foundation.org, dave.hansen@intel.com, sean.j.christopherson@intel.com, nhorman@redhat.com, npmccallum@redhat.com, serge.ayoun@intel.com, shay.katz-zamir@intel.com, haitao.huang@intel.com, andriy.shevchenko@linux.intel.com, tglx@linutronix.de, kai.svahn@intel.com, bp@alien8.de, josh@joshtriplett.org, luto@kernel.org, kai.huang@intel.com, rientjes@google.com, Jarkko Sakkinen Subject: [PATCH v19 13/27] x86/sgx: Add wrappers for ENCLS leaf functions Date: Sun, 17 Mar 2019 23:14:42 +0200 Message-Id: <20190317211456.13927-14-jarkko.sakkinen@linux.intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> References: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> MIME-Version: 1.0 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 ENCLS is an umbrella instruction for a variety of cpl0 SGX functions. The ENCLS function that is executed is specified in EAX, with each function potentially having more leaf-specific operands beyond EAX. ENCLS introduces its own (positive value) error codes that (some) leafs use to return failure information in EAX. Leafs that return an error code also modify RFLAGS. And finally, ENCLS generates ENCLS-specific non-fatal #GPs and #PFs, i.e. a bug-free kernel may encounter faults on ENCLS that must be handled gracefully. Because of the complexity involved in encoding ENCLS and handling its assortment of failure paths, executing any given leaf is not a simple matter of emitting ENCLS. To enable adding support for ENCLS leafs with minimal fuss, add a two-layer macro system along with an encoding scheme to allow wrappers to return trap numbers along ENCLS-specific error codes. The bottom layer of the macro system splits between the leafs that return an error code and those that do not. The second layer generates the correct input/output annotations based on the number of operands for each leaf function. Signed-off-by: Jarkko Sakkinen Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson --- arch/x86/kernel/cpu/sgx/Makefile | 2 +- arch/x86/kernel/cpu/sgx/encls.c | 21 +++ arch/x86/kernel/cpu/sgx/encls.h | 244 +++++++++++++++++++++++++++++++ 3 files changed, 266 insertions(+), 1 deletion(-) create mode 100644 arch/x86/kernel/cpu/sgx/encls.c create mode 100644 arch/x86/kernel/cpu/sgx/encls.h diff --git a/arch/x86/kernel/cpu/sgx/Makefile b/arch/x86/kernel/cpu/sgx/Makefile index b666967fd570..20ce33655ff4 100644 --- a/arch/x86/kernel/cpu/sgx/Makefile +++ b/arch/x86/kernel/cpu/sgx/Makefile @@ -1 +1 @@ -obj-y += main.o +obj-y += main.o encls.o diff --git a/arch/x86/kernel/cpu/sgx/encls.c b/arch/x86/kernel/cpu/sgx/encls.c new file mode 100644 index 000000000000..5045f1365e07 --- /dev/null +++ b/arch/x86/kernel/cpu/sgx/encls.c @@ -0,0 +1,21 @@ +#include +#include +#include "encls.h" +#include "sgx.h" + +/** + * encls_failed() - Check if an ENCLS leaf function failed + * @ret: the return value of an ENCLS leaf function call + * + * Check if an ENCLS leaf function failed. This is a condition where the leaf + * function causes a fault that is not caused by an EPCM conflict. + * + * Return: true if there was a fault other than an EPCM conflict + */ +bool encls_failed(int ret) +{ + int epcm_trapnr = boot_cpu_has(X86_FEATURE_SGX2) ? + X86_TRAP_PF : X86_TRAP_GP; + + return encls_faulted(ret) && ENCLS_TRAPNR(ret) != epcm_trapnr; +} diff --git a/arch/x86/kernel/cpu/sgx/encls.h b/arch/x86/kernel/cpu/sgx/encls.h new file mode 100644 index 000000000000..aea3b9d09936 --- /dev/null +++ b/arch/x86/kernel/cpu/sgx/encls.h @@ -0,0 +1,244 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +#ifndef _X86_ENCLS_H +#define _X86_ENCLS_H + +#include +#include +#include +#include +#include +#include +#include "arch.h" + +/** + * ENCLS_FAULT_FLAG - flag signifying an ENCLS return code is a trapnr + * + * ENCLS has its own (positive value) error codes and also generates + * ENCLS specific #GP and #PF faults. And the ENCLS values get munged + * with system error codes as everything percolates back up the stack. + * Unfortunately (for us), we need to precisely identify each unique + * error code, e.g. the action taken if EWB fails varies based on the + * type of fault and on the exact SGX error code, i.e. we can't simply + * convert all faults to -EFAULT. + * + * To make all three error types coexist, we set bit 30 to identify an + * ENCLS fault. Bit 31 (technically bits N:31) is used to differentiate + * between positive (faults and SGX error codes) and negative (system + * error codes) values. + */ +#define ENCLS_FAULT_FLAG 0x40000000 + +/** + * Retrieve the encoded trapnr from the specified return code. + */ +#define ENCLS_TRAPNR(r) ((r) & ~ENCLS_FAULT_FLAG) + +/* Issue a WARN() about an ENCLS leaf. */ +#define ENCLS_WARN(r, name) { \ + do { \ + int _r = (r); \ + WARN(_r, "sgx: %s returned %d (0x%x)\n", (name), _r, \ + _r); \ + } while (0); \ +} + +/** + * encls_faulted() - Check if ENCLS leaf function faulted + * @ret: the return value of an ENCLS leaf function call + * + * Return: true if the fault flag is set + */ +static inline bool encls_faulted(int ret) +{ + return (ret & ENCLS_FAULT_FLAG) != 0; +} + +/** + * encls_returned_code() - Check if an ENCLS leaf function returned a code + * @ret: the return value of an ENCLS leaf function call + * + * Check if an ENCLS leaf function returned an error or information code. + * + * Return: true if there was a fault other than an EPCM conflict + */ +static inline bool encls_returned_code(int ret) +{ + return !encls_faulted(ret) && ret; +} + +bool encls_failed(int ret); + +/** + * __encls_ret_N - encode an ENCLS leaf that returns an error code in EAX + * @rax: leaf number + * @inputs: asm inputs for the leaf + * + * Emit assembly for an ENCLS leaf that returns an error code, e.g. EREMOVE. + * And because SGX isn't complex enough as it is, leafs that return an error + * code also modify flags. + * + * Return: + * 0 on success, + * SGX error code on failure + */ +#define __encls_ret_N(rax, inputs...) \ + ({ \ + int ret; \ + asm volatile( \ + "1: .byte 0x0f, 0x01, 0xcf;\n\t" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: orl $"__stringify(ENCLS_FAULT_FLAG)",%%eax\n" \ + " jmp 2b\n" \ + ".previous\n" \ + _ASM_EXTABLE_FAULT(1b, 3b) \ + : "=a"(ret) \ + : "a"(rax), inputs \ + : "memory", "cc"); \ + ret; \ + }) + +#define __encls_ret_1(rax, rcx) \ + ({ \ + __encls_ret_N(rax, "c"(rcx)); \ + }) + +#define __encls_ret_2(rax, rbx, rcx) \ + ({ \ + __encls_ret_N(rax, "b"(rbx), "c"(rcx)); \ + }) + +#define __encls_ret_3(rax, rbx, rcx, rdx) \ + ({ \ + __encls_ret_N(rax, "b"(rbx), "c"(rcx), "d"(rdx)); \ + }) + +/** + * __encls_N - encode an ENCLS leaf that doesn't return an error code + * @rax: leaf number + * @rbx_out: optional output variable + * @inputs: asm inputs for the leaf + * + * Emit assembly for an ENCLS leaf that does not return an error code, + * e.g. ECREATE. Leaves without error codes either succeed or fault. + * @rbx_out is an optional parameter for use by EDGBRD, which returns + * the the requested value in RBX. + * + * Return: + * 0 on success, + * trapnr with ENCLS_FAULT_FLAG set on fault + */ +#define __encls_N(rax, rbx_out, inputs...) \ + ({ \ + int ret; \ + asm volatile( \ + "1: .byte 0x0f, 0x01, 0xcf;\n\t" \ + " xor %%eax,%%eax;\n" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: orl $"__stringify(ENCLS_FAULT_FLAG)",%%eax\n" \ + " jmp 2b\n" \ + ".previous\n" \ + _ASM_EXTABLE_FAULT(1b, 3b) \ + : "=a"(ret), "=b"(rbx_out) \ + : "a"(rax), inputs \ + : "memory"); \ + ret; \ + }) + +#define __encls_2(rax, rbx, rcx) \ + ({ \ + unsigned long ign_rbx_out; \ + __encls_N(rax, ign_rbx_out, "b"(rbx), "c"(rcx)); \ + }) + +#define __encls_1_1(rax, data, rcx) \ + ({ \ + unsigned long rbx_out; \ + int ret = __encls_N(rax, rbx_out, "c"(rcx)); \ + if (!ret) \ + data = rbx_out; \ + ret; \ + }) + +static inline int __ecreate(struct sgx_pageinfo *pginfo, void *secs) +{ + return __encls_2(SGX_ECREATE, pginfo, secs); +} + +static inline int __eextend(void *secs, void *addr) +{ + return __encls_2(SGX_EEXTEND, secs, addr); +} + +static inline int __eadd(struct sgx_pageinfo *pginfo, void *addr) +{ + return __encls_2(SGX_EADD, pginfo, addr); +} + +static inline int __einit(void *sigstruct, struct sgx_einittoken *einittoken, + void *secs) +{ + return __encls_ret_3(SGX_EINIT, sigstruct, secs, einittoken); +} + +static inline int __eremove(void *addr) +{ + return __encls_ret_1(SGX_EREMOVE, addr); +} + +static inline int __edbgwr(void *addr, unsigned long *data) +{ + return __encls_2(SGX_EDGBWR, *data, addr); +} + +static inline int __edbgrd(void *addr, unsigned long *data) +{ + return __encls_1_1(SGX_EDGBRD, *data, addr); +} + +static inline int __etrack(void *addr) +{ + return __encls_ret_1(SGX_ETRACK, addr); +} + +static inline int __eldu(struct sgx_pageinfo *pginfo, void *addr, + void *va) +{ + return __encls_ret_3(SGX_ELDU, pginfo, addr, va); +} + +static inline int __eblock(void *addr) +{ + return __encls_ret_1(SGX_EBLOCK, addr); +} + +static inline int __epa(void *addr) +{ + unsigned long rbx = SGX_PAGE_TYPE_VA; + + return __encls_2(SGX_EPA, rbx, addr); +} + +static inline int __ewb(struct sgx_pageinfo *pginfo, void *addr, + void *va) +{ + return __encls_ret_3(SGX_EWB, pginfo, addr, va); +} + +static inline int __eaug(struct sgx_pageinfo *pginfo, void *addr) +{ + return __encls_2(SGX_EAUG, pginfo, addr); +} + +static inline int __emodpr(struct sgx_secinfo *secinfo, void *addr) +{ + return __encls_ret_2(SGX_EMODPR, secinfo, addr); +} + +static inline int __emodt(struct sgx_secinfo *secinfo, void *addr) +{ + return __encls_ret_2(SGX_EMODT, secinfo, addr); +} + +#endif /* _X86_ENCLS_H */ From patchwork Sun Mar 17 21:14:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 10856621 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 94DE31823 for ; Sun, 17 Mar 2019 21:18:05 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 75675291EE for ; Sun, 17 Mar 2019 21:18:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 645FA29214; Sun, 17 Mar 2019 21:18:05 +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 C20E4291EE for ; Sun, 17 Mar 2019 21:18:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726735AbfCQVSC (ORCPT ); Sun, 17 Mar 2019 17:18:02 -0400 Received: from mga17.intel.com ([192.55.52.151]:5974 "EHLO mga17.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726229AbfCQVSC (ORCPT ); Sun, 17 Mar 2019 17:18:02 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga107.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Mar 2019 14:18:01 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,491,1544515200"; d="scan'208";a="142817137" Received: from vanderss-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.254.193]) by orsmga002.jf.intel.com with ESMTP; 17 Mar 2019 14:17:51 -0700 From: Jarkko Sakkinen To: x86@kernel.org, linux-sgx@vger.kernel.org Cc: akpm@linux-foundation.org, dave.hansen@intel.com, sean.j.christopherson@intel.com, nhorman@redhat.com, npmccallum@redhat.com, serge.ayoun@intel.com, shay.katz-zamir@intel.com, haitao.huang@intel.com, andriy.shevchenko@linux.intel.com, tglx@linutronix.de, kai.svahn@intel.com, bp@alien8.de, josh@joshtriplett.org, luto@kernel.org, kai.huang@intel.com, rientjes@google.com, Jarkko Sakkinen , Suresh Siddha Subject: [PATCH v19 16/27] x86/sgx: Add the Linux SGX Enclave Driver Date: Sun, 17 Mar 2019 23:14:45 +0200 Message-Id: <20190317211456.13927-17-jarkko.sakkinen@linux.intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> References: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> MIME-Version: 1.0 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 Intel Software Guard eXtensions (SGX) is a set of CPU instructions that can be used by applications to set aside private regions of code and data. The code outside the enclave is disallowed to access the memory inside the enclave by the CPU access control. This commit adds the Linux SGX Enclave Driver that provides an ioctl API to manage enclaves. The address range for an enclave, commonly referred as ELRANGE in the documentation (e.g. Intel SDM), is reserved with mmap() against /dev/sgx. After that a set ioctls is used to build the enclave to the ELRANGE. Signed-off-by: Jarkko Sakkinen Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson Co-developed-by: Serge Ayoun Signed-off-by: Serge Ayoun Co-developed-by: Shay Katz-zamir Signed-off-by: Shay Katz-zamir Co-developed-by: Suresh Siddha Signed-off-by: Suresh Siddha --- Documentation/ioctl/ioctl-number.txt | 1 + arch/x86/Kconfig | 17 +- arch/x86/include/uapi/asm/sgx.h | 59 ++ arch/x86/kernel/cpu/sgx/Makefile | 5 +- arch/x86/kernel/cpu/sgx/driver/Makefile | 3 + arch/x86/kernel/cpu/sgx/driver/driver.h | 38 ++ arch/x86/kernel/cpu/sgx/driver/ioctl.c | 795 ++++++++++++++++++++++++ arch/x86/kernel/cpu/sgx/driver/main.c | 290 +++++++++ arch/x86/kernel/cpu/sgx/encl.c | 358 +++++++++++ arch/x86/kernel/cpu/sgx/encl.h | 88 +++ arch/x86/kernel/cpu/sgx/encls.c | 1 + arch/x86/kernel/cpu/sgx/main.c | 3 + arch/x86/kernel/cpu/sgx/sgx.h | 1 + 13 files changed, 1657 insertions(+), 2 deletions(-) create mode 100644 arch/x86/include/uapi/asm/sgx.h create mode 100644 arch/x86/kernel/cpu/sgx/driver/Makefile create mode 100644 arch/x86/kernel/cpu/sgx/driver/driver.h create mode 100644 arch/x86/kernel/cpu/sgx/driver/ioctl.c create mode 100644 arch/x86/kernel/cpu/sgx/driver/main.c create mode 100644 arch/x86/kernel/cpu/sgx/encl.c create mode 100644 arch/x86/kernel/cpu/sgx/encl.h diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt index c9558146ac58..ef2694221cd0 100644 --- a/Documentation/ioctl/ioctl-number.txt +++ b/Documentation/ioctl/ioctl-number.txt @@ -312,6 +312,7 @@ Code Seq#(hex) Include File Comments 0xA3 90-9F linux/dtlk.h 0xA4 00-1F uapi/linux/tee.h Generic TEE subsystem +0xA4 00-02 uapi/asm/sgx.h conflict! 0xAA 00-3F linux/uapi/linux/userfaultfd.h 0xAB 00-1F linux/nbd.h 0xAC 00-1F linux/raw.h diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index dc630208003f..34257b5659cc 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1925,7 +1925,6 @@ config INTEL_SGX bool "Intel SGX core functionality" depends on X86_64 && CPU_SUP_INTEL help - Intel(R) SGX is a set of CPU instructions that can be used by applications to set aside private regions of code and data. The code outside the enclave is disallowed to access the memory inside the @@ -1940,6 +1939,22 @@ config INTEL_SGX If unsure, say N. +config INTEL_SGX_DRIVER + tristate "Intel(R) SGX Driver" + default n + depends on X86_64 && CPU_SUP_INTEL && INTEL_SGX + select MMU_NOTIFIER + select CRYPTO + select CRYPTO_SHA256 + help + This options enables the kernel SGX driver that allows to construct + enclaves to the process memory by using a device node (by default + /dev/sgx) and a set of ioctls. The driver requires that the MSRs + specifying the public key hash for the launch enclave are writable so + that Linux has the full control to run enclaves. + + For details, see Documentation/x86/intel_sgx.rst + config EFI bool "EFI runtime service support" depends on ACPI diff --git a/arch/x86/include/uapi/asm/sgx.h b/arch/x86/include/uapi/asm/sgx.h new file mode 100644 index 000000000000..aadf9c76e360 --- /dev/null +++ b/arch/x86/include/uapi/asm/sgx.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/** + * Copyright(c) 2016-18 Intel Corporation. + */ +#ifndef _UAPI_ASM_X86_SGX_H +#define _UAPI_ASM_X86_SGX_H + +#include +#include + +#define SGX_MAGIC 0xA4 + +#define SGX_IOC_ENCLAVE_CREATE \ + _IOW(SGX_MAGIC, 0x00, struct sgx_enclave_create) +#define SGX_IOC_ENCLAVE_ADD_PAGE \ + _IOW(SGX_MAGIC, 0x01, struct sgx_enclave_add_page) +#define SGX_IOC_ENCLAVE_INIT \ + _IOW(SGX_MAGIC, 0x02, struct sgx_enclave_init) + +/* IOCTL return values */ +#define SGX_POWER_LOST_ENCLAVE 0x40000000 + +/** + * struct sgx_enclave_create - parameter structure for the + * %SGX_IOC_ENCLAVE_CREATE ioctl + * @src: address for the SECS page data + */ +struct sgx_enclave_create { + __u64 src; +}; + +/** + * struct sgx_enclave_add_page - parameter structure for the + * %SGX_IOC_ENCLAVE_ADD_PAGE ioctl + * @addr: address within the ELRANGE + * @src: address for the page data + * @secinfo: address for the SECINFO data + * @mrmask: bitmask for the measured 256 byte chunks + */ +struct sgx_enclave_add_page { + __u64 addr; + __u64 src; + __u64 secinfo; + __u16 mrmask; +} __attribute__((__packed__)); + + +/** + * struct sgx_enclave_init - parameter structure for the + * %SGX_IOC_ENCLAVE_INIT ioctl + * @addr: address within the ELRANGE + * @sigstruct: address for the SIGSTRUCT data + */ +struct sgx_enclave_init { + __u64 addr; + __u64 sigstruct; +}; + +#endif /* _UAPI_ASM_X86_SGX_H */ diff --git a/arch/x86/kernel/cpu/sgx/Makefile b/arch/x86/kernel/cpu/sgx/Makefile index 20ce33655ff4..48174e5fc181 100644 --- a/arch/x86/kernel/cpu/sgx/Makefile +++ b/arch/x86/kernel/cpu/sgx/Makefile @@ -1 +1,4 @@ -obj-y += main.o encls.o +obj-y += encl.o +obj-y += encls.o +obj-y += main.o +obj-$(CONFIG_INTEL_SGX_DRIVER) += driver/ diff --git a/arch/x86/kernel/cpu/sgx/driver/Makefile b/arch/x86/kernel/cpu/sgx/driver/Makefile new file mode 100644 index 000000000000..01ebbbb06a47 --- /dev/null +++ b/arch/x86/kernel/cpu/sgx/driver/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_INTEL_SGX_DRIVER) += sgx.o +sgx-$(CONFIG_INTEL_SGX_DRIVER) += ioctl.o +sgx-$(CONFIG_INTEL_SGX_DRIVER) += main.o diff --git a/arch/x86/kernel/cpu/sgx/driver/driver.h b/arch/x86/kernel/cpu/sgx/driver/driver.h new file mode 100644 index 000000000000..b736411b5317 --- /dev/null +++ b/arch/x86/kernel/cpu/sgx/driver/driver.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/** + * Copyright(c) 2016-19 Intel Corporation. + */ +#ifndef __ARCH_INTEL_SGX_H__ +#define __ARCH_INTEL_SGX_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "../arch.h" +#include "../encl.h" +#include "../encls.h" +#include "../sgx.h" + +#define SGX_DRV_NR_DEVICES 1 +#define SGX_EINIT_SPIN_COUNT 20 +#define SGX_EINIT_SLEEP_COUNT 50 +#define SGX_EINIT_SLEEP_TIME 20 + +extern struct workqueue_struct *sgx_encl_wq; +extern u64 sgx_encl_size_max_32; +extern u64 sgx_encl_size_max_64; +extern u32 sgx_misc_reserved_mask; +extern u64 sgx_attributes_reserved_mask; +extern u64 sgx_xfrm_reserved_mask; +extern u32 sgx_xsave_size_tbl[64]; + +extern const struct file_operations sgx_fs_provision_fops; + +long sgx_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); + +#endif /* __ARCH_X86_INTEL_SGX_H__ */ diff --git a/arch/x86/kernel/cpu/sgx/driver/ioctl.c b/arch/x86/kernel/cpu/sgx/driver/ioctl.c new file mode 100644 index 000000000000..4b9a91b53b50 --- /dev/null +++ b/arch/x86/kernel/cpu/sgx/driver/ioctl.c @@ -0,0 +1,795 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// Copyright(c) 2016-19 Intel Corporation. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "driver.h" + +struct sgx_add_page_req { + struct sgx_encl *encl; + struct sgx_encl_page *encl_page; + struct sgx_secinfo secinfo; + unsigned long mrmask; + struct list_head list; +}; + +static int sgx_encl_get(unsigned long addr, struct sgx_encl **encl) +{ + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + int ret; + + if (addr & (PAGE_SIZE - 1)) + return -EINVAL; + + down_read(&mm->mmap_sem); + + ret = sgx_encl_find(mm, addr, &vma); + if (!ret) { + *encl = vma->vm_private_data; + + if ((*encl)->flags & SGX_ENCL_SUSPEND) + ret = SGX_POWER_LOST_ENCLAVE; + else + kref_get(&(*encl)->refcount); + } + + up_read(&mm->mmap_sem); + return ret; +} + +static bool sgx_process_add_page_req(struct sgx_add_page_req *req, + struct sgx_epc_page *epc_page) +{ + struct sgx_encl_page *encl_page = req->encl_page; + struct sgx_encl *encl = req->encl; + unsigned long page_index = sgx_encl_get_index(encl, encl_page); + struct sgx_secinfo secinfo; + struct sgx_pageinfo pginfo; + struct page *backing; + unsigned long addr; + int ret; + int i; + + if (encl->flags & (SGX_ENCL_SUSPEND | SGX_ENCL_DEAD)) + return false; + + addr = SGX_ENCL_PAGE_ADDR(encl_page); + + backing = sgx_encl_get_backing_page(encl, page_index); + if (IS_ERR(backing)) + return false; + + /* + * The SECINFO field must be 64-byte aligned, copy it to a local + * variable that is guaranteed to be aligned as req->secinfo may + * or may not be 64-byte aligned, e.g. req may have been allocated + * via kzalloc which is not aware of __aligned attributes. + */ + memcpy(&secinfo, &req->secinfo, sizeof(secinfo)); + + pginfo.secs = (unsigned long)sgx_epc_addr(encl->secs.epc_page); + pginfo.addr = addr; + pginfo.metadata = (unsigned long)&secinfo; + pginfo.contents = (unsigned long)kmap_atomic(backing); + ret = __eadd(&pginfo, sgx_epc_addr(epc_page)); + kunmap_atomic((void *)(unsigned long)pginfo.contents); + + put_page(backing); + + if (ret) { + if (encls_failed(ret)) + ENCLS_WARN(ret, "EADD"); + return false; + } + + for_each_set_bit(i, &req->mrmask, 16) { + ret = __eextend(sgx_epc_addr(encl->secs.epc_page), + sgx_epc_addr(epc_page) + (i * 0x100)); + if (ret) { + if (encls_failed(ret)) + ENCLS_WARN(ret, "EEXTEND"); + return false; + } + } + + encl_page->encl = encl; + encl_page->epc_page = epc_page; + encl->secs_child_cnt++; + + return true; +} + +static void sgx_add_page_worker(struct work_struct *work) +{ + struct sgx_add_page_req *req; + bool skip_rest = false; + bool is_empty = false; + struct sgx_encl *encl; + struct sgx_epc_page *epc_page; + + encl = container_of(work, struct sgx_encl, work); + + do { + schedule(); + + mutex_lock(&encl->lock); + if (encl->flags & SGX_ENCL_DEAD) + skip_rest = true; + + req = list_first_entry(&encl->add_page_reqs, + struct sgx_add_page_req, list); + list_del(&req->list); + is_empty = list_empty(&encl->add_page_reqs); + mutex_unlock(&encl->lock); + + if (skip_rest) + goto next; + + epc_page = sgx_alloc_page(); + + mutex_lock(&encl->lock); + + if (IS_ERR(epc_page)) { + sgx_encl_destroy(encl); + skip_rest = true; + } else if (!sgx_process_add_page_req(req, epc_page)) { + sgx_free_page(epc_page); + sgx_encl_destroy(encl); + skip_rest = true; + } + + mutex_unlock(&encl->lock); + +next: + kfree(req); + } while (!kref_put(&encl->refcount, sgx_encl_release) && !is_empty); +} + +static u32 sgx_calc_ssaframesize(u32 miscselect, u64 xfrm) +{ + u32 size_max = PAGE_SIZE; + u32 size; + int i; + + for (i = 2; i < 64; i++) { + if (!((1 << i) & xfrm)) + continue; + + size = SGX_SSA_GPRS_SIZE + sgx_xsave_size_tbl[i]; + if (miscselect & SGX_MISC_EXINFO) + size += SGX_SSA_MISC_EXINFO_SIZE; + + if (size > size_max) + size_max = size; + } + + return PFN_UP(size_max); +} + +static int sgx_validate_secs(const struct sgx_secs *secs, + unsigned long ssaframesize) +{ + if (secs->size < (2 * PAGE_SIZE) || !is_power_of_2(secs->size)) + return -EINVAL; + + if (secs->base & (secs->size - 1)) + return -EINVAL; + + if (secs->miscselect & sgx_misc_reserved_mask || + secs->attributes & sgx_attributes_reserved_mask || + secs->xfrm & sgx_xfrm_reserved_mask) + return -EINVAL; + + if (secs->attributes & SGX_ATTR_MODE64BIT) { + if (secs->size > sgx_encl_size_max_64) + return -EINVAL; + } else if (secs->size > sgx_encl_size_max_32) + return -EINVAL; + + if (!(secs->xfrm & XFEATURE_MASK_FP) || + !(secs->xfrm & XFEATURE_MASK_SSE) || + (((secs->xfrm >> XFEATURE_BNDREGS) & 1) != + ((secs->xfrm >> XFEATURE_BNDCSR) & 1))) + return -EINVAL; + + if (!secs->ssa_frame_size || ssaframesize > secs->ssa_frame_size) + return -EINVAL; + + if (memchr_inv(secs->reserved1, 0, SGX_SECS_RESERVED1_SIZE) || + memchr_inv(secs->reserved2, 0, SGX_SECS_RESERVED2_SIZE) || + memchr_inv(secs->reserved3, 0, SGX_SECS_RESERVED3_SIZE) || + memchr_inv(secs->reserved4, 0, SGX_SECS_RESERVED4_SIZE)) + return -EINVAL; + + return 0; +} + +static struct sgx_encl *sgx_encl_alloc(struct sgx_secs *secs) +{ + unsigned long encl_size = secs->size + PAGE_SIZE; + unsigned long ssaframesize; + struct sgx_encl_mm *mm; + struct sgx_encl *encl; + struct file *backing; + + ssaframesize = sgx_calc_ssaframesize(secs->miscselect, secs->xfrm); + if (sgx_validate_secs(secs, ssaframesize)) + return ERR_PTR(-EINVAL); + + backing = shmem_file_setup("SGX backing", encl_size + (encl_size >> 5), + VM_NORESERVE); + if (IS_ERR(backing)) + return ERR_CAST(backing); + + encl = kzalloc(sizeof(*encl), GFP_KERNEL); + if (!encl) { + fput(backing); + return ERR_PTR(-ENOMEM); + } + + mm = kzalloc(sizeof(*mm), GFP_KERNEL); + if (!mm) { + kfree(encl); + fput(backing); + return ERR_PTR(-ENOMEM); + } + + encl->secs_attributes = secs->attributes; + encl->allowed_attributes = SGX_ATTR_ALLOWED_MASK; + kref_init(&encl->refcount); + INIT_LIST_HEAD(&encl->add_page_reqs); + INIT_RADIX_TREE(&encl->page_tree, GFP_KERNEL); + mutex_init(&encl->lock); + INIT_WORK(&encl->work, sgx_add_page_worker); + INIT_LIST_HEAD(&encl->mm_list); + list_add(&mm->list, &encl->mm_list); + kref_init(&mm->refcount); + mm->mm = current->mm; + mm->encl = encl; + spin_lock_init(&encl->mm_lock); + encl->base = secs->base; + encl->size = secs->size; + encl->ssaframesize = secs->ssa_frame_size; + encl->backing = backing; + + return encl; +} + +static struct sgx_encl_page *sgx_encl_page_alloc(struct sgx_encl *encl, + unsigned long addr) +{ + struct sgx_encl_page *encl_page; + int ret; + + if (radix_tree_lookup(&encl->page_tree, PFN_DOWN(addr))) + return ERR_PTR(-EEXIST); + encl_page = kzalloc(sizeof(*encl_page), GFP_KERNEL); + if (!encl_page) + return ERR_PTR(-ENOMEM); + encl_page->desc = addr; + encl_page->encl = encl; + ret = radix_tree_insert(&encl->page_tree, PFN_DOWN(encl_page->desc), + encl_page); + if (ret) { + kfree(encl_page); + return ERR_PTR(ret); + } + return encl_page; +} + +static int sgx_encl_pm_notifier(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct sgx_encl *encl = container_of(nb, struct sgx_encl, pm_notifier); + + if (action != PM_SUSPEND_PREPARE && action != PM_HIBERNATION_PREPARE) + return NOTIFY_DONE; + + mutex_lock(&encl->lock); + sgx_encl_destroy(encl); + encl->flags |= SGX_ENCL_SUSPEND; + mutex_unlock(&encl->lock); + flush_work(&encl->work); + return NOTIFY_DONE; +} + +static int sgx_encl_create(struct sgx_encl *encl, struct sgx_secs *secs) +{ + struct vm_area_struct *vma; + struct sgx_pageinfo pginfo; + struct sgx_secinfo secinfo; + struct sgx_epc_page *secs_epc; + long ret; + + secs_epc = sgx_alloc_page(); + if (IS_ERR(secs_epc)) { + ret = PTR_ERR(secs_epc); + return ret; + } + + encl->secs.encl = encl; + encl->secs.epc_page = secs_epc; + + pginfo.addr = 0; + pginfo.contents = (unsigned long)secs; + pginfo.metadata = (unsigned long)&secinfo; + pginfo.secs = 0; + memset(&secinfo, 0, sizeof(secinfo)); + ret = __ecreate((void *)&pginfo, sgx_epc_addr(secs_epc)); + + if (ret) { + pr_debug("ECREATE returned %ld\n", ret); + return ret; + } + + if (secs->attributes & SGX_ATTR_DEBUG) + encl->flags |= SGX_ENCL_DEBUG; + + encl->pm_notifier.notifier_call = &sgx_encl_pm_notifier; + ret = register_pm_notifier(&encl->pm_notifier); + if (ret) { + encl->pm_notifier.notifier_call = NULL; + return ret; + } + + down_read(¤t->mm->mmap_sem); + ret = sgx_encl_find(current->mm, secs->base, &vma); + if (ret != -ENOENT) { + if (!ret) + ret = -EINVAL; + up_read(¤t->mm->mmap_sem); + return ret; + } + + if (vma->vm_start != secs->base || + vma->vm_end != (secs->base + secs->size) || + vma->vm_pgoff != 0) { + ret = -EINVAL; + up_read(¤t->mm->mmap_sem); + return ret; + } + + vma->vm_private_data = encl; + up_read(¤t->mm->mmap_sem); + return 0; +} + +/** + * sgx_ioc_enclave_create - handler for %SGX_IOC_ENCLAVE_CREATE + * @filep: open file to /dev/sgx + * @cmd: the command value + * @arg: pointer to an &sgx_enclave_create instance + * + * Validates SECS attributes, allocates an EPC page for the SECS and performs + * ECREATE. + * + * Return: + * 0 on success, + * -errno otherwise + */ +static long sgx_ioc_enclave_create(struct file *filep, unsigned int cmd, + unsigned long arg) +{ + struct sgx_enclave_create *createp = (struct sgx_enclave_create *)arg; + struct page *secs_page; + struct sgx_secs *secs; + struct sgx_encl *encl; + int ret; + + secs_page = alloc_page(GFP_HIGHUSER); + if (!secs_page) + return -ENOMEM; + + secs = kmap(secs_page); + if (copy_from_user(secs, (void __user *)createp->src, sizeof(*secs))) { + ret = -EFAULT; + goto out; + } + + encl = sgx_encl_alloc(secs); + if (IS_ERR(encl)) { + ret = PTR_ERR(encl); + goto out; + } + + ret = sgx_encl_create(encl, secs); + if (ret) + kref_put(&encl->refcount, sgx_encl_release); + +out: + kunmap(secs_page); + __free_page(secs_page); + return ret; +} + +static int sgx_validate_secinfo(struct sgx_secinfo *secinfo) +{ + u64 page_type = secinfo->flags & SGX_SECINFO_PAGE_TYPE_MASK; + u64 perm = secinfo->flags & SGX_SECINFO_PERMISSION_MASK; + int i; + + if ((secinfo->flags & SGX_SECINFO_RESERVED_MASK) || + ((perm & SGX_SECINFO_W) && !(perm & SGX_SECINFO_R)) || + (page_type != SGX_SECINFO_TCS && page_type != SGX_SECINFO_TRIM && + page_type != SGX_SECINFO_REG)) + return -EINVAL; + + for (i = 0; i < SGX_SECINFO_RESERVED_SIZE; i++) + if (secinfo->reserved[i]) + return -EINVAL; + + return 0; +} + +static bool sgx_validate_offset(struct sgx_encl *encl, unsigned long offset) +{ + if (offset & (PAGE_SIZE - 1)) + return false; + + if (offset >= encl->size) + return false; + + return true; +} + +static int sgx_validate_tcs(struct sgx_encl *encl, struct sgx_tcs *tcs) +{ + int i; + + if (tcs->flags & SGX_TCS_RESERVED_MASK) + return -EINVAL; + + if (tcs->flags & SGX_TCS_DBGOPTIN) + return -EINVAL; + + if (!sgx_validate_offset(encl, tcs->ssa_offset)) + return -EINVAL; + + if (!sgx_validate_offset(encl, tcs->fs_offset)) + return -EINVAL; + + if (!sgx_validate_offset(encl, tcs->gs_offset)) + return -EINVAL; + + if ((tcs->fs_limit & 0xFFF) != 0xFFF) + return -EINVAL; + + if ((tcs->gs_limit & 0xFFF) != 0xFFF) + return -EINVAL; + + for (i = 0; i < SGX_TCS_RESERVED_SIZE; i++) + if (tcs->reserved[i]) + return -EINVAL; + + return 0; +} + +static int __sgx_encl_add_page(struct sgx_encl *encl, + struct sgx_encl_page *encl_page, + void *data, + struct sgx_secinfo *secinfo, + unsigned int mrmask) +{ + unsigned long page_index = sgx_encl_get_index(encl, encl_page); + u64 page_type = secinfo->flags & SGX_SECINFO_PAGE_TYPE_MASK; + struct sgx_add_page_req *req = NULL; + struct page *backing; + void *backing_ptr; + int empty; + + req = kzalloc(sizeof(*req), GFP_KERNEL); + if (!req) + return -ENOMEM; + + backing = sgx_encl_get_backing_page(encl, page_index); + if (IS_ERR(backing)) { + kfree(req); + return PTR_ERR(backing); + } + + backing_ptr = kmap(backing); + memcpy(backing_ptr, data, PAGE_SIZE); + kunmap(backing); + if (page_type == SGX_SECINFO_TCS) + encl_page->desc |= SGX_ENCL_PAGE_TCS; + memcpy(&req->secinfo, secinfo, sizeof(*secinfo)); + req->encl = encl; + req->encl_page = encl_page; + req->mrmask = mrmask; + empty = list_empty(&encl->add_page_reqs); + kref_get(&encl->refcount); + list_add_tail(&req->list, &encl->add_page_reqs); + if (empty) + queue_work(sgx_encl_wq, &encl->work); + set_page_dirty(backing); + put_page(backing); + return 0; +} + +static int sgx_encl_add_page(struct sgx_encl *encl, unsigned long addr, + void *data, struct sgx_secinfo *secinfo, + unsigned int mrmask) +{ + u64 page_type = secinfo->flags & SGX_SECINFO_PAGE_TYPE_MASK; + struct sgx_encl_page *encl_page; + int ret; + + if (sgx_validate_secinfo(secinfo)) + return -EINVAL; + if (page_type == SGX_SECINFO_TCS) { + ret = sgx_validate_tcs(encl, data); + if (ret) + return ret; + } + + mutex_lock(&encl->lock); + + if (encl->flags & (SGX_ENCL_INITIALIZED | SGX_ENCL_DEAD)) { + ret = -EINVAL; + goto out; + } + + encl_page = sgx_encl_page_alloc(encl, addr); + if (IS_ERR(encl_page)) { + ret = PTR_ERR(encl_page); + goto out; + } + + ret = __sgx_encl_add_page(encl, encl_page, data, secinfo, mrmask); + if (ret) { + radix_tree_delete(&encl_page->encl->page_tree, + PFN_DOWN(encl_page->desc)); + kfree(encl_page); + } + +out: + mutex_unlock(&encl->lock); + return ret; +} + +/** + * sgx_ioc_enclave_add_page - handler for %SGX_IOC_ENCLAVE_ADD_PAGE + * + * @filep: open file to /dev/sgx + * @cmd: the command value + * @arg: pointer to an &sgx_enclave_add_page instance + * + * Creates a new enclave page and enqueues an EADD operation that will be + * processed by a worker thread later on. + * + * Return: + * 0 on success, + * -errno otherwise + */ +static long sgx_ioc_enclave_add_page(struct file *filep, unsigned int cmd, + unsigned long arg) +{ + struct sgx_enclave_add_page *addp = (void *)arg; + struct sgx_secinfo secinfo; + struct sgx_encl *encl; + struct page *data_page; + void *data; + int ret; + + ret = sgx_encl_get(addp->addr, &encl); + if (ret) + return ret; + + if (copy_from_user(&secinfo, (void __user *)addp->secinfo, + sizeof(secinfo))) { + kref_put(&encl->refcount, sgx_encl_release); + return -EFAULT; + } + + data_page = alloc_page(GFP_HIGHUSER); + if (!data_page) { + kref_put(&encl->refcount, sgx_encl_release); + return -ENOMEM; + } + + data = kmap(data_page); + + if (copy_from_user((void *)data, (void __user *)addp->src, PAGE_SIZE)) { + ret = -EFAULT; + goto out; + } + + ret = sgx_encl_add_page(encl, addp->addr, data, &secinfo, addp->mrmask); + if (ret) + goto out; + +out: + kref_put(&encl->refcount, sgx_encl_release); + kunmap(data_page); + __free_page(data_page); + return ret; +} + +static int __sgx_get_key_hash(struct crypto_shash *tfm, const void *modulus, + void *hash) +{ + SHASH_DESC_ON_STACK(shash, tfm); + + shash->tfm = tfm; + shash->flags = CRYPTO_TFM_REQ_MAY_SLEEP; + + return crypto_shash_digest(shash, modulus, SGX_MODULUS_SIZE, hash); +} + +static int sgx_get_key_hash(const void *modulus, void *hash) +{ + struct crypto_shash *tfm; + int ret; + + tfm = crypto_alloc_shash("sha256", 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(tfm)) + return PTR_ERR(tfm); + + ret = __sgx_get_key_hash(tfm, modulus, hash); + + crypto_free_shash(tfm); + return ret; +} + +static int sgx_encl_init(struct sgx_encl *encl, struct sgx_sigstruct *sigstruct, + struct sgx_einittoken *token) +{ + u64 mrsigner[4]; + int ret; + int i; + int j; + + /* Check that the required attributes have been authorized. */ + if (encl->secs_attributes & ~encl->allowed_attributes) + return -EINVAL; + + ret = sgx_get_key_hash(sigstruct->modulus, mrsigner); + if (ret) + return ret; + + flush_work(&encl->work); + + mutex_lock(&encl->lock); + + if (encl->flags & SGX_ENCL_INITIALIZED) + goto err_out; + + if (encl->flags & SGX_ENCL_DEAD) { + ret = -EFAULT; + goto err_out; + } + + for (i = 0; i < SGX_EINIT_SLEEP_COUNT; i++) { + for (j = 0; j < SGX_EINIT_SPIN_COUNT; j++) { + ret = sgx_einit(sigstruct, token, encl->secs.epc_page, + mrsigner); + if (ret == SGX_UNMASKED_EVENT) + continue; + else + break; + } + + if (ret != SGX_UNMASKED_EVENT) + break; + + msleep_interruptible(SGX_EINIT_SLEEP_TIME); + + if (signal_pending(current)) { + ret = -ERESTARTSYS; + goto err_out; + } + } + + if (encls_faulted(ret)) { + if (encls_failed(ret)) + ENCLS_WARN(ret, "EINIT"); + + sgx_encl_destroy(encl); + ret = -EFAULT; + } else if (encls_returned_code(ret)) { + pr_debug("EINIT returned %d\n", ret); + } else { + encl->flags |= SGX_ENCL_INITIALIZED; + } + +err_out: + mutex_unlock(&encl->lock); + return ret; +} + +/** + * sgx_ioc_enclave_init - handler for %SGX_IOC_ENCLAVE_INIT + * + * @filep: open file to /dev/sgx + * @cmd: the command value + * @arg: pointer to an &sgx_enclave_init instance + * + * Flushes the remaining enqueued EADD operations and performs EINIT. + * + * Return: + * 0 on success, + * SGX error code on EINIT failure, + * -errno otherwise + */ +static long sgx_ioc_enclave_init(struct file *filep, unsigned int cmd, + unsigned long arg) +{ + struct sgx_enclave_init *initp = (struct sgx_enclave_init *)arg; + struct sgx_sigstruct *sigstruct; + struct sgx_einittoken *einittoken; + struct sgx_encl *encl; + struct page *initp_page; + int ret; + + initp_page = alloc_page(GFP_HIGHUSER); + if (!initp_page) + return -ENOMEM; + + sigstruct = kmap(initp_page); + einittoken = (struct sgx_einittoken *) + ((unsigned long)sigstruct + PAGE_SIZE / 2); + memset(einittoken, 0, sizeof(*einittoken)); + + if (copy_from_user(sigstruct, (void __user *)initp->sigstruct, + sizeof(*sigstruct))) { + ret = -EFAULT; + goto out; + } + + ret = sgx_encl_get(initp->addr, &encl); + if (ret) + goto out; + + ret = sgx_encl_init(encl, sigstruct, einittoken); + + kref_put(&encl->refcount, sgx_encl_release); + +out: + kunmap(initp_page); + __free_page(initp_page); + return ret; +} + +typedef long (*sgx_ioc_t)(struct file *filep, unsigned int cmd, + unsigned long arg); + +long sgx_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) +{ + char data[256]; + sgx_ioc_t handler = NULL; + long ret; + + switch (cmd) { + case SGX_IOC_ENCLAVE_CREATE: + handler = sgx_ioc_enclave_create; + break; + case SGX_IOC_ENCLAVE_ADD_PAGE: + handler = sgx_ioc_enclave_add_page; + break; + case SGX_IOC_ENCLAVE_INIT: + handler = sgx_ioc_enclave_init; + break; + default: + return -ENOIOCTLCMD; + } + + if (copy_from_user(data, (void __user *)arg, _IOC_SIZE(cmd))) + return -EFAULT; + + ret = handler(filep, cmd, (unsigned long)((void *)data)); + if (!ret && (cmd & IOC_OUT)) { + if (copy_to_user((void __user *)arg, data, _IOC_SIZE(cmd))) + return -EFAULT; + } + + return ret; +} diff --git a/arch/x86/kernel/cpu/sgx/driver/main.c b/arch/x86/kernel/cpu/sgx/driver/main.c new file mode 100644 index 000000000000..16f36cd0af04 --- /dev/null +++ b/arch/x86/kernel/cpu/sgx/driver/main.c @@ -0,0 +1,290 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// Copyright(c) 2016-18 Intel Corporation. + +#include +#include +#include +#include +#include +#include +#include +#include "driver.h" + +MODULE_DESCRIPTION("Intel SGX Enclave Driver"); +MODULE_AUTHOR("Jarkko Sakkinen "); +MODULE_LICENSE("Dual BSD/GPL"); + +struct workqueue_struct *sgx_encl_wq; +u64 sgx_encl_size_max_32; +u64 sgx_encl_size_max_64; +u32 sgx_misc_reserved_mask; +u64 sgx_attributes_reserved_mask; +u64 sgx_xfrm_reserved_mask = ~0x3; +u32 sgx_xsave_size_tbl[64]; + +#ifdef CONFIG_COMPAT +static long sgx_compat_ioctl(struct file *filep, unsigned int cmd, + unsigned long arg) +{ + return sgx_ioctl(filep, cmd, arg); +} +#endif + +static int sgx_mmap(struct file *file, struct vm_area_struct *vma) +{ + vma->vm_ops = &sgx_vm_ops; + vma->vm_flags |= VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP | VM_IO; + + return 0; +} + +static unsigned long sgx_get_unmapped_area(struct file *file, + unsigned long addr, + unsigned long len, + unsigned long pgoff, + unsigned long flags) +{ + if (len < 2 * PAGE_SIZE || len & (len - 1) || flags & MAP_PRIVATE) + return -EINVAL; + + addr = current->mm->get_unmapped_area(file, addr, 2 * len, pgoff, + flags); + if (IS_ERR_VALUE(addr)) + return addr; + + addr = (addr + (len - 1)) & ~(len - 1); + + return addr; +} + +static const struct file_operations sgx_ctrl_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = sgx_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = sgx_compat_ioctl, +#endif + .mmap = sgx_mmap, + .get_unmapped_area = sgx_get_unmapped_area, +}; + +static struct bus_type sgx_bus_type = { + .name = "sgx", +}; + +static char *sgx_devnode(struct device *dev, umode_t *mode, + kuid_t *uid, kgid_t *gid) +{ + if (mode) + *mode = 0666; + return kasprintf(GFP_KERNEL, "sgx"); +} + +static const struct device_type sgx_device_type = { + .name = "sgx", + .devnode = sgx_devnode, +}; + +struct sgx_dev_ctx { + struct device ctrl_dev; + struct cdev ctrl_cdev; +}; + +static dev_t sgx_devt; + +static void sgx_dev_release(struct device *dev) +{ + struct sgx_dev_ctx *ctx = container_of(dev, struct sgx_dev_ctx, + ctrl_dev); + + kfree(ctx); +} + +static struct sgx_dev_ctx *sgx_dev_ctx_alloc(struct device *parent) +{ + struct sgx_dev_ctx *ctx; + int ret; + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return ERR_PTR(-ENOMEM); + + device_initialize(&ctx->ctrl_dev); + + ctx->ctrl_dev.bus = &sgx_bus_type; + ctx->ctrl_dev.type = &sgx_device_type; + ctx->ctrl_dev.parent = parent; + ctx->ctrl_dev.devt = MKDEV(MAJOR(sgx_devt), 0); + ctx->ctrl_dev.release = sgx_dev_release; + + ret = dev_set_name(&ctx->ctrl_dev, "sgx"); + if (ret) { + put_device(&ctx->ctrl_dev); + return ERR_PTR(ret); + } + + cdev_init(&ctx->ctrl_cdev, &sgx_ctrl_fops); + ctx->ctrl_cdev.owner = THIS_MODULE; + + dev_set_drvdata(parent, ctx); + + return ctx; +} + +static struct sgx_dev_ctx *sgxm_dev_ctx_alloc(struct device *parent) +{ + struct sgx_dev_ctx *ctx; + int rc; + + ctx = sgx_dev_ctx_alloc(parent); + if (IS_ERR(ctx)) + return ctx; + + rc = devm_add_action_or_reset(parent, (void (*)(void *))put_device, + &ctx->ctrl_dev); + if (rc) + return ERR_PTR(rc); + + return ctx; +} + +static int sgx_dev_init(struct device *parent) +{ + struct sgx_dev_ctx *sgx_dev; + unsigned int eax; + unsigned int ebx; + unsigned int ecx; + unsigned int edx; + u64 attr_mask; + u64 xfrm_mask; + int ret; + int i; + + cpuid_count(SGX_CPUID, 0, &eax, &ebx, &ecx, &edx); + sgx_misc_reserved_mask = ~ebx | SGX_MISC_RESERVED_MASK; + sgx_encl_size_max_64 = 1ULL << ((edx >> 8) & 0xFF); + sgx_encl_size_max_32 = 1ULL << (edx & 0xFF); + + cpuid_count(SGX_CPUID, 1, &eax, &ebx, &ecx, &edx); + + attr_mask = (((u64)ebx) << 32) + (u64)eax; + sgx_attributes_reserved_mask = ~attr_mask | SGX_ATTR_RESERVED_MASK; + + if (boot_cpu_has(X86_FEATURE_OSXSAVE)) { + xfrm_mask = (((u64)edx) << 32) + (u64)ecx; + + for (i = 2; i < 64; i++) { + cpuid_count(0x0D, i, &eax, &ebx, &ecx, &edx); + if ((1 << i) & xfrm_mask) + sgx_xsave_size_tbl[i] = eax + ebx; + } + + sgx_xfrm_reserved_mask = ~xfrm_mask; + } + + sgx_dev = sgxm_dev_ctx_alloc(parent); + if (IS_ERR(sgx_dev)) + return PTR_ERR(sgx_dev); + + sgx_encl_wq = alloc_workqueue("sgx-encl-wq", + WQ_UNBOUND | WQ_FREEZABLE, 1); + if (!sgx_encl_wq) + return -ENOMEM; + + ret = cdev_device_add(&sgx_dev->ctrl_cdev, &sgx_dev->ctrl_dev); + if (ret) + goto err_device_add; + + return 0; + +err_device_add: + destroy_workqueue(sgx_encl_wq); + return ret; +} + +static int sgx_drv_probe(struct platform_device *pdev) +{ + if (!sgx_enabled) { + pr_info("sgx: SGX is not enabled in the core\n"); + return -ENODEV; + } + + if (!boot_cpu_has(X86_FEATURE_SGX_LC)) { + pr_info("sgx: The public key MSRs are not writable\n"); + return -ENODEV; + } + + return sgx_dev_init(&pdev->dev); +} + +static int sgx_drv_remove(struct platform_device *pdev) +{ + struct sgx_dev_ctx *ctx = dev_get_drvdata(&pdev->dev); + + cdev_device_del(&ctx->ctrl_cdev, &ctx->ctrl_dev); + destroy_workqueue(sgx_encl_wq); + + return 0; +} + +#ifdef CONFIG_ACPI +static struct acpi_device_id sgx_device_ids[] = { + {"INT0E0C", 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, sgx_device_ids); +#endif + +static struct platform_driver sgx_drv = { + .probe = sgx_drv_probe, + .remove = sgx_drv_remove, + .driver = { + .name = "sgx", + .acpi_match_table = ACPI_PTR(sgx_device_ids), + }, +}; + +static int __init sgx_drv_subsys_init(void) +{ + int ret; + + ret = bus_register(&sgx_bus_type); + if (ret) + return ret; + + ret = alloc_chrdev_region(&sgx_devt, 0, SGX_DRV_NR_DEVICES, "sgx"); + if (ret < 0) { + bus_unregister(&sgx_bus_type); + return ret; + } + + return 0; +} + +static void sgx_drv_subsys_exit(void) +{ + bus_unregister(&sgx_bus_type); + unregister_chrdev_region(sgx_devt, SGX_DRV_NR_DEVICES); +} + +static int __init sgx_drv_init(void) +{ + int ret; + + ret = sgx_drv_subsys_init(); + if (ret) + return ret; + + ret = platform_driver_register(&sgx_drv); + if (ret) + sgx_drv_subsys_exit(); + + return ret; +} +module_init(sgx_drv_init); + +static void __exit sgx_drv_exit(void) +{ + platform_driver_unregister(&sgx_drv); + sgx_drv_subsys_exit(); +} +module_exit(sgx_drv_exit); diff --git a/arch/x86/kernel/cpu/sgx/encl.c b/arch/x86/kernel/cpu/sgx/encl.c new file mode 100644 index 000000000000..bd8bcd748976 --- /dev/null +++ b/arch/x86/kernel/cpu/sgx/encl.c @@ -0,0 +1,358 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// Copyright(c) 2016-18 Intel Corporation. + +#include +#include +#include +#include +#include "arch.h" +#include "encl.h" +#include "sgx.h" + +static struct sgx_encl_page *sgx_encl_load_page(struct sgx_encl *encl, + unsigned long addr) +{ + struct sgx_encl_page *entry; + + /* If process was forked, VMA is still there but vm_private_data is set + * to NULL. + */ + if (!encl) + return ERR_PTR(-EFAULT); + + if ((encl->flags & SGX_ENCL_DEAD) || + !(encl->flags & SGX_ENCL_INITIALIZED)) + return ERR_PTR(-EFAULT); + + entry = radix_tree_lookup(&encl->page_tree, addr >> PAGE_SHIFT); + if (!entry) + return ERR_PTR(-EFAULT); + + /* Page is already resident in the EPC. */ + if (entry->epc_page) + return entry; + + return ERR_PTR(-EFAULT); +} + +static struct sgx_encl_mm *sgx_encl_get_mm(struct sgx_encl *encl, + struct mm_struct *mm) +{ + struct sgx_encl_mm *next_mm = NULL; + struct sgx_encl_mm *prev_mm = NULL; + int iter; + + while (true) { + next_mm = sgx_encl_next_mm(encl, prev_mm, &iter); + if (prev_mm) { + mmdrop(prev_mm->mm); + kref_put(&prev_mm->refcount, sgx_encl_release_mm); + } + prev_mm = next_mm; + + if (iter == SGX_ENCL_MM_ITER_DONE) + break; + + if (iter == SGX_ENCL_MM_ITER_RESTART) + continue; + + if (mm == next_mm->mm) + return next_mm; + } + + return NULL; +} + +static void sgx_vma_open(struct vm_area_struct *vma) +{ + struct sgx_encl *encl = vma->vm_private_data; + struct sgx_encl_mm *mm; + + if (!encl) + return; + + if (encl->flags & SGX_ENCL_DEAD) + goto out; + + mm = sgx_encl_get_mm(encl, vma->vm_mm); + if (!mm) { + mm = kzalloc(sizeof(*mm), GFP_KERNEL); + if (!mm) { + encl->flags |= SGX_ENCL_DEAD; + goto out; + } + + spin_lock(&encl->mm_lock); + mm->encl = encl; + mm->mm = vma->vm_mm; + list_add(&mm->list, &encl->mm_list); + kref_init(&mm->refcount); + spin_unlock(&encl->mm_lock); + } else { + mmdrop(mm->mm); + } + +out: + kref_get(&encl->refcount); +} + +static void sgx_vma_close(struct vm_area_struct *vma) +{ + struct sgx_encl *encl = vma->vm_private_data; + struct sgx_encl_mm *mm; + + if (!encl) + return; + + mm = sgx_encl_get_mm(encl, vma->vm_mm); + if (mm) { + mmdrop(mm->mm); + kref_put(&mm->refcount, sgx_encl_release_mm); + + /* Release kref for the VMA. */ + kref_put(&mm->refcount, sgx_encl_release_mm); + } + + kref_put(&encl->refcount, sgx_encl_release); +} + +static unsigned int sgx_vma_fault(struct vm_fault *vmf) +{ + unsigned long addr = (unsigned long)vmf->address; + struct vm_area_struct *vma = vmf->vma; + struct sgx_encl *encl = vma->vm_private_data; + struct sgx_encl_page *entry; + int ret = VM_FAULT_NOPAGE; + struct sgx_encl_mm *mm; + unsigned long pfn; + + mm = sgx_encl_get_mm(encl, vma->vm_mm); + if (!mm) + return VM_FAULT_SIGBUS; + + mmdrop(mm->mm); + kref_put(&mm->refcount, sgx_encl_release_mm); + + mutex_lock(&encl->lock); + + entry = sgx_encl_load_page(encl, addr); + if (IS_ERR(entry)) { + if (unlikely(PTR_ERR(entry) != -EBUSY)) + ret = VM_FAULT_SIGBUS; + + goto out; + } + + if (!follow_pfn(vma, addr, &pfn)) + goto out; + + ret = vmf_insert_pfn(vma, addr, PFN_DOWN(entry->epc_page->desc)); + if (ret != VM_FAULT_NOPAGE) { + ret = VM_FAULT_SIGBUS; + goto out; + } + +out: + mutex_unlock(&encl->lock); + return ret; +} + +const struct vm_operations_struct sgx_vm_ops = { + .close = sgx_vma_close, + .open = sgx_vma_open, + .fault = sgx_vma_fault, +}; +EXPORT_SYMBOL_GPL(sgx_vm_ops); + +/** + * sgx_encl_find - find an enclave + * @mm: mm struct of the current process + * @addr: address in the ELRANGE + * @vma: the resulting VMA + * + * Find an enclave identified by the given address. Give back a VMA that is + * part of the enclave and located in that address. The VMA is given back if it + * is a proper enclave VMA even if an &sgx_encl instance does not exist yet + * (enclave creation has not been performed). + * + * Return: + * 0 on success, + * -EINVAL if an enclave was not found, + * -ENOENT if the enclave has not been created yet + */ +int sgx_encl_find(struct mm_struct *mm, unsigned long addr, + struct vm_area_struct **vma) +{ + struct vm_area_struct *result; + struct sgx_encl *encl; + + result = find_vma(mm, addr); + if (!result || result->vm_ops != &sgx_vm_ops || addr < result->vm_start) + return -EINVAL; + + encl = result->vm_private_data; + *vma = result; + + return encl ? 0 : -ENOENT; +} +EXPORT_SYMBOL_GPL(sgx_encl_find); + +/** + * sgx_encl_destroy() - destroy enclave resources + * @encl: an &sgx_encl instance + */ +void sgx_encl_destroy(struct sgx_encl *encl) +{ + struct sgx_encl_page *entry; + struct radix_tree_iter iter; + void **slot; + + encl->flags |= SGX_ENCL_DEAD; + + radix_tree_for_each_slot(slot, &encl->page_tree, &iter, 0) { + entry = *slot; + if (entry->epc_page) { + if (!__sgx_free_page(entry->epc_page)) { + encl->secs_child_cnt--; + entry->epc_page = NULL; + + } + + radix_tree_delete(&entry->encl->page_tree, + PFN_DOWN(entry->desc)); + } + } + + if (!encl->secs_child_cnt && encl->secs.epc_page) { + sgx_free_page(encl->secs.epc_page); + encl->secs.epc_page = NULL; + } +} +EXPORT_SYMBOL_GPL(sgx_encl_destroy); + +/** + * sgx_encl_release - Destroy an enclave instance + * @kref: address of a kref inside &sgx_encl + * + * Used together with kref_put(). Frees all the resources associated with the + * enclave and the instance itself. + */ +void sgx_encl_release(struct kref *ref) +{ + struct sgx_encl *encl = container_of(ref, struct sgx_encl, refcount); + struct sgx_encl_mm *mm; + + if (encl->pm_notifier.notifier_call) + unregister_pm_notifier(&encl->pm_notifier); + + sgx_encl_destroy(encl); + + if (encl->backing) + fput(encl->backing); + + /* If sgx_encl_create() fails, can be non-empty */ + while (!list_empty(&encl->mm_list)) { + mm = list_first_entry(&encl->mm_list, struct sgx_encl_mm, list); + list_del(&mm->list); + kfree(mm); + } + + kfree(encl); +} +EXPORT_SYMBOL_GPL(sgx_encl_release); + +/** + * sgx_encl_get_index() - Convert a page descriptor to a page index + * @encl: an enclave + * @page: an enclave page + * + * Given an enclave page descriptor, convert it to a page index used to access + * backing storage. The backing page for SECS is located after the enclave + * pages. + */ +pgoff_t sgx_encl_get_index(struct sgx_encl *encl, struct sgx_encl_page *page) +{ + if (!PFN_DOWN(page->desc)) + return PFN_DOWN(encl->size); + + return PFN_DOWN(page->desc - encl->base); +} +EXPORT_SYMBOL_GPL(sgx_encl_get_index); + +/** + * sgx_encl_encl_get_backing_page() - Pin the backing page + * @encl: an enclave + * @index: page index + * + * Return: the pinned backing page + */ +struct page *sgx_encl_get_backing_page(struct sgx_encl *encl, pgoff_t index) +{ + struct inode *inode = encl->backing->f_path.dentry->d_inode; + struct address_space *mapping = inode->i_mapping; + gfp_t gfpmask = mapping_gfp_mask(mapping); + + return shmem_read_mapping_page_gfp(mapping, index, gfpmask); +} +EXPORT_SYMBOL_GPL(sgx_encl_get_backing_page); + +/** + * sgx_encl_next_mm() - Iterate to the next mm + * @encl: an enclave + * @mm: an mm list entry + * @iter: iterator status + * + * Return: the enclave mm or NULL + */ +struct sgx_encl_mm *sgx_encl_next_mm(struct sgx_encl *encl, + struct sgx_encl_mm *mm, int *iter) +{ + struct list_head *entry; + + WARN(!encl, "%s: encl is NULL", __func__); + WARN(!iter, "%s: iter is NULL", __func__); + + spin_lock(&encl->mm_lock); + + entry = mm ? mm->list.next : encl->mm_list.next; + WARN(!entry, "%s: entry is NULL", __func__); + + if (entry == &encl->mm_list) { + mm = NULL; + *iter = SGX_ENCL_MM_ITER_DONE; + goto out; + } + + mm = list_entry(entry, struct sgx_encl_mm, list); + + if (!kref_get_unless_zero(&mm->refcount)) { + *iter = SGX_ENCL_MM_ITER_RESTART; + mm = NULL; + goto out; + } + + if (!atomic_add_unless(&mm->mm->mm_count, 1, 0)) { + kref_put(&mm->refcount, sgx_encl_release_mm); + mm = NULL; + *iter = SGX_ENCL_MM_ITER_RESTART; + goto out; + } + + *iter = SGX_ENCL_MM_ITER_NEXT; + +out: + spin_unlock(&encl->mm_lock); + return mm; +} + +void sgx_encl_release_mm(struct kref *ref) +{ + struct sgx_encl_mm *mm = + container_of(ref, struct sgx_encl_mm, refcount); + + spin_lock(&mm->encl->mm_lock); + list_del(&mm->list); + spin_unlock(&mm->encl->mm_lock); + + kfree(mm); +} diff --git a/arch/x86/kernel/cpu/sgx/encl.h b/arch/x86/kernel/cpu/sgx/encl.h new file mode 100644 index 000000000000..374ad3396684 --- /dev/null +++ b/arch/x86/kernel/cpu/sgx/encl.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/** + * Copyright(c) 2016-19 Intel Corporation. + */ +#ifndef _X86_ENCL_H +#define _X86_ENCL_H + +#include + +/** + * enum sgx_encl_page_desc - defines bits for an enclave page's descriptor + * %SGX_ENCL_PAGE_TCS: The page is a TCS page. + * %SGX_ENCL_PAGE_ADDR_MASK: Holds the virtual address of the page. + * + * The page address for SECS is zero and is used by the subsystem to recognize + * the SECS page. + */ +enum sgx_encl_page_desc { + SGX_ENCL_PAGE_TCS = BIT(0), + /* Bits 11:3 are available when the page is not swapped. */ + SGX_ENCL_PAGE_ADDR_MASK = PAGE_MASK, +}; + +#define SGX_ENCL_PAGE_ADDR(encl_page) \ + ((encl_page)->desc & SGX_ENCL_PAGE_ADDR_MASK) +#define SGX_ENCL_PAGE_VA_OFFSET(encl_page) \ + ((encl_page)->desc & SGX_ENCL_PAGE_VA_OFFSET_MASK) + +struct sgx_encl_page { + unsigned long desc; + struct sgx_epc_page *epc_page; + struct sgx_encl *encl; +}; + +enum sgx_encl_flags { + SGX_ENCL_INITIALIZED = BIT(0), + SGX_ENCL_DEBUG = BIT(1), + SGX_ENCL_SUSPEND = BIT(2), + SGX_ENCL_DEAD = BIT(3), +}; + +struct sgx_encl_mm { + struct sgx_encl *encl; + struct mm_struct *mm; + struct kref refcount; + struct list_head list; +}; + +struct sgx_encl { + unsigned int flags; + u64 secs_attributes; + u64 allowed_attributes; + unsigned int page_cnt; + unsigned int secs_child_cnt; + struct mutex lock; + struct list_head mm_list; + spinlock_t mm_lock; + struct file *backing; + struct kref refcount; + unsigned long base; + unsigned long size; + unsigned long ssaframesize; + struct radix_tree_root page_tree; + struct list_head add_page_reqs; + struct work_struct work; + struct sgx_encl_page secs; + struct notifier_block pm_notifier; +}; + +extern const struct vm_operations_struct sgx_vm_ops; + +enum sgx_encl_mm_iter { + SGX_ENCL_MM_ITER_DONE = 0, + SGX_ENCL_MM_ITER_NEXT = 1, + SGX_ENCL_MM_ITER_RESTART = 2, +}; + +int sgx_encl_find(struct mm_struct *mm, unsigned long addr, + struct vm_area_struct **vma); +void sgx_encl_destroy(struct sgx_encl *encl); +void sgx_encl_release(struct kref *ref); +pgoff_t sgx_encl_get_index(struct sgx_encl *encl, struct sgx_encl_page *page); +struct page *sgx_encl_get_backing_page(struct sgx_encl *encl, pgoff_t index); +struct sgx_encl_mm *sgx_encl_next_mm(struct sgx_encl *encl, + struct sgx_encl_mm *mm, int *iter); +void sgx_encl_release_mm(struct kref *ref); + +#endif /* _X86_ENCL_H */ diff --git a/arch/x86/kernel/cpu/sgx/encls.c b/arch/x86/kernel/cpu/sgx/encls.c index 5045f1365e07..698cc526bfbf 100644 --- a/arch/x86/kernel/cpu/sgx/encls.c +++ b/arch/x86/kernel/cpu/sgx/encls.c @@ -19,3 +19,4 @@ bool encls_failed(int ret) return encls_faulted(ret) && ENCLS_TRAPNR(ret) != epcm_trapnr; } +EXPORT_SYMBOL_GPL(encls_failed); diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c index e966f96837c7..d88dc3d1d4a7 100644 --- a/arch/x86/kernel/cpu/sgx/main.c +++ b/arch/x86/kernel/cpu/sgx/main.c @@ -14,6 +14,8 @@ struct sgx_epc_section sgx_epc_sections[SGX_MAX_EPC_SECTIONS]; EXPORT_SYMBOL_GPL(sgx_epc_sections); +bool sgx_enabled; +EXPORT_SYMBOL_GPL(sgx_enabled); static int sgx_nr_epc_sections; @@ -283,6 +285,7 @@ static __init int sgx_init(void) if (ret) return ret; + sgx_enabled = true; return 0; } diff --git a/arch/x86/kernel/cpu/sgx/sgx.h b/arch/x86/kernel/cpu/sgx/sgx.h index f90d02fbbbbd..2337b63ba487 100644 --- a/arch/x86/kernel/cpu/sgx/sgx.h +++ b/arch/x86/kernel/cpu/sgx/sgx.h @@ -34,6 +34,7 @@ struct sgx_epc_section { #define SGX_MAX_EPC_SECTIONS 8 extern struct sgx_epc_section sgx_epc_sections[SGX_MAX_EPC_SECTIONS]; +extern bool sgx_enabled; /** * enum sgx_epc_page_desc - bits and masks for an EPC page's descriptor From patchwork Sun Mar 17 21:14:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 10856623 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 C81FB1390 for ; Sun, 17 Mar 2019 21:18:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B0F13291EE for ; Sun, 17 Mar 2019 21:18:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A51B52922A; Sun, 17 Mar 2019 21:18:18 +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 79744291EE for ; Sun, 17 Mar 2019 21:18:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727054AbfCQVSR (ORCPT ); Sun, 17 Mar 2019 17:18:17 -0400 Received: from mga02.intel.com ([134.134.136.20]:8746 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726229AbfCQVSR (ORCPT ); Sun, 17 Mar 2019 17:18:17 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Mar 2019 14:18:12 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,491,1544515200"; d="scan'208";a="142817207" Received: from vanderss-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.254.193]) by orsmga002.jf.intel.com with ESMTP; 17 Mar 2019 14:18:03 -0700 From: Jarkko Sakkinen To: x86@kernel.org, linux-sgx@vger.kernel.org Cc: akpm@linux-foundation.org, dave.hansen@intel.com, sean.j.christopherson@intel.com, nhorman@redhat.com, npmccallum@redhat.com, serge.ayoun@intel.com, shay.katz-zamir@intel.com, haitao.huang@intel.com, andriy.shevchenko@linux.intel.com, tglx@linutronix.de, kai.svahn@intel.com, bp@alien8.de, josh@joshtriplett.org, luto@kernel.org, kai.huang@intel.com, rientjes@google.com, Jarkko Sakkinen , James Morris , "Serge E . Hallyn" , linux-security-module@vger.kernel.org Subject: [PATCH v19 17/27] x86/sgx: Add provisioning Date: Sun, 17 Mar 2019 23:14:46 +0200 Message-Id: <20190317211456.13927-18-jarkko.sakkinen@linux.intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> References: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> MIME-Version: 1.0 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 In order to provide a mechanism for devilering provisoning rights: 1. Add a new file to the securityfs file called sgx/provision that works as a token for allowing an enclave to have the provisioning privileges. 2. Add a new ioctl called SGX_IOC_ENCLAVE_SET_ATTRIBUTE that accepts the following data structure: struct sgx_enclave_set_attribute { __u64 addr; __u64 token_fd; }; A daemon could sit on top of sgx/provision and send a file descriptor of this file to a process that needs to be able to provision enclaves. The way this API is used is more or less straight-forward. Lets assume that dev_fd is a handle to /dev/sgx and prov_fd is a handle to sgx/provision. You would allow SGX_IOC_ENCLAVE_CREATE to initialize an enclave with the PROVISIONKEY attribute by params.addr = ; params.token_fd = prov_fd; ioctl(dev_fd, SGX_IOC_ENCLAVE_SET_ATTRIBUTE, ¶ms); Cc: James Morris Cc: Serge E. Hallyn Cc: linux-security-module@vger.kernel.org Suggested-by: Andy Lutomirski Signed-off-by: Jarkko Sakkinen --- arch/x86/include/uapi/asm/sgx.h | 13 +++++++ arch/x86/kernel/cpu/sgx/driver/ioctl.c | 43 +++++++++++++++++++++++ arch/x86/kernel/cpu/sgx/driver/main.c | 47 ++++++++++++++++++++++++++ 3 files changed, 103 insertions(+) diff --git a/arch/x86/include/uapi/asm/sgx.h b/arch/x86/include/uapi/asm/sgx.h index aadf9c76e360..150a784db395 100644 --- a/arch/x86/include/uapi/asm/sgx.h +++ b/arch/x86/include/uapi/asm/sgx.h @@ -16,6 +16,8 @@ _IOW(SGX_MAGIC, 0x01, struct sgx_enclave_add_page) #define SGX_IOC_ENCLAVE_INIT \ _IOW(SGX_MAGIC, 0x02, struct sgx_enclave_init) +#define SGX_IOC_ENCLAVE_SET_ATTRIBUTE \ + _IOW(SGX_MAGIC, 0x03, struct sgx_enclave_set_attribute) /* IOCTL return values */ #define SGX_POWER_LOST_ENCLAVE 0x40000000 @@ -56,4 +58,15 @@ struct sgx_enclave_init { __u64 sigstruct; }; +/** + * struct sgx_enclave_set_attribute - parameter structure for the + * %SGX_IOC_ENCLAVE_INIT ioctl + * @addr: address within the ELRANGE + * @attribute_fd: file handle of the attribute file in the securityfs + */ +struct sgx_enclave_set_attribute { + __u64 addr; + __u64 attribute_fd; +}; + #endif /* _UAPI_ASM_X86_SGX_H */ diff --git a/arch/x86/kernel/cpu/sgx/driver/ioctl.c b/arch/x86/kernel/cpu/sgx/driver/ioctl.c index 4b9a91b53b50..5d85bd3f7876 100644 --- a/arch/x86/kernel/cpu/sgx/driver/ioctl.c +++ b/arch/x86/kernel/cpu/sgx/driver/ioctl.c @@ -759,6 +759,46 @@ static long sgx_ioc_enclave_init(struct file *filep, unsigned int cmd, return ret; } +/** + * sgx_ioc_enclave_set_attribute - handler for %SGX_IOC_ENCLAVE_SET_ATTRIBUTE + * @filep: open file to /dev/sgx + * @cmd: the command value + * @arg: pointer to a struct sgx_enclave_set_attribute instance + * + * Sets an attribute matching the attribute file that is pointed by the + * parameter structure field attribute_fd. + * + * Return: 0 on success, -errno otherwise + */ +static long sgx_ioc_enclave_set_attribute(struct file *filep, unsigned int cmd, + unsigned long arg) +{ + struct sgx_enclave_set_attribute *params = (void *)arg; + struct file *attribute_file; + struct sgx_encl *encl; + int ret; + + attribute_file = fget(params->attribute_fd); + if (!attribute_file->f_op) + return -EINVAL; + + if (attribute_file->f_op != &sgx_fs_provision_fops) { + ret = -EINVAL; + goto out; + } + + ret = sgx_encl_get(params->addr, &encl); + if (ret) + goto out; + + encl->allowed_attributes |= SGX_ATTR_PROVISIONKEY; + kref_put(&encl->refcount, sgx_encl_release); + +out: + fput(attribute_file); + return ret; +} + typedef long (*sgx_ioc_t)(struct file *filep, unsigned int cmd, unsigned long arg); @@ -778,6 +818,9 @@ long sgx_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) case SGX_IOC_ENCLAVE_INIT: handler = sgx_ioc_enclave_init; break; + case SGX_IOC_ENCLAVE_SET_ATTRIBUTE: + handler = sgx_ioc_enclave_set_attribute; + break; default: return -ENOIOCTLCMD; } diff --git a/arch/x86/kernel/cpu/sgx/driver/main.c b/arch/x86/kernel/cpu/sgx/driver/main.c index 16f36cd0af04..9a5360dcad98 100644 --- a/arch/x86/kernel/cpu/sgx/driver/main.c +++ b/arch/x86/kernel/cpu/sgx/driver/main.c @@ -22,6 +22,11 @@ u64 sgx_attributes_reserved_mask; u64 sgx_xfrm_reserved_mask = ~0x3; u32 sgx_xsave_size_tbl[64]; +const struct file_operations sgx_fs_provision_fops; + +static struct dentry *sgx_fs; +static struct dentry *sgx_fs_provision; + #ifdef CONFIG_COMPAT static long sgx_compat_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) @@ -147,6 +152,40 @@ static struct sgx_dev_ctx *sgxm_dev_ctx_alloc(struct device *parent) return ctx; } +static int sgx_fs_init(struct device *dev) +{ + int ret; + + sgx_fs = securityfs_create_dir(dev_name(dev), NULL); + if (IS_ERR(sgx_fs)) { + ret = PTR_ERR(sgx_fs); + goto err_sgx_fs; + } + + sgx_fs_provision = securityfs_create_file("provision", 0600, sgx_fs, + NULL, &sgx_fs_provision_fops); + if (IS_ERR(sgx_fs)) { + ret = PTR_ERR(sgx_fs_provision); + goto err_sgx_fs_provision; + } + + return 0; + +err_sgx_fs_provision: + securityfs_remove(sgx_fs); + sgx_fs_provision = NULL; + +err_sgx_fs: + sgx_fs = NULL; + return ret; +} + +static void sgx_fs_remove(void) +{ + securityfs_remove(sgx_fs_provision); + securityfs_remove(sgx_fs); +} + static int sgx_dev_init(struct device *parent) { struct sgx_dev_ctx *sgx_dev; @@ -190,6 +229,10 @@ static int sgx_dev_init(struct device *parent) if (!sgx_encl_wq) return -ENOMEM; + ret = sgx_fs_init(&sgx_dev->ctrl_dev); + if (ret) + goto err_fs_init; + ret = cdev_device_add(&sgx_dev->ctrl_cdev, &sgx_dev->ctrl_dev); if (ret) goto err_device_add; @@ -197,6 +240,9 @@ static int sgx_dev_init(struct device *parent) return 0; err_device_add: + sgx_fs_remove(); + +err_fs_init: destroy_workqueue(sgx_encl_wq); return ret; } @@ -220,6 +266,7 @@ static int sgx_drv_remove(struct platform_device *pdev) { struct sgx_dev_ctx *ctx = dev_get_drvdata(&pdev->dev); + sgx_fs_remove(); cdev_device_del(&ctx->ctrl_cdev, &ctx->ctrl_dev); destroy_workqueue(sgx_encl_wq); From patchwork Sun Mar 17 21:14:48 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 10856627 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 242131575 for ; Sun, 17 Mar 2019 21:18:36 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0E2D4291EE for ; Sun, 17 Mar 2019 21:18:36 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0097329214; Sun, 17 Mar 2019 21:18:35 +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 84686291EE for ; Sun, 17 Mar 2019 21:18:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727173AbfCQVSf (ORCPT ); Sun, 17 Mar 2019 17:18:35 -0400 Received: from mga07.intel.com ([134.134.136.100]:4142 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727054AbfCQVSe (ORCPT ); Sun, 17 Mar 2019 17:18:34 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Mar 2019 14:18:34 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,491,1544515200"; d="scan'208";a="142817250" Received: from vanderss-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.254.193]) by orsmga002.jf.intel.com with ESMTP; 17 Mar 2019 14:18:25 -0700 From: Jarkko Sakkinen To: x86@kernel.org, linux-sgx@vger.kernel.org Cc: akpm@linux-foundation.org, dave.hansen@intel.com, sean.j.christopherson@intel.com, nhorman@redhat.com, npmccallum@redhat.com, serge.ayoun@intel.com, shay.katz-zamir@intel.com, haitao.huang@intel.com, andriy.shevchenko@linux.intel.com, tglx@linutronix.de, kai.svahn@intel.com, bp@alien8.de, josh@joshtriplett.org, luto@kernel.org, kai.huang@intel.com, rientjes@google.com, Jarkko Sakkinen Subject: [PATCH v19 19/27] x86/sgx: ptrace() support for the SGX driver Date: Sun, 17 Mar 2019 23:14:48 +0200 Message-Id: <20190317211456.13927-20-jarkko.sakkinen@linux.intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> References: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> MIME-Version: 1.0 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 Add VMA callbacks for ptrace() that can be used with debug enclaves. With debug enclaves data can be read and write the memory word at a time by using ENCLS(EDBGRD) and ENCLS(EDBGWR) leaf instructions. Signed-off-by: Jarkko Sakkinen --- arch/x86/kernel/cpu/sgx/encl.c | 97 ++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/arch/x86/kernel/cpu/sgx/encl.c b/arch/x86/kernel/cpu/sgx/encl.c index 1b8874699dd3..5b5fc933ee19 100644 --- a/arch/x86/kernel/cpu/sgx/encl.c +++ b/arch/x86/kernel/cpu/sgx/encl.c @@ -256,10 +256,107 @@ static unsigned int sgx_vma_fault(struct vm_fault *vmf) return ret; } +static int sgx_edbgrd(struct sgx_encl *encl, struct sgx_encl_page *page, + unsigned long addr, void *data) +{ + unsigned long offset; + int ret; + + offset = addr & ~PAGE_MASK; + + if ((page->desc & SGX_ENCL_PAGE_TCS) && + offset > offsetof(struct sgx_tcs, gs_limit)) + return -ECANCELED; + + ret = __edbgrd(sgx_epc_addr(page->epc_page) + offset, data); + if (ret) + return -EIO; + + return 0; +} + +static int sgx_edbgwr(struct sgx_encl *encl, struct sgx_encl_page *page, + unsigned long addr, void *data) +{ + unsigned long offset; + int ret; + + offset = addr & ~PAGE_MASK; + + /* Writing anything else than flags will cause #GP */ + if ((page->desc & SGX_ENCL_PAGE_TCS) && + offset != offsetof(struct sgx_tcs, flags)) + return -ECANCELED; + + ret = __edbgwr(sgx_epc_addr(page->epc_page) + offset, data); + if (ret) + return -EIO; + + return 0; +} + +static int sgx_vma_access(struct vm_area_struct *vma, unsigned long addr, + void *buf, int len, int write) +{ + struct sgx_encl *encl = vma->vm_private_data; + struct sgx_encl_page *entry = NULL; + unsigned long align; + char data[sizeof(unsigned long)]; + int offset; + int cnt; + int ret = 0; + int i; + + /* If process was forked, VMA is still there but vm_private_data is set + * to NULL. + */ + if (!encl) + return -EFAULT; + + if (!(encl->flags & SGX_ENCL_DEBUG) || + !(encl->flags & SGX_ENCL_INITIALIZED) || + (encl->flags & SGX_ENCL_DEAD)) + return -EFAULT; + + for (i = 0; i < len; i += cnt) { + entry = sgx_encl_reserve_page(encl, (addr + i) & PAGE_MASK); + if (IS_ERR(entry)) { + ret = PTR_ERR(entry); + break; + } + + align = ALIGN_DOWN(addr + i, sizeof(unsigned long)); + offset = (addr + i) & (sizeof(unsigned long) - 1); + cnt = sizeof(unsigned long) - offset; + cnt = min(cnt, len - i); + + ret = sgx_edbgrd(encl, entry, align, data); + if (ret) + goto out; + + if (write) { + memcpy(data + offset, buf + i, cnt); + ret = sgx_edbgwr(encl, entry, align, data); + if (ret) + goto out; + } else + memcpy(buf + i, data + offset, cnt); + +out: + mutex_unlock(&encl->lock); + + if (ret) + break; + } + + return ret < 0 ? ret : i; +} + const struct vm_operations_struct sgx_vm_ops = { .close = sgx_vma_close, .open = sgx_vma_open, .fault = sgx_vma_fault, + .access = sgx_vma_access, }; EXPORT_SYMBOL_GPL(sgx_vm_ops); From patchwork Sun Mar 17 21:14:49 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 10856629 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 64E971575 for ; Sun, 17 Mar 2019 21:18:49 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 49828291EE for ; Sun, 17 Mar 2019 21:18:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3D9A929214; Sun, 17 Mar 2019 21:18:49 +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 35F93291EE for ; Sun, 17 Mar 2019 21:18:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727054AbfCQVSs (ORCPT ); Sun, 17 Mar 2019 17:18:48 -0400 Received: from mga06.intel.com ([134.134.136.31]:23950 "EHLO mga06.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726702AbfCQVSr (ORCPT ); Sun, 17 Mar 2019 17:18:47 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Mar 2019 14:18:47 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,491,1544515200"; d="scan'208";a="142817275" Received: from vanderss-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.254.193]) by orsmga002.jf.intel.com with ESMTP; 17 Mar 2019 14:18:36 -0700 From: Jarkko Sakkinen To: x86@kernel.org, linux-sgx@vger.kernel.org Cc: akpm@linux-foundation.org, dave.hansen@intel.com, sean.j.christopherson@intel.com, nhorman@redhat.com, npmccallum@redhat.com, serge.ayoun@intel.com, shay.katz-zamir@intel.com, haitao.huang@intel.com, andriy.shevchenko@linux.intel.com, tglx@linutronix.de, kai.svahn@intel.com, bp@alien8.de, josh@joshtriplett.org, luto@kernel.org, kai.huang@intel.com, rientjes@google.com, Andy Lutomirski , Jarkko Sakkinen , Dave Hansen Subject: [PATCH v19 20/27] x86/vdso: Add support for exception fixup in vDSO functions Date: Sun, 17 Mar 2019 23:14:49 +0200 Message-Id: <20190317211456.13927-21-jarkko.sakkinen@linux.intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> References: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> MIME-Version: 1.0 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 From: Sean Christopherson The basic concept and implementation is very similar to the kernel's exception fixup mechanism. The key differences are that the kernel handler is hardcoded and the fixup entry addresses are relative to the overall table as opposed to individual entries. Hardcoding the kernel handler avoids the need to figure out how to get userspace code to point at a kernel function. Given that the expected usage is to propagate information to userspace, dumping all fault information into registers is likely the desired behavior for the vast majority of yet-to-be-created functions. Use registers DI, SI and DX to communicate fault information, which follows Linux's ABI for register consumption and hopefully avoids conflict with hardware features that might leverage the fixup capabilities, e.g. register usage for SGX instructions was at least partially designed with calling conventions in mind. Making fixup addresses relative to the overall table allows the table to be stripped from the final vDSO image (it's a kernel construct) without complicating the offset logic, e.g. entry-relative addressing would also need to account for the table's location relative to the image. Regarding stripping the table, modify vdso2c to extract the table from the raw, a.k.a. unstripped, data and dump it as a standalone byte array in the resulting .c file. The original base of the table, its length and a pointer to the byte array are captured in struct vdso_image. Alternatively, the table could be dumped directly into the struct, but because the number of entries can vary per image, that would require either hardcoding a max sized table into the struct definition or defining the table as a flexible length array. The flexible length array approach has zero benefits, e.g. the base/size are still needed, and prevents reusing the extraction code, while hardcoding the max size adds ongoing maintenance just to avoid exporting the explicit size. The immediate use case is for Intel Software Guard Extensions (SGX). SGX introduces a new CPL3-only "enclave" mode that runs as a sort of black box shared object that is hosted by an untrusted "normal" CPl3 process. Entering an enclave can only be done through SGX-specific instructions, EENTER and ERESUME, and is a non-trivial process. Because of the complexity of transitioning to/from an enclave, the vast majority of enclaves are expected to utilize a library to handle the actual transitions. This is roughly analogous to how e.g. libc implementations are used by most applications. Another crucial characteristic of SGX enclaves is that they can generate exceptions as part of their normal (at least as "normal" as SGX can be) operation that need to be handled *in* the enclave and/or are unique to SGX. And because they are essentially fancy shared objects, a process can host any number of enclaves, each of which can execute multiple threads simultaneously. Putting everything together, userspace enclaves will utilize a library that must be prepared to handle any and (almost) all exceptions any time at least one thread may be executing in an enclave. Leveraging signals to handle the enclave exceptions is unpleasant, to put it mildly, e.g. the SGX library must constantly (un)register its signal handler based on whether or not at least one thread is executing in an enclave, and filter and forward exceptions that aren't related to its enclaves. This becomes particularly nasty when using multiple levels of libraries that register signal handlers, e.g. running an enclave via cgo inside of the Go runtime. Enabling exception fixup in vDSO allows the kernel to provide a vDSO function that wraps the low-level transitions to/from the enclave, i.e. the EENTER and ERESUME instructions. The vDSO function can intercept exceptions that would otherwise generate a signal and return the fault information directly to its caller, thus avoiding the need to juggle signal handlers. Note that unlike the kernel's _ASM_EXTABLE_HANDLE implementation, the 'C' version of _ASM_VDSO_EXTABLE_HANDLE doesn't use a pre-compiled assembly macro. Duplicating four lines of code is simpler than adding the necessary infrastructure to generate pre-compiled assembly and the intended benefit of massaging GCC's inlining algorithm is unlikely to realized in the vDSO any time soon, if ever. Suggested-by: Andy Lutomirski Cc: Andy Lutomirski Cc: Jarkko Sakkinen Cc: Dave Hansen Cc: Josh Triplett Signed-off-by: Sean Christopherson --- arch/x86/entry/vdso/Makefile | 4 +- arch/x86/entry/vdso/extable.c | 37 +++++++++++++++++ arch/x86/entry/vdso/extable.h | 29 ++++++++++++++ arch/x86/entry/vdso/vdso-layout.lds.S | 9 ++++- arch/x86/entry/vdso/vdso2c.h | 58 +++++++++++++++++++++++---- arch/x86/include/asm/vdso.h | 5 +++ 6 files changed, 131 insertions(+), 11 deletions(-) create mode 100644 arch/x86/entry/vdso/extable.c create mode 100644 arch/x86/entry/vdso/extable.h diff --git a/arch/x86/entry/vdso/Makefile b/arch/x86/entry/vdso/Makefile index 5bfe2243a08f..34bcf87d358c 100644 --- a/arch/x86/entry/vdso/Makefile +++ b/arch/x86/entry/vdso/Makefile @@ -20,7 +20,7 @@ VDSO32-$(CONFIG_IA32_EMULATION) := y vobjs-y := vdso-note.o vclock_gettime.o vgetcpu.o # files to link into kernel -obj-y += vma.o +obj-y += vma.o extable.o OBJECT_FILES_NON_STANDARD_vma.o := n # vDSO images to build @@ -115,7 +115,7 @@ $(obj)/%-x32.o: $(obj)/%.o FORCE targets += vdsox32.lds $(vobjx32s-y) -$(obj)/%.so: OBJCOPYFLAGS := -S +$(obj)/%.so: OBJCOPYFLAGS := -S --remove-section __ex_table $(obj)/%.so: $(obj)/%.so.dbg $(call if_changed,objcopy) diff --git a/arch/x86/entry/vdso/extable.c b/arch/x86/entry/vdso/extable.c new file mode 100644 index 000000000000..49284d560d36 --- /dev/null +++ b/arch/x86/entry/vdso/extable.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include + +struct vdso_exception_table_entry { + int insn, fixup; +}; + +bool fixup_vdso_exception(struct pt_regs *regs, int trapnr, + unsigned long error_code, unsigned long fault_addr) +{ + const struct vdso_image *image = current->mm->context.vdso_image; + const struct vdso_exception_table_entry *extable; + unsigned int nr_entries, i; + unsigned long base; + + if (!current->mm->context.vdso) + return false; + + base = (unsigned long)current->mm->context.vdso + image->extable_base; + nr_entries = image->extable_len / (sizeof(*extable)); + extable = image->extable; + + for (i = 0; i < nr_entries; i++) { + if (regs->ip == base + extable[i].insn) { + regs->ip = base + extable[i].fixup; + regs->di = trapnr; + regs->si = error_code; + regs->dx = fault_addr; + return true; + } + } + + return false; +} diff --git a/arch/x86/entry/vdso/extable.h b/arch/x86/entry/vdso/extable.h new file mode 100644 index 000000000000..aafdac396948 --- /dev/null +++ b/arch/x86/entry/vdso/extable.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __VDSO_EXTABLE_H +#define __VDSO_EXTABLE_H + +/* + * Inject exception fixup for vDSO code. Unlike normal exception fixup, + * vDSO uses a dedicated handler the addresses are relative to the overall + * exception table, not each individual entry. + */ +#ifdef __ASSEMBLY__ +#define _ASM_VDSO_EXTABLE_HANDLE(from, to) \ + ASM_VDSO_EXTABLE_HANDLE from to + +.macro ASM_VDSO_EXTABLE_HANDLE from:req to:req + .pushsection __ex_table, "a" + .long (\from) - __ex_table + .long (\to) - __ex_table + .popsection +.endm +#else +#define _ASM_VDSO_EXTABLE_HANDLE(from, to) \ + ".pushsection __ex_table, \"a\"\n" \ + ".long (" #from ") - __ex_table\n" \ + ".long (" #to ") - __ex_table\n" \ + ".popsection\n" +#endif + +#endif /* __VDSO_EXTABLE_H */ + diff --git a/arch/x86/entry/vdso/vdso-layout.lds.S b/arch/x86/entry/vdso/vdso-layout.lds.S index 93c6dc7812d0..8ef849064501 100644 --- a/arch/x86/entry/vdso/vdso-layout.lds.S +++ b/arch/x86/entry/vdso/vdso-layout.lds.S @@ -63,11 +63,18 @@ SECTIONS * stuff that isn't used at runtime in between. */ - .text : { *(.text*) } :text =0x90909090, + .text : { + *(.text*) + *(.fixup) + } :text =0x90909090, + + .altinstructions : { *(.altinstructions) } :text .altinstr_replacement : { *(.altinstr_replacement) } :text + __ex_table : { *(__ex_table) } :text + /DISCARD/ : { *(.discard) *(.discard.*) diff --git a/arch/x86/entry/vdso/vdso2c.h b/arch/x86/entry/vdso/vdso2c.h index fa847a620f40..eca2f808bec3 100644 --- a/arch/x86/entry/vdso/vdso2c.h +++ b/arch/x86/entry/vdso/vdso2c.h @@ -5,6 +5,41 @@ * are built for 32-bit userspace. */ +static void BITSFUNC(copy)(FILE *outfile, const unsigned char *data, size_t len) +{ + size_t i; + + for (i = 0; i < len; i++) { + if (i % 10 == 0) + fprintf(outfile, "\n\t"); + fprintf(outfile, "0x%02X, ", (int)(data)[i]); + } +} + + +/* + * Extract a section from the input data into a standalone blob. Used to + * capture kernel-only data that needs to persist indefinitely, e.g. the + * exception fixup tables, but only in the kernel, i.e. the section can + * be stripped from the final vDSO image. + */ +static void BITSFUNC(extract)(const unsigned char *data, size_t data_len, + FILE *outfile, ELF(Shdr) *sec, const char *name) +{ + unsigned long offset; + size_t len; + + offset = (unsigned long)GET_LE(&sec->sh_offset); + len = (size_t)GET_LE(&sec->sh_size); + + if (offset + len > data_len) + fail("section to extract overruns input data"); + + fprintf(outfile, "static const unsigned char %s[%lu] = {", name, len); + BITSFUNC(copy)(outfile, data + offset, len); + fprintf(outfile, "\n};\n\n"); +} + static void BITSFUNC(go)(void *raw_addr, size_t raw_len, void *stripped_addr, size_t stripped_len, FILE *outfile, const char *name) @@ -14,9 +49,8 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len, unsigned long mapping_size; ELF(Ehdr) *hdr = (ELF(Ehdr) *)raw_addr; int i; - unsigned long j; ELF(Shdr) *symtab_hdr = NULL, *strtab_hdr, *secstrings_hdr, - *alt_sec = NULL; + *alt_sec = NULL, *extable_sec = NULL; ELF(Dyn) *dyn = 0, *dyn_end = 0; const char *secstrings; INT_BITS syms[NSYMS] = {}; @@ -78,6 +112,8 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len, if (!strcmp(secstrings + GET_LE(&sh->sh_name), ".altinstructions")) alt_sec = sh; + if (!strcmp(secstrings + GET_LE(&sh->sh_name), "__ex_table")) + extable_sec = sh; } if (!symtab_hdr) @@ -149,13 +185,11 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len, fprintf(outfile, "static unsigned char raw_data[%lu] __ro_after_init __aligned(PAGE_SIZE) = {", mapping_size); - for (j = 0; j < stripped_len; j++) { - if (j % 10 == 0) - fprintf(outfile, "\n\t"); - fprintf(outfile, "0x%02X, ", - (int)((unsigned char *)stripped_addr)[j]); - } + BITSFUNC(copy)(outfile, stripped_addr, stripped_len); fprintf(outfile, "\n};\n\n"); + if (extable_sec) + BITSFUNC(extract)(raw_addr, raw_len, outfile, + extable_sec, "extable"); fprintf(outfile, "const struct vdso_image %s = {\n", name); fprintf(outfile, "\t.data = raw_data,\n"); @@ -166,6 +200,14 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len, fprintf(outfile, "\t.alt_len = %lu,\n", (unsigned long)GET_LE(&alt_sec->sh_size)); } + if (extable_sec) { + fprintf(outfile, "\t.extable_base = %lu,\n", + (unsigned long)GET_LE(&extable_sec->sh_offset)); + fprintf(outfile, "\t.extable_len = %lu,\n", + (unsigned long)GET_LE(&extable_sec->sh_size)); + fprintf(outfile, "\t.extable = extable,\n"); + } + for (i = 0; i < NSYMS; i++) { if (required_syms[i].export && syms[i]) fprintf(outfile, "\t.sym_%s = %" PRIi64 ",\n", diff --git a/arch/x86/include/asm/vdso.h b/arch/x86/include/asm/vdso.h index 27566e57e87d..1c8a6a8f7b59 100644 --- a/arch/x86/include/asm/vdso.h +++ b/arch/x86/include/asm/vdso.h @@ -15,6 +15,8 @@ struct vdso_image { unsigned long size; /* Always a multiple of PAGE_SIZE */ unsigned long alt, alt_len; + unsigned long extable_base, extable_len; + const void *extable; long sym_vvar_start; /* Negative offset to the vvar area */ @@ -45,6 +47,9 @@ extern void __init init_vdso_image(const struct vdso_image *image); extern int map_vdso_once(const struct vdso_image *image, unsigned long addr); +extern bool fixup_vdso_exception(struct pt_regs *regs, int trapnr, + unsigned long error_code, + unsigned long fault_addr); #endif /* __ASSEMBLER__ */ #endif /* _ASM_X86_VDSO_H */ From patchwork Sun Mar 17 21:14:50 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 10856631 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 56CAD1390 for ; Sun, 17 Mar 2019 21:19:00 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3E059291EE for ; Sun, 17 Mar 2019 21:19:00 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 31A4129214; Sun, 17 Mar 2019 21:19:00 +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 2475629200 for ; Sun, 17 Mar 2019 21:18:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727467AbfCQVS6 (ORCPT ); Sun, 17 Mar 2019 17:18:58 -0400 Received: from mga17.intel.com ([192.55.52.151]:6017 "EHLO mga17.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727054AbfCQVS5 (ORCPT ); Sun, 17 Mar 2019 17:18:57 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga107.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Mar 2019 14:18:57 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,491,1544515200"; d="scan'208";a="142817288" Received: from vanderss-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.254.193]) by orsmga002.jf.intel.com with ESMTP; 17 Mar 2019 14:18:48 -0700 From: Jarkko Sakkinen To: x86@kernel.org, linux-sgx@vger.kernel.org Cc: akpm@linux-foundation.org, dave.hansen@intel.com, sean.j.christopherson@intel.com, nhorman@redhat.com, npmccallum@redhat.com, serge.ayoun@intel.com, shay.katz-zamir@intel.com, haitao.huang@intel.com, andriy.shevchenko@linux.intel.com, tglx@linutronix.de, kai.svahn@intel.com, bp@alien8.de, josh@joshtriplett.org, luto@kernel.org, kai.huang@intel.com, rientjes@google.com Subject: [PATCH v19 21/27] x86/fault: Add helper function to sanitize error code Date: Sun, 17 Mar 2019 23:14:50 +0200 Message-Id: <20190317211456.13927-22-jarkko.sakkinen@linux.intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> References: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> MIME-Version: 1.0 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 From: Sean Christopherson ...to prepare for vDSO exception fixup, which will expose the error code to userspace and runs before set_signal_archinfo(), i.e. suppresses the signal when fixup is successful. Signed-off-by: Sean Christopherson --- arch/x86/mm/fault.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 78e2807fbede..5babd515f616 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -719,6 +719,18 @@ pgtable_bad(struct pt_regs *regs, unsigned long error_code, oops_end(flags, regs, sig); } +static void sanitize_error_code(unsigned long address, + unsigned long *error_code) +{ + /* + * To avoid leaking information about the kernel page + * table layout, pretend that user-mode accesses to + * kernel addresses are always protection faults. + */ + if (address >= TASK_SIZE_MAX) + *error_code |= X86_PF_PROT; +} + static void set_signal_archinfo(unsigned long address, unsigned long error_code) { @@ -771,6 +783,8 @@ no_context(struct pt_regs *regs, unsigned long error_code, * faulting through the emulate_vsyscall() logic. */ if (current->thread.sig_on_uaccess_err && signal) { + sanitize_error_code(address, &error_code); + set_signal_archinfo(address, error_code); /* XXX: hwpoison faults will set the wrong code. */ @@ -920,13 +934,7 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code, if (is_errata100(regs, address)) return; - /* - * To avoid leaking information about the kernel page table - * layout, pretend that user-mode accesses to kernel addresses - * are always protection faults. - */ - if (address >= TASK_SIZE_MAX) - error_code |= X86_PF_PROT; + sanitize_error_code(address, &error_code); if (likely(show_unhandled_signals)) show_signal_msg(regs, error_code, address, tsk); @@ -1045,6 +1053,8 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address, if (is_prefetch(regs, error_code, address)) return; + sanitize_error_code(address, &error_code); + set_signal_archinfo(address, error_code); #ifdef CONFIG_MEMORY_FAILURE From patchwork Sun Mar 17 21:14:51 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 10856633 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 157D11575 for ; Sun, 17 Mar 2019 21:19:10 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id F006D28514 for ; Sun, 17 Mar 2019 21:19:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E411528F8F; Sun, 17 Mar 2019 21:19:09 +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 7F06A28514 for ; Sun, 17 Mar 2019 21:19:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727468AbfCQVTJ (ORCPT ); Sun, 17 Mar 2019 17:19:09 -0400 Received: from mga18.intel.com ([134.134.136.126]:64835 "EHLO mga18.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727054AbfCQVTI (ORCPT ); Sun, 17 Mar 2019 17:19:08 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Mar 2019 14:19:08 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,491,1544515200"; d="scan'208";a="142817297" Received: from vanderss-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.254.193]) by orsmga002.jf.intel.com with ESMTP; 17 Mar 2019 14:18:59 -0700 From: Jarkko Sakkinen To: x86@kernel.org, linux-sgx@vger.kernel.org Cc: akpm@linux-foundation.org, dave.hansen@intel.com, sean.j.christopherson@intel.com, nhorman@redhat.com, npmccallum@redhat.com, serge.ayoun@intel.com, shay.katz-zamir@intel.com, haitao.huang@intel.com, andriy.shevchenko@linux.intel.com, tglx@linutronix.de, kai.svahn@intel.com, bp@alien8.de, josh@joshtriplett.org, luto@kernel.org, kai.huang@intel.com, rientjes@google.com, Andy Lutomirski , Jarkko Sakkinen , Dave Hansen Subject: [PATCH v19 22/27] x86/fault: Attempt to fixup unhandled #PF in vDSO before signaling Date: Sun, 17 Mar 2019 23:14:51 +0200 Message-Id: <20190317211456.13927-23-jarkko.sakkinen@linux.intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> References: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> MIME-Version: 1.0 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 From: Sean Christopherson vDSO functions can now leverage an exception fixup mechanism similar to kernel exception fixup. For vDSO exception fixup, the initial user is Intel's Software Guard Extensions (SGX), which will wrap the low-level transitions to/from the enclave, i.e. EENTER and ERESUME instructions, in a vDSO function and leverage fixup to intercept exceptions that would otherwise generate a signal. This allows the vDSO wrapper to return the fault information directly to its caller, obviating the need for SGX applications and libraries to juggle signal handlers. Attempt to fixup vDSO exceptions immediately prior to populating and sending signal information. Except for the delivery mechanism, an exception in a vDSO function should be treated like any other exception in userspace, e.g. any fault that is successfully handled by the kernel should not be directly visible to userspace. Suggested-by: Andy Lutomirski Cc: Andy Lutomirski Cc: Jarkko Sakkinen Cc: Dave Hansen Cc: Josh Triplett Signed-off-by: Sean Christopherson --- arch/x86/mm/fault.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 5babd515f616..13be0c67379e 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -28,6 +28,7 @@ #include /* vma_pkey() */ #include /* efi_recover_from_page_fault()*/ #include /* store_idt(), ... */ +#include /* fixup_vdso_exception() */ #define CREATE_TRACE_POINTS #include @@ -936,6 +937,9 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code, sanitize_error_code(address, &error_code); + if (fixup_vdso_exception(regs, X86_TRAP_PF, error_code, address)) + return; + if (likely(show_unhandled_signals)) show_signal_msg(regs, error_code, address, tsk); @@ -1055,6 +1059,9 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address, sanitize_error_code(address, &error_code); + if (fixup_vdso_exception(regs, X86_TRAP_PF, error_code, address)) + return; + set_signal_archinfo(address, error_code); #ifdef CONFIG_MEMORY_FAILURE From patchwork Sun Mar 17 21:14:52 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 10856635 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 5A9E01669 for ; Sun, 17 Mar 2019 21:19:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3F82528514 for ; Sun, 17 Mar 2019 21:19:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 303D728F8F; Sun, 17 Mar 2019 21:19:21 +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 B377B28514 for ; Sun, 17 Mar 2019 21:19:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727469AbfCQVTU (ORCPT ); Sun, 17 Mar 2019 17:19:20 -0400 Received: from mga07.intel.com ([134.134.136.100]:4194 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727054AbfCQVTU (ORCPT ); Sun, 17 Mar 2019 17:19:20 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Mar 2019 14:19:19 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,491,1544515200"; d="scan'208";a="142817320" Received: from vanderss-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.254.193]) by orsmga002.jf.intel.com with ESMTP; 17 Mar 2019 14:19:10 -0700 From: Jarkko Sakkinen To: x86@kernel.org, linux-sgx@vger.kernel.org Cc: akpm@linux-foundation.org, dave.hansen@intel.com, sean.j.christopherson@intel.com, nhorman@redhat.com, npmccallum@redhat.com, serge.ayoun@intel.com, shay.katz-zamir@intel.com, haitao.huang@intel.com, andriy.shevchenko@linux.intel.com, tglx@linutronix.de, kai.svahn@intel.com, bp@alien8.de, josh@joshtriplett.org, luto@kernel.org, kai.huang@intel.com, rientjes@google.com, Andy Lutomirski , Jarkko Sakkinen , Dave Hansen Subject: [PATCH v19 23/27] x86/traps: Attempt to fixup exceptions in vDSO before signaling Date: Sun, 17 Mar 2019 23:14:52 +0200 Message-Id: <20190317211456.13927-24-jarkko.sakkinen@linux.intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> References: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> MIME-Version: 1.0 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 From: Sean Christopherson vDSO functions can now leverage an exception fixup mechanism similar to kernel exception fixup. For vDSO exception fixup, the initial user is Intel's Software Guard Extensions (SGX), which will wrap the low-level transitions to/from the enclave, i.e. EENTER and ERESUME instructions, in a vDSO function and leverage fixup to intercept exceptions that would otherwise generate a signal. This allows the vDSO wrapper to return the fault information directly to its caller, obviating the need for SGX applications and libraries to juggle signal handlers. Attempt to fixup vDSO exceptions immediately prior to populating and sending signal information. Except for the delivery mechanism, an exception in a vDSO function should be treated like any other exception in userspace, e.g. any fault that is successfully handled by the kernel should not be directly visible to userspace. Although it's debatable whether or not all exceptions are of interest to enclaves, defer to the vDSO fixup to decide whether to do fixup or generate a signal. Future users of vDSO fixup, if there ever are any, will undoubtedly have different requirements than SGX enclaves, e.g. the fixup vs. signal logic can be made function specific if/when necessary. Suggested-by: Andy Lutomirski Cc: Andy Lutomirski Cc: Jarkko Sakkinen Cc: Dave Hansen Cc: Josh Triplett Signed-off-by: Sean Christopherson --- arch/x86/kernel/traps.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index d26f9e9c3d83..02eda456c119 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -61,6 +61,7 @@ #include #include #include +#include #ifdef CONFIG_X86_64 #include @@ -210,6 +211,9 @@ do_trap_no_signal(struct task_struct *tsk, int trapnr, const char *str, tsk->thread.error_code = error_code; tsk->thread.trap_nr = trapnr; die(str, regs, error_code); + } else { + if (fixup_vdso_exception(regs, trapnr, error_code, 0)) + return 0; } /* @@ -561,6 +565,9 @@ do_general_protection(struct pt_regs *regs, long error_code) return; } + if (fixup_vdso_exception(regs, X86_TRAP_GP, error_code, 0)) + return; + tsk->thread.error_code = error_code; tsk->thread.trap_nr = X86_TRAP_GP; @@ -775,6 +782,10 @@ dotraplinkage void do_debug(struct pt_regs *regs, long error_code) SIGTRAP) == NOTIFY_STOP) goto exit; + if (user_mode(regs) && + fixup_vdso_exception(regs, X86_TRAP_DB, error_code, 0)) + goto exit; + /* * Let others (NMI) know that the debug stack is in use * as we may switch to the interrupt stack. @@ -855,6 +866,9 @@ static void math_error(struct pt_regs *regs, int error_code, int trapnr) if (!si_code) return; + if (fixup_vdso_exception(regs, trapnr, error_code, 0)) + return; + force_sig_fault(SIGFPE, si_code, (void __user *)uprobe_get_trap_addr(regs), task); } From patchwork Sun Mar 17 21:14:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 10856637 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 D1E0713B5 for ; Sun, 17 Mar 2019 21:19:45 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B5E492914C for ; Sun, 17 Mar 2019 21:19:45 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A63FE2916E; Sun, 17 Mar 2019 21:19:45 +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 A71392914C for ; Sun, 17 Mar 2019 21:19:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727480AbfCQVTo (ORCPT ); Sun, 17 Mar 2019 17:19:44 -0400 Received: from mga09.intel.com ([134.134.136.24]:9226 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727481AbfCQVTo (ORCPT ); Sun, 17 Mar 2019 17:19:44 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Mar 2019 14:19:42 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,491,1544515200"; d="scan'208";a="142817360" Received: from vanderss-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.254.193]) by orsmga002.jf.intel.com with ESMTP; 17 Mar 2019 14:19:34 -0700 From: Jarkko Sakkinen To: x86@kernel.org, linux-sgx@vger.kernel.org Cc: akpm@linux-foundation.org, dave.hansen@intel.com, sean.j.christopherson@intel.com, nhorman@redhat.com, npmccallum@redhat.com, serge.ayoun@intel.com, shay.katz-zamir@intel.com, haitao.huang@intel.com, andriy.shevchenko@linux.intel.com, tglx@linutronix.de, kai.svahn@intel.com, bp@alien8.de, josh@joshtriplett.org, luto@kernel.org, kai.huang@intel.com, rientjes@google.com, Jarkko Sakkinen Subject: [PATCH v19 25/27] x86/sgx: SGX documentation Date: Sun, 17 Mar 2019 23:14:54 +0200 Message-Id: <20190317211456.13927-26-jarkko.sakkinen@linux.intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> References: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> MIME-Version: 1.0 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 Documentation of the features of the Software Guard eXtensions (SGX), the basic design choices for the core and driver functionality and the UAPI. Signed-off-by: Jarkko Sakkinen Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson --- Documentation/index.rst | 1 + Documentation/x86/index.rst | 10 ++ Documentation/x86/sgx.rst | 234 ++++++++++++++++++++++++++++++++++++ 3 files changed, 245 insertions(+) create mode 100644 Documentation/x86/index.rst create mode 100644 Documentation/x86/sgx.rst diff --git a/Documentation/index.rst b/Documentation/index.rst index 80a421cb935e..3511400dc092 100644 --- a/Documentation/index.rst +++ b/Documentation/index.rst @@ -102,6 +102,7 @@ implementation. :maxdepth: 2 sh/index + x86/index Filesystem Documentation ------------------------ diff --git a/Documentation/x86/index.rst b/Documentation/x86/index.rst new file mode 100644 index 000000000000..f137d7109052 --- /dev/null +++ b/Documentation/x86/index.rst @@ -0,0 +1,10 @@ +.. SPDX-License-Identifier: GPL-2.0 + +====================== +x86 Architecture Guide +====================== + +.. toctree:: + :maxdepth: 2 + + sgx diff --git a/Documentation/x86/sgx.rst b/Documentation/x86/sgx.rst new file mode 100644 index 000000000000..72c3ea2e8889 --- /dev/null +++ b/Documentation/x86/sgx.rst @@ -0,0 +1,234 @@ +.. SPDX-License-Identifier: GPL-2.0 + +================================== +Intel(R) Software Guard eXtensions +================================== + +Introduction +============ + +Intel(R) SGX is a set of CPU instructions that can be used by applications to +set aside private regions of code and data. The code outside the enclave is +disallowed to access the memory inside the enclave by the CPU access control. +In a way you can think that SGX provides an inverted sandbox. It protects the +application from a malicious host. + +You can tell if your CPU supports SGX by looking into ``/proc/cpuinfo``: + + ``cat /proc/cpuinfo | grep sgx`` + +Overview of SGX +=============== + +SGX has a set of data structures to maintain information about the enclaves and +their security properties. BIOS reserves a fixed size region of physical memory +for these structures by setting Processor Reserved Memory Range Registers +(PRMRR). + +This memory range is protected from outside access by the CPU and all the data +coming in and out of the CPU package is encrypted by a key that is generated for +each boot cycle. + +Enclaves execute in ring 3 in a special enclave submode using pages from the +reserved memory range. A fixed logical address range for the enclave is reserved +by ENCLS(ECREATE), a leaf instruction used to create enclaves. It is referred to +in the documentation commonly as the *ELRANGE*. + +Every memory access to the ELRANGE is asserted by the CPU. If the CPU is not +executing in the enclave mode inside the enclave, #GP is raised. On the other +hand, enclave code can make memory accesses both inside and outside of the +ELRANGE. + +An enclave can only execute code inside the ELRANGE. Instructions that may cause +VMEXIT, IO instructions and instructions that require a privilege change are +prohibited inside the enclave. Interrupts and exceptions always cause an enclave +to exit and jump to an address outside the enclave given when the enclave is +entered by using the leaf instruction ENCLS(EENTER). + +Protected memory +---------------- + +Enclave Page Cache (EPC) + Physical pages used with enclaves that are protected by the CPU from + unauthorized access. + +Enclave Page Cache Map (EPCM) + A database that describes the properties and state of the pages e.g. their + permissions or which enclave they belong to. + +Memory Encryption Engine (MEE) integrity tree + Autonomously updated integrity tree. The root of the tree located in on-die + SRAM. + +EPC data types +-------------- + +SGX Enclave Control Structure (SECS) + Describes the global properties of an enclave. Will not be mapped to the + ELRANGE. + +Regular (REG) + These pages contain code and data. + +Thread Control Structure (TCS) + The pages that define the entry points inside an enclave. An enclave can + only be entered through these entry points and each can host a single + hardware thread at a time. + +Version Array (VA) + The pages contain 64-bit version numbers for pages that have been swapped + outside the enclave. Each page has the capacity of 512 version numbers. + +Launch control +-------------- + +To launch an enclave, two structures must be provided for ENCLS(EINIT): + +1. **SIGSTRUCT:** signed measurement of the enclave binary. +2. **EINITTOKEN:** a cryptographic token CMAC-signed with a AES256-key called + *launch key*, which is regenerated for each boot cycle. + +The CPU holds a SHA256 hash of a 3072-bit RSA public key inside +IA32_SGXLEPUBKEYHASHn MSRs. Enclaves with a SIGSTRUCT that is signed with this +key do not require a valid EINITTOKEN and can be authorized with special +privileges. One of those privileges is ability to acquire the launch key with +ENCLS(EGETKEY). + +**IA32_FEATURE_CONTROL[SGX_LE_WR]** is used by the BIOS configure whether +IA32_SGXLEPUBKEYHASH MSRs are read-only or read-write before locking the feature +control register and handing over control to the operating system. + +Enclave construction +-------------------- + +The construction is started by filling out the SECS that contains enclave +address range, privileged attributes and measurement of TCS and REG pages (pages +that will be mapped to the address range) among the other things. This structure +is passed to the ENCLS(ECREATE) together with a physical address of a page in +EPC that will hold the SECS. + +The pages are added with ENCLS(EADD) and measured with ENCLS(EEXTEND), i.e. +SHA256 hash MRENCLAVE residing in the SECS is extended with the page data. + +After all of the pages have been added, the enclave is initialized with +ENCLS(EINIT). It will check that the SIGSTRUCT is signed with the contained +public key. If the given EINITTOKEN has the valid bit set, the CPU checks that +the token is valid (CMAC'd with the launch key). If the token is not valid, +the CPU will check whether the enclave is signed with a key matching to the +IA32_SGXLEPUBKEYHASHn MSRs. + +Swapping pages +-------------- + +Enclave pages can be swapped out with the *ENCLS(EWB)* instruction to the +unprotected memory. In addition to the EPC page, ENCLS(EWB) takes in a VA page +and address for PCMD structure (Page Crypto MetaData) as input. The VA page will +seal a version number for the page. PCMD is 128-byte structure that contains +tracking information for the page, most importantly its MAC. With these +structures the enclave is sealed and rollback protected while it resides in the +unprotected memory. + +Before the page can be swapped out it must not have any active TLB references. +The *ENCLS(EBLOCK)* instruction moves a page to the *blocked* state, which means +that no new TLB entries can be created to it by the hardware threads. + +After this a shootdown sequence is started with the *ENCLS(ETRACK)* instruction, +which sets an increased counter value to the entering hardware threads. +ENCLS(EWB) will return *SGX_NOT_TRACKED* error while there are still threads +with the earlier counter value because that means that there might be hardware +threads inside the enclave with TLB entries to pages that are to be swapped. + +Kernel internals +================ + +Requirements +------------ + +Because SGX has an ever evolving and expanding feature set, it's possible for +a BIOS or VMM to configure a system in such a way that not all CPUs are equal, +e.g. where Launch Control is only enabled on a subset of CPUs. Linux does +*not* support such a heterogeneous system configuration, nor does it even +attempt to play nice in the face of a misconfigured system. With the exception +of Launch Control's hash MSRs, which can vary per CPU, Linux assumes that all +CPUs have a configuration that is identical to the boot CPU. + + +Roles and responsibilities +-------------------------- + +SGX introduces system resources, e.g. EPC memory, that must be accessible to +multiple entities, e.g. the native kernel driver (to expose SGX to userspace) +and KVM (to expose SGX to VMs), ideally without introducing any dependencies +between each SGX entity. To that end, the kernel owns and manages the shared +system resources, i.e. the EPC and Launch Control MSRs, and defines functions +that provide appropriate access to the shared resources. SGX support for +user space and VMs is left to the SGX platform driver and KVM respectively. + +Launching enclaves +------------------ + +The current kernel implementation supports only writable MSRs. The launch is +performed by setting the MSRs to the hash of the public key modulus of the +enclave signer and a token with the valid bit set to zero. + +EPC management +-------------- + +Due to the unique requirements for swapping EPC pages, and because EPC pages +(currently) do not have associated page structures, management of the EPC is +not handled by the standard Linux swapper. SGX directly handles swapping +of EPC pages, including a kthread to initiate reclaim and a rudimentary LRU +mechanism. The consumers of EPC pages, e.g. the SGX driver, are required to +implement function callbacks that can be invoked by the kernel to age, +swap, and/or forcefully reclaim a target EPC page. In effect, the kernel +controls what happens and when, while the consumers (driver, KVM, etc..) do +the actual work. + +Exception handling +------------------ + +The PF_SGX bit is set if and only if the #PF is detected by the SGX Enclave Page +Cache Map (EPCM). The EPCM is a hardware-managed table that enforces accesses to +an enclave's EPC pages in addition to the software-managed kernel page tables, +i.e. the effective permissions for an EPC page are a logical AND of the kernel's +page tables and the corresponding EPCM entry. + +The EPCM is consulted only after an access walks the kernel's page tables, i.e.: + +1. the access was allowed by the kernel +2. the kernel's tables have become less restrictive than the EPCM +3. the kernel cannot fixup the cause of the fault + +Notably, (2) implies that either the kernel has botched the EPC mappings or the +EPCM has been invalidated (see below). Regardless of why the fault occurred, +userspace needs to be alerted so that it can take appropriate action, e.g. +restart the enclave. This is reinforced by (3) as the kernel doesn't really +have any other reasonable option, i.e. signalling SIGSEGV is actually the least +severe action possible. + +Although the primary purpose of the EPCM is to prevent a malicious or +compromised kernel from attacking an enclave, e.g. by modifying the enclave's +page tables, do not WARN on a #PF with PF_SGX set. The SGX architecture +effectively allows the CPU to invalidate all EPCM entries at will and requires +that software be prepared to handle an EPCM fault at any time. The architecture +defines this behavior because the EPCM is encrypted with an ephemeral key that +isn't exposed to software. As such, the EPCM entries cannot be preserved across +transitions that result in a new key being used, e.g. CPU power down as part of +an S3 transition or when a VM is live migrated to a new physical system. + +SGX UAPI +======== + +.. kernel-doc:: drivers/platform/x86/intel_sgx/sgx_ioctl.c + :functions: sgx_ioc_enclave_create + sgx_ioc_enclave_add_page + sgx_ioc_enclave_init + +.. kernel-doc:: arch/x86/include/uapi/asm/sgx.h + +References +========== + +* A Memory Encryption Engine Suitable for General Purpose Processors + +* System Programming Manual: 39.1.4 IntelĀ® SGX Launch Control Configuration From patchwork Sun Mar 17 21:14:55 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 10856639 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 CAD3F186D for ; Sun, 17 Mar 2019 21:19:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AD6DA2914C for ; Sun, 17 Mar 2019 21:19:57 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9E1702916E; Sun, 17 Mar 2019 21:19:57 +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 9B4942914C for ; Sun, 17 Mar 2019 21:19:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727481AbfCQVTz (ORCPT ); Sun, 17 Mar 2019 17:19:55 -0400 Received: from mga07.intel.com ([134.134.136.100]:4212 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727426AbfCQVTz (ORCPT ); Sun, 17 Mar 2019 17:19:55 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Mar 2019 14:19:54 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,491,1544515200"; d="scan'208";a="142817374" Received: from vanderss-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.254.193]) by orsmga002.jf.intel.com with ESMTP; 17 Mar 2019 14:19:44 -0700 From: Jarkko Sakkinen To: x86@kernel.org, linux-sgx@vger.kernel.org Cc: akpm@linux-foundation.org, dave.hansen@intel.com, sean.j.christopherson@intel.com, nhorman@redhat.com, npmccallum@redhat.com, serge.ayoun@intel.com, shay.katz-zamir@intel.com, haitao.huang@intel.com, andriy.shevchenko@linux.intel.com, tglx@linutronix.de, kai.svahn@intel.com, bp@alien8.de, josh@joshtriplett.org, luto@kernel.org, kai.huang@intel.com, rientjes@google.com, Jarkko Sakkinen Subject: [PATCH v19 26/27] selftests/x86: Add a selftest for SGX Date: Sun, 17 Mar 2019 23:14:55 +0200 Message-Id: <20190317211456.13927-27-jarkko.sakkinen@linux.intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> References: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> MIME-Version: 1.0 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 Add a selftest for SGX. It is a trivial test where a simple enclave copies one 64-bit word of memory between two memory locations given to the enclave as arguments. Signed-off-by: Jarkko Sakkinen --- tools/testing/selftests/x86/Makefile | 10 + tools/testing/selftests/x86/sgx/Makefile | 48 ++ tools/testing/selftests/x86/sgx/defines.h | 39 ++ tools/testing/selftests/x86/sgx/encl.c | 20 + tools/testing/selftests/x86/sgx/encl.lds | 33 ++ .../selftests/x86/sgx/encl_bootstrap.S | 94 ++++ tools/testing/selftests/x86/sgx/encl_piggy.S | 18 + tools/testing/selftests/x86/sgx/encl_piggy.h | 14 + tools/testing/selftests/x86/sgx/main.c | 280 ++++++++++ tools/testing/selftests/x86/sgx/sgx_call.S | 15 + tools/testing/selftests/x86/sgx/sgxsign.c | 508 ++++++++++++++++++ .../testing/selftests/x86/sgx/signing_key.pem | 39 ++ 12 files changed, 1118 insertions(+) create mode 100644 tools/testing/selftests/x86/sgx/Makefile create mode 100644 tools/testing/selftests/x86/sgx/defines.h create mode 100644 tools/testing/selftests/x86/sgx/encl.c create mode 100644 tools/testing/selftests/x86/sgx/encl.lds create mode 100644 tools/testing/selftests/x86/sgx/encl_bootstrap.S create mode 100644 tools/testing/selftests/x86/sgx/encl_piggy.S create mode 100644 tools/testing/selftests/x86/sgx/encl_piggy.h create mode 100644 tools/testing/selftests/x86/sgx/main.c create mode 100644 tools/testing/selftests/x86/sgx/sgx_call.S create mode 100644 tools/testing/selftests/x86/sgx/sgxsign.c create mode 100644 tools/testing/selftests/x86/sgx/signing_key.pem diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile index 186520198de7..4fc9a42f56ea 100644 --- a/tools/testing/selftests/x86/Makefile +++ b/tools/testing/selftests/x86/Makefile @@ -1,4 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 + +SUBDIRS_64 := sgx + all: include ../lib.mk @@ -67,6 +70,13 @@ 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 $@; \ + done + EXTRA_CLEAN := $(BINARIES_32) $(BINARIES_64) $(BINARIES_32): $(OUTPUT)/%_32: %.c diff --git a/tools/testing/selftests/x86/sgx/Makefile b/tools/testing/selftests/x86/sgx/Makefile new file mode 100644 index 000000000000..1fd6f2708e81 --- /dev/null +++ b/tools/testing/selftests/x86/sgx/Makefile @@ -0,0 +1,48 @@ +top_srcdir = ../../../../.. + +include ../../lib.mk + +HOST_CFLAGS := -Wall -Werror -g $(INCLUDES) -fPIC +ENCL_CFLAGS := -Wall -Werror -static -nostdlib -nostartfiles -fPIC \ + -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 + $(CC) $(HOST_CFLAGS) -o $@ $^ + +$(OUTPUT)/main.o: main.c + $(CC) $(HOST_CFLAGS) -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 + 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.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)/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 diff --git a/tools/testing/selftests/x86/sgx/defines.h b/tools/testing/selftests/x86/sgx/defines.h new file mode 100644 index 000000000000..3ff73a9d9b93 --- /dev/null +++ b/tools/testing/selftests/x86/sgx/defines.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright(c) 2016-19 Intel Corporation. + */ + +#ifndef TYPES_H +#define TYPES_H + +#include + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +#define __aligned(x) __attribute__((__aligned__(x))) +#define __packed __attribute__((packed)) + +/* Derived from asm-generic/bitsperlong.h. */ +#if __x86_64__ +#define BITS_PER_LONG 64 +#else +#define BITS_PER_LONG 32 +#endif +#define BITS_PER_LONG_LONG 64 + +/* Taken from linux/bits.h. */ +#define BIT(nr) (1UL << (nr)) +#define BIT_ULL(nr) (1ULL << (nr)) +#define GENMASK(h, l) \ + (((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h)))) +#define GENMASK_ULL(h, l) \ + (((~0ULL) - (1ULL << (l)) + 1) & \ + (~0ULL >> (BITS_PER_LONG_LONG - 1 - (h)))) + +#include "../../../../../arch/x86/kernel/cpu/sgx/arch.h" +#include "../../../../../arch/x86/include/uapi/asm/sgx.h" + +#endif /* TYPES_H */ diff --git a/tools/testing/selftests/x86/sgx/encl.c b/tools/testing/selftests/x86/sgx/encl.c new file mode 100644 index 000000000000..ede915399742 --- /dev/null +++ b/tools/testing/selftests/x86/sgx/encl.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// Copyright(c) 2016-18 Intel Corporation. + +#include +#include "defines.h" + +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; +} + +void encl_body(void *rdi, void *rsi) +{ + memcpy(rsi, rdi, 8); +} diff --git a/tools/testing/selftests/x86/sgx/encl.lds b/tools/testing/selftests/x86/sgx/encl.lds new file mode 100644 index 000000000000..2ee01ac3ec79 --- /dev/null +++ b/tools/testing/selftests/x86/sgx/encl.lds @@ -0,0 +1,33 @@ +OUTPUT_FORMAT(elf64-x86-64) + +SECTIONS +{ + . = 0; + .tcs : { + *(.tcs*) + } + + . = ALIGN(4096); + .text : { + *(.text*) + *(.rodata*) + } + + . = ALIGN(4096); + .data : { + *(.data*) + } + + /DISCARD/ : { + *(.data*) + *(.comment*) + *(.note*) + *(.debug*) + *(.eh_frame*) + } +} + +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") diff --git a/tools/testing/selftests/x86/sgx/encl_bootstrap.S b/tools/testing/selftests/x86/sgx/encl_bootstrap.S new file mode 100644 index 000000000000..d07f970ccdf9 --- /dev/null +++ b/tools/testing/selftests/x86/sgx/encl_bootstrap.S @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* + * Copyright(c) 2016-18 Intel Corporation. + */ + + .macro ENCLU + .byte 0x0f, 0x01, 0xd7 + .endm + + .section ".tcs", "a" + .balign 4096 + + .fill 1, 8, 0 # STATE (set by CPU) + .fill 1, 8, 0 # FLAGS + .quad encl_ssa # OSSA + .fill 1, 4, 0 # CSSA (set by CPU) + .fill 1, 4, 1 # NSSA + .quad encl_entry # OENTRY + .fill 1, 8, 0 # AEP (set by EENTER and ERESUME) + .fill 1, 8, 0 # OFSBASE + .fill 1, 8, 0 # OGSBASE + .fill 1, 4, 0xFFFFFFFF # FSLIMIT + .fill 1, 4, 0xFFFFFFFF # GSLIMIT + .fill 4024, 1, 0 # Reserved + + .text + +encl_entry: + # RBX contains the base address for TCS, which is also the first address + # inside the enclave. By adding the value of le_stack_end to it, we get + # the absolute address for the stack. + lea (encl_stack)(%rbx), %rax + xchg %rsp, %rax + push %rax + + push %rcx # push the address after EENTER + push %rbx # push the enclave base address + + call encl_body + + pop %rbx # pop the enclave base address + + # Restore XSAVE registers to a synthetic state. + mov $0xFFFFFFFF, %rax + mov $0xFFFFFFFF, %rdx + lea (xsave_area)(%rbx), %rdi + fxrstor (%rdi) + + # Clear GPRs. + xor %rcx, %rcx + xor %rdx, %rdx + xor %rdi, %rdi + xor %rsi, %rsi + xor %r8, %r8 + xor %r9, %r9 + xor %r10, %r10 + xor %r11, %r11 + xor %r12, %r12 + xor %r13, %r13 + xor %r14, %r14 + xor %r15, %r15 + + # 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 + + # Restore the caller stack. + pop %rax + mov %rax, %rsp + + # EEXIT + mov $4, %rax + enclu + + .section ".data", "aw" + +encl_ssa: + .space 4096 + +xsave_area: + .fill 1, 4, 0x037F # FCW + .fill 5, 4, 0 + .fill 1, 4, 0x1F80 # MXCSR + .fill 1, 4, 0xFFFF # MXCSR_MASK + .fill 123, 4, 0 + .fill 1, 4, 0x80000000 # XCOMP_BV[63] = 1, compaction mode + .fill 12, 4, 0 + + .balign 4096 + .space 8192 +encl_stack: diff --git a/tools/testing/selftests/x86/sgx/encl_piggy.S b/tools/testing/selftests/x86/sgx/encl_piggy.S new file mode 100644 index 000000000000..542001658afb --- /dev/null +++ b/tools/testing/selftests/x86/sgx/encl_piggy.S @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* + * Copyright(c) 2016-18 Intel Corporation. + */ + + .section ".rodata", "a" + +encl_bin: + .globl encl_bin + .incbin "encl.bin" +encl_bin_end: + .globl encl_bin_end + +encl_ss: + .globl encl_ss + .incbin "encl.ss" +encl_ss_end: + .globl encl_ss_end diff --git a/tools/testing/selftests/x86/sgx/encl_piggy.h b/tools/testing/selftests/x86/sgx/encl_piggy.h new file mode 100644 index 000000000000..ee8224f8cc8d --- /dev/null +++ b/tools/testing/selftests/x86/sgx/encl_piggy.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* + * Copyright(c) 2016-18 Intel Corporation. + */ + +#ifndef ENCL_PIGGY_H +#define ENCL_PIGGY_H + +extern unsigned char encl_bin[]; +extern unsigned char encl_bin_end[]; +extern unsigned char encl_ss[]; +extern unsigned char encl_ss_end[]; + +#endif /* ENCL_PIGGY_H */ diff --git a/tools/testing/selftests/x86/sgx/main.c b/tools/testing/selftests/x86/sgx/main.c new file mode 100644 index 000000000000..61cf62fb300a --- /dev/null +++ b/tools/testing/selftests/x86/sgx/main.c @@ -0,0 +1,280 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// Copyright(c) 2016-18 Intel Corporation. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "encl_piggy.h" +#include "defines.h" +#include "../../../../../arch/x86/kernel/cpu/sgx/arch.h" +#include "../../../../../arch/x86/include/uapi/asm/sgx.h" + +static const uint64_t MAGIC = 0x1122334455667788ULL; + +struct vdso_symtab { + Elf64_Sym *elf_symtab; + const char *elf_symstrtab; + Elf64_Word *elf_hashtab; +}; + +static void *vdso_get_base_addr(char *envp[]) +{ + Elf64_auxv_t *auxv; + int i; + + for (i = 0; envp[i]; i++); + auxv = (Elf64_auxv_t *)&envp[i + 1]; + + for (i = 0; auxv[i].a_type != AT_NULL; i++) { + if (auxv[i].a_type == AT_SYSINFO_EHDR) + return (void *)auxv[i].a_un.a_val; + } + + return NULL; +} + +static Elf64_Dyn *vdso_get_dyntab(void *addr) +{ + Elf64_Ehdr *ehdr = addr; + Elf64_Phdr *phdrtab = addr + ehdr->e_phoff; + int i; + + for (i = 0; i < ehdr->e_phnum; i++) + if (phdrtab[i].p_type == PT_DYNAMIC) + return addr + phdrtab[i].p_offset; + + return NULL; +} + +static void *vdso_get_dyn(void *addr, Elf64_Dyn *dyntab, Elf64_Sxword tag) +{ + int i; + + for (i = 0; dyntab[i].d_tag != DT_NULL; i++) + if (dyntab[i].d_tag == tag) + return addr + dyntab[i].d_un.d_ptr; + + return NULL; +} + +static bool vdso_get_symtab(void *addr, struct vdso_symtab *symtab) +{ + Elf64_Dyn *dyntab = vdso_get_dyntab(addr); + + symtab->elf_symtab = vdso_get_dyn(addr, dyntab, DT_SYMTAB); + if (!symtab->elf_symtab) + return false; + + symtab->elf_symstrtab = vdso_get_dyn(addr, dyntab, DT_STRTAB); + if (!symtab->elf_symstrtab) + return false; + + symtab->elf_hashtab = vdso_get_dyn(addr, dyntab, DT_HASH); + if (!symtab->elf_hashtab) + return false; + + return true; +} + +static unsigned long elf_sym_hash(const char *name) +{ + unsigned long h = 0, high; + + while (*name) { + h = (h << 4) + *name++; + high = h & 0xf0000000; + + if (high) + h ^= high >> 24; + + h &= ~high; + } + + return h; +} + +static Elf64_Sym *vdso_symtab_get(struct vdso_symtab *symtab, const char *name) +{ + Elf64_Word bucketnum = symtab->elf_hashtab[0]; + Elf64_Word *buckettab = &symtab->elf_hashtab[2]; + Elf64_Word *chaintab = &symtab->elf_hashtab[2 + bucketnum]; + Elf64_Sym *sym; + Elf64_Word i; + + for (i = buckettab[elf_sym_hash(name) % bucketnum]; i != STN_UNDEF; + i = chaintab[i]) { + sym = &symtab->elf_symtab[i]; + if (!strcmp(name, &symtab->elf_symstrtab[sym->st_name])) + return sym; + } + + return NULL; +} + +static bool encl_create(int dev_fd, unsigned long bin_size, + struct sgx_secs *secs) +{ + struct sgx_enclave_create ioc; + void *base; + int rc; + + memset(secs, 0, sizeof(*secs)); + secs->ssa_frame_size = 1; + secs->attributes = SGX_ATTR_MODE64BIT; + secs->xfrm = 3; + + for (secs->size = 4096; secs->size < bin_size; ) + secs->size <<= 1; + + base = mmap(NULL, secs->size, PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_SHARED, dev_fd, 0); + if (base == MAP_FAILED) { + perror("mmap"); + return false; + } + + secs->base = (uint64_t)base; + + ioc.src = (unsigned long)secs; + rc = ioctl(dev_fd, SGX_IOC_ENCLAVE_CREATE, &ioc); + if (rc) { + fprintf(stderr, "ECREATE failed rc=%d.\n", rc); + munmap(base, secs->size); + return false; + } + + return true; +} + +static bool encl_add_page(int dev_fd, unsigned long addr, void *data, + uint64_t flags) +{ + struct sgx_enclave_add_page ioc; + struct sgx_secinfo secinfo; + int rc; + + memset(&secinfo, 0, sizeof(secinfo)); + secinfo.flags = flags; + + ioc.secinfo = (unsigned long)&secinfo; + ioc.mrmask = 0xFFFF; + ioc.addr = addr; + ioc.src = (uint64_t)data; + + rc = ioctl(dev_fd, SGX_IOC_ENCLAVE_ADD_PAGE, &ioc); + if (rc) { + fprintf(stderr, "EADD failed rc=%d.\n", rc); + return false; + } + + return true; +} + +static bool encl_load(struct sgx_secs *secs, unsigned long bin_size) +{ + struct sgx_enclave_init ioc; + uint64_t offset; + uint64_t flags; + int dev_fd; + int rc; + + dev_fd = open("/dev/sgx", O_RDWR); + if (dev_fd < 0) { + fprintf(stderr, "Unable to open /dev/sgx\n"); + return false; + } + + if (!encl_create(dev_fd, bin_size, secs)) + goto out_dev_fd; + + for (offset = 0; offset < bin_size; offset += 0x1000) { + if (!offset) + flags = SGX_SECINFO_TCS; + else + flags = SGX_SECINFO_REG | SGX_SECINFO_R | + SGX_SECINFO_W | SGX_SECINFO_X; + + if (!encl_add_page(dev_fd, secs->base + offset, + encl_bin + offset, flags)) + goto out_map; + } + + ioc.addr = secs->base; + ioc.sigstruct = (uint64_t)&encl_ss; + rc = ioctl(dev_fd, SGX_IOC_ENCLAVE_INIT, &ioc); + if (rc) { + printf("EINIT failed rc=%d\n", rc); + goto out_map; + } + + close(dev_fd); + return true; +out_map: + munmap((void *)secs->base, secs->size); +out_dev_fd: + close(dev_fd); + return false; +} + +void sgx_call(void *rdi, void *rsi, void *tcs, + struct sgx_enclave_exception *exception, + void *eenter); + +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); + + if (!vdso_get_symtab(addr, &symtab)) + exit(1); + + eenter_sym = vdso_symtab_get(&symtab, "__vdso_sgx_enter_enclave"); + if (!eenter_sym) + exit(1); + eenter = addr + eenter_sym->st_value; + + printf("Binary size %lu (0x%lx), SIGSTRUCT size %lu\n", bin_size, + bin_size, ss_size); + if (ss_size != sizeof(struct sgx_sigstruct)) { + fprintf(stderr, "The size of SIGSTRUCT should be %lu\n", + sizeof(struct sgx_sigstruct)); + exit(1); + } + + printf("Loading the enclave.\n"); + 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); +} diff --git a/tools/testing/selftests/x86/sgx/sgx_call.S b/tools/testing/selftests/x86/sgx/sgx_call.S new file mode 100644 index 000000000000..14bd0a044199 --- /dev/null +++ b/tools/testing/selftests/x86/sgx/sgx_call.S @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/** +* Copyright(c) 2016-18 Intel Corporation. +*/ + + .text + + .global sgx_call +sgx_call: + push %rbx + mov $0x02, %rax + mov %rdx, %rbx + call *%r8 + pop %rbx + ret diff --git a/tools/testing/selftests/x86/sgx/sgxsign.c b/tools/testing/selftests/x86/sgx/sgxsign.c new file mode 100644 index 000000000000..0b89823fc703 --- /dev/null +++ b/tools/testing/selftests/x86/sgx/sgxsign.c @@ -0,0 +1,508 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// Copyright(c) 2016-18 Intel Corporation. + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "defines.h" + +struct sgx_sigstruct_payload { + struct sgx_sigstruct_header header; + struct sgx_sigstruct_body body; +}; + +static const char *sign_key_pass; + +static bool check_crypto_errors(void) +{ + int err; + bool had_errors = false; + const char *filename; + int line; + char str[256]; + + for ( ; ; ) { + if (ERR_peek_error() == 0) + break; + + had_errors = true; + err = ERR_get_error_line(&filename, &line); + ERR_error_string_n(err, str, sizeof(str)); + fprintf(stderr, "crypto: %s: %s:%d\n", str, filename, line); + } + + return had_errors; +} + +static void exit_usage(const char *program) +{ + fprintf(stderr, + "Usage: %s/sign-le \n", program); + exit(1); +} + +static int pem_passwd_cb(char *buf, int size, int rwflag, void *u) +{ + if (!sign_key_pass) + return -1; + + strncpy(buf, sign_key_pass, size); + /* no retry */ + sign_key_pass = NULL; + + return strlen(buf) >= size ? size - 1 : strlen(buf); +} + +static inline const BIGNUM *get_modulus(RSA *key) +{ +#if OPENSSL_VERSION_NUMBER < 0x10100000L + return key->n; +#else + const BIGNUM *n; + + RSA_get0_key(key, &n, NULL, NULL); + return n; +#endif +} + +static RSA *load_sign_key(const char *path) +{ + FILE *f; + RSA *key; + + f = fopen(path, "rb"); + if (!f) { + fprintf(stderr, "Unable to open %s\n", path); + return NULL; + } + key = RSA_new(); + if (!PEM_read_RSAPrivateKey(f, &key, pem_passwd_cb, NULL)) + return NULL; + fclose(f); + + if (BN_num_bytes(get_modulus(key)) != SGX_MODULUS_SIZE) { + fprintf(stderr, "Invalid key size %d\n", + BN_num_bytes(get_modulus(key))); + RSA_free(key); + return NULL; + } + + return key; +} + +static void reverse_bytes(void *data, int length) +{ + int i = 0; + int j = length - 1; + uint8_t temp; + uint8_t *ptr = data; + + while (i < j) { + temp = ptr[i]; + ptr[i] = ptr[j]; + ptr[j] = temp; + i++; + j--; + } +} + +enum mrtags { + MRECREATE = 0x0045544145524345, + MREADD = 0x0000000044444145, + MREEXTEND = 0x00444E4554584545, +}; + +static bool mrenclave_update(EVP_MD_CTX *ctx, const void *data) +{ + if (!EVP_DigestUpdate(ctx, data, 64)) { + fprintf(stderr, "digest update failed\n"); + return false; + } + + return true; +} + +static bool mrenclave_commit(EVP_MD_CTX *ctx, uint8_t *mrenclave) +{ + unsigned int size; + + if (!EVP_DigestFinal_ex(ctx, (unsigned char *)mrenclave, &size)) { + fprintf(stderr, "digest commit failed\n"); + return false; + } + + if (size != 32) { + fprintf(stderr, "invalid digest size = %u\n", size); + return false; + } + + return true; +} + +struct mrecreate { + uint64_t tag; + uint32_t ssaframesize; + uint64_t size; + uint8_t reserved[44]; +} __attribute__((__packed__)); + + +static bool mrenclave_ecreate(EVP_MD_CTX *ctx, uint64_t blob_size) +{ + struct mrecreate mrecreate; + uint64_t encl_size; + + for (encl_size = 0x1000; encl_size < blob_size; ) + encl_size <<= 1; + + memset(&mrecreate, 0, sizeof(mrecreate)); + mrecreate.tag = MRECREATE; + mrecreate.ssaframesize = 1; + mrecreate.size = encl_size; + + if (!EVP_DigestInit_ex(ctx, EVP_sha256(), NULL)) + return false; + + return mrenclave_update(ctx, &mrecreate); +} + +struct mreadd { + uint64_t tag; + uint64_t offset; + uint64_t flags; /* SECINFO flags */ + uint8_t reserved[40]; +} __attribute__((__packed__)); + +static bool mrenclave_eadd(EVP_MD_CTX *ctx, uint64_t offset, uint64_t flags) +{ + struct mreadd mreadd; + + memset(&mreadd, 0, sizeof(mreadd)); + mreadd.tag = MREADD; + mreadd.offset = offset; + mreadd.flags = flags; + + return mrenclave_update(ctx, &mreadd); +} + +struct mreextend { + uint64_t tag; + uint64_t offset; + uint8_t reserved[48]; +} __attribute__((__packed__)); + +static bool mrenclave_eextend(EVP_MD_CTX *ctx, uint64_t offset, uint8_t *data) +{ + struct mreextend mreextend; + int i; + + for (i = 0; i < 0x1000; i += 0x100) { + memset(&mreextend, 0, sizeof(mreextend)); + mreextend.tag = MREEXTEND; + mreextend.offset = offset + i; + + if (!mrenclave_update(ctx, &mreextend)) + return false; + + if (!mrenclave_update(ctx, &data[i + 0x00])) + return false; + + if (!mrenclave_update(ctx, &data[i + 0x40])) + return false; + + if (!mrenclave_update(ctx, &data[i + 0x80])) + return false; + + if (!mrenclave_update(ctx, &data[i + 0xC0])) + return false; + } + + return true; +} + +/** + * measure_encl - measure enclave + * @path: path to the enclave + * @mrenclave: measurement + * + * Calculates MRENCLAVE. Assumes that the very first page is a TCS page and + * following pages are regular pages. Does not measure the contents of the + * enclave as the signing tool is used at the moment only for the launch + * enclave, which is pass-through (everything gets a token). + */ +static bool measure_encl(const char *path, uint8_t *mrenclave) +{ + FILE *file; + struct stat sb; + EVP_MD_CTX *ctx; + uint64_t flags; + uint64_t offset; + uint8_t data[0x1000]; + int rc; + + ctx = EVP_MD_CTX_create(); + if (!ctx) + return false; + + file = fopen(path, "rb"); + if (!file) { + perror("fopen"); + EVP_MD_CTX_destroy(ctx); + return false; + } + + rc = stat(path, &sb); + if (rc) { + perror("stat"); + goto out; + } + + if (!sb.st_size || sb.st_size & 0xfff) { + fprintf(stderr, "Invalid blob size %lu\n", sb.st_size); + goto out; + } + + if (!mrenclave_ecreate(ctx, sb.st_size)) + goto out; + + for (offset = 0; offset < sb.st_size; offset += 0x1000) { + if (!offset) + flags = SGX_SECINFO_TCS; + else + flags = SGX_SECINFO_REG | SGX_SECINFO_R | + SGX_SECINFO_W | SGX_SECINFO_X; + + if (!mrenclave_eadd(ctx, offset, flags)) + goto out; + + rc = fread(data, 1, 0x1000, file); + if (!rc) + break; + if (rc < 0x1000) + goto out; + + if (!mrenclave_eextend(ctx, offset, data)) + goto out; + } + + if (!mrenclave_commit(ctx, mrenclave)) + goto out; + + fclose(file); + EVP_MD_CTX_destroy(ctx); + return true; +out: + fclose(file); + EVP_MD_CTX_destroy(ctx); + return false; +} + +/** + * sign_encl - sign enclave + * @sigstruct: pointer to SIGSTRUCT + * @key: 3072-bit RSA key + * @signature: byte array for the signature + * + * Calculates EMSA-PKCSv1.5 signature for the given SIGSTRUCT. The result is + * stored in big-endian format so that it can be further passed to OpenSSL + * libcrypto functions. + */ +static bool sign_encl(const struct sgx_sigstruct *sigstruct, RSA *key, + uint8_t *signature) +{ + struct sgx_sigstruct_payload payload; + unsigned int siglen; + uint8_t digest[SHA256_DIGEST_LENGTH]; + bool ret; + + memcpy(&payload.header, &sigstruct->header, sizeof(sigstruct->header)); + memcpy(&payload.body, &sigstruct->body, sizeof(sigstruct->body)); + + SHA256((unsigned char *)&payload, sizeof(payload), digest); + + ret = RSA_sign(NID_sha256, digest, SHA256_DIGEST_LENGTH, signature, + &siglen, key); + + return ret; +} + +struct q1q2_ctx { + BN_CTX *bn_ctx; + BIGNUM *m; + BIGNUM *s; + BIGNUM *q1; + BIGNUM *qr; + BIGNUM *q2; +}; + +static void free_q1q2_ctx(struct q1q2_ctx *ctx) +{ + BN_CTX_free(ctx->bn_ctx); + BN_free(ctx->m); + BN_free(ctx->s); + BN_free(ctx->q1); + BN_free(ctx->qr); + BN_free(ctx->q2); +} + +static bool alloc_q1q2_ctx(const uint8_t *s, const uint8_t *m, + struct q1q2_ctx *ctx) +{ + ctx->bn_ctx = BN_CTX_new(); + ctx->s = BN_bin2bn(s, SGX_MODULUS_SIZE, NULL); + ctx->m = BN_bin2bn(m, SGX_MODULUS_SIZE, NULL); + ctx->q1 = BN_new(); + ctx->qr = BN_new(); + ctx->q2 = BN_new(); + + if (!ctx->bn_ctx || !ctx->s || !ctx->m || !ctx->q1 || !ctx->qr || + !ctx->q2) { + free_q1q2_ctx(ctx); + return false; + } + + return true; +} + +static bool calc_q1q2(const uint8_t *s, const uint8_t *m, uint8_t *q1, + uint8_t *q2) +{ + struct q1q2_ctx ctx; + + if (!alloc_q1q2_ctx(s, m, &ctx)) { + fprintf(stderr, "Not enough memory for Q1Q2 calculation\n"); + return false; + } + + if (!BN_mul(ctx.q1, ctx.s, ctx.s, ctx.bn_ctx)) + goto out; + + if (!BN_div(ctx.q1, ctx.qr, ctx.q1, ctx.m, ctx.bn_ctx)) + goto out; + + if (BN_num_bytes(ctx.q1) > SGX_MODULUS_SIZE) { + fprintf(stderr, "Too large Q1 %d bytes\n", + BN_num_bytes(ctx.q1)); + goto out; + } + + if (!BN_mul(ctx.q2, ctx.s, ctx.qr, ctx.bn_ctx)) + goto out; + + if (!BN_div(ctx.q2, NULL, ctx.q2, ctx.m, ctx.bn_ctx)) + goto out; + + if (BN_num_bytes(ctx.q2) > SGX_MODULUS_SIZE) { + fprintf(stderr, "Too large Q2 %d bytes\n", + BN_num_bytes(ctx.q2)); + goto out; + } + + BN_bn2bin(ctx.q1, q1); + BN_bn2bin(ctx.q2, q2); + + free_q1q2_ctx(&ctx); + return true; +out: + free_q1q2_ctx(&ctx); + return false; +} + +static bool save_sigstruct(const struct sgx_sigstruct *sigstruct, + const char *path) +{ + FILE *f = fopen(path, "wb"); + + if (!f) { + fprintf(stderr, "Unable to open %s\n", path); + return false; + } + + fwrite(sigstruct, sizeof(*sigstruct), 1, f); + fclose(f); + return true; +} + +int main(int argc, char **argv) +{ + uint64_t header1[2] = {0x000000E100000006, 0x0000000000010000}; + uint64_t header2[2] = {0x0000006000000101, 0x0000000100000060}; + struct sgx_sigstruct ss; + const char *program; + int opt; + RSA *sign_key; + + memset(&ss, 0, sizeof(ss)); + ss.header.header1[0] = header1[0]; + ss.header.header1[1] = header1[1]; + ss.header.header2[0] = header2[0]; + ss.header.header2[1] = header2[1]; + ss.exponent = 3; + +#ifndef CONFIG_EINITTOKENKEY + ss.body.attributes = SGX_ATTR_MODE64BIT; +#else + ss.body.attributes = SGX_ATTR_MODE64BIT | SGX_ATTR_EINITTOKENKEY; +#endif + ss.body.xfrm = 3, + + sign_key_pass = getenv("KBUILD_SGX_SIGN_PIN"); + program = argv[0]; + + do { + opt = getopt(argc, argv, ""); + switch (opt) { + case -1: + break; + default: + exit_usage(program); + } + } while (opt != -1); + + argc -= optind; + argv += optind; + + if (argc < 3) + exit_usage(program); + + /* sanity check only */ + if (check_crypto_errors()) + exit(1); + + sign_key = load_sign_key(argv[0]); + if (!sign_key) + goto out; + + BN_bn2bin(get_modulus(sign_key), ss.modulus); + + if (!measure_encl(argv[1], ss.body.mrenclave)) + goto out; + + if (!sign_encl(&ss, sign_key, ss.signature)) + goto out; + + if (!calc_q1q2(ss.signature, ss.modulus, ss.q1, ss.q2)) + goto out; + + /* convert to little endian */ + reverse_bytes(ss.signature, SGX_MODULUS_SIZE); + reverse_bytes(ss.modulus, SGX_MODULUS_SIZE); + reverse_bytes(ss.q1, SGX_MODULUS_SIZE); + reverse_bytes(ss.q2, SGX_MODULUS_SIZE); + + if (!save_sigstruct(&ss, argv[2])) + goto out; + exit(0); +out: + check_crypto_errors(); + exit(1); +} diff --git a/tools/testing/selftests/x86/sgx/signing_key.pem b/tools/testing/selftests/x86/sgx/signing_key.pem new file mode 100644 index 000000000000..d76f21f19187 --- /dev/null +++ b/tools/testing/selftests/x86/sgx/signing_key.pem @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG4wIBAAKCAYEApalGbq7Q+usM91CPtksu3D+b0Prc8gAFL6grM3mg85A5Bx8V +cfMXPgtrw8EYFwQxDAvzZWwl+9VfOX0ECrFRBkOHcOiG0SnADN8+FLj1UiNUQwbp +S6OzhNWuRcSbGraSOyUlVlV0yMQSvewyzGklOaXBe30AJqzIBc8QfdSxKuP8rs0Z +ga6k/Bl73osrYKByILJTUUeZqjLERsE6GebsdzbWgKn8qVqng4ZS4yMNg6LeRlH3 ++9CIPgg4jwpSLHcp7dq2qTIB9a0tGe9ayp+5FbucpB6U7ePold0EeRN6RlJGDF9k +L93v8P5ykz5G5gYZ2g0K1X2sHIWV4huxPgv5PXgdyQYbK+6olqj0d5rjYuwX57Ul +k6SroPS1U6UbdCjG5txM+BNGU0VpD0ZhrIRw0leQdnNcCO9sTJuInZrgYacSVJ7u +mtB+uCt+uzUesc+l+xPRYA+9e14lLkZp7AAmo9FvL816XDI09deehJ3i/LmHKCRN +tuqC5TprRjFwUr6dAgEDAoIBgG5w2Z8fNfycs0+LCnmHdJLVEotR6KFVWMpwHMz7 +wKJgJgS/Y6FMuilc8oKAuroCy11dTO5IGVKOP3uorVx2NgQtBPXwWeDGgAiU1A3Q +o4wXjYIEm4fCd63jyYPYZ2ckYXzDbjmOTdstYdPyzIhGGNEZK6eoqsRzMAPfYFPj +IMdCqHSIu6vJw1K7p+myHOsVoWshjODaZnF3LYSA0WaZ8vokjwBxUxuRxQJZjJds +s60XPtmL+qfgWtQFewoG4XL6GuD8FcXccynRRtzrLtFNPIl9BQfWfjBBhTC1/Te1 +0Z6XbZvpdUTD9OfLB7SbR2OUFNpKQgriO0iYVdbW3cr7uu38Zwp4W1TX73DPjoi6 +KNooP6SGWd4mRJW2+dUmSYS4QNG8eVVZswKcploEIXlAKRsOe4kzJJ1iETugIe85 +uX8nd1WYEp65xwoRUg8hqng0MeyveVbXqNKuJG6tzNDt9kgFYo+hmC/oouAW2Dtc +T9jdRAwKJXqA2Eg6OkgXCEv+kwKBwQDYaQiFMlFhsmLlqI+EzCUh7c941/cL7m6U +7j98+8ngl0HgCEcrc10iJVCKakQW3YbPzAx3XkKTaGjWazvvrFarXIGlOud64B8a +iWyQ7VdlnmZnNEdk+C83tI91OQeaTKqRLDGzKh29Ry/jL8Pcbazt+kDgxa0H7qJp +roADUanLQuNkYubpbhFBh3xpa2EExaVq6rF7nIVsD8W9TrbmPKA4LgH7z0iy544D +kVCNYsTjYDdUWP+WiSor8kCnnpjnN9sCgcEAw/eNezUD1UDf6OYFC9+5JZJFn4Tg +mZMyN93JKIb199ffwnjtHUSjcyiWeesXucpzwtGbTcwQnDisSW4oneYKLSEBlBaq +scqiUugyGZZOthFSCbdXYXMViK2vHrKlkse7GxVlROKcEhM/pRBrmjaGO8eWR+D4 +FO2wCXzVs3KgV6j779frw0vC54oHOxc9+Lu1rSHp4i+600koyvL/zF6U/5tZXIvN +YW2yoiQJnjCmVA1pwbwV6KAUTPDTMnBK+YjnAoHBAJBGBa4hi5Z27JkbCliIGMFJ +NPs6pLKe9GNJf6in2+sPgUAFhMeiPhbDiwbxgrnpBIqICE+ULGJFmzmc0p/IOceT +ARjR76dAFLxbnbXzj5kURETNhO36yiUjCk4mBRGIcbYddndxaSjaH+zKgpLzyJ6m +1esuc1qfFvEfAAI2cTIsl5hB70ZJYNZaUvDyQK3ZGPHxy6e9rkgKg9OJz0QoatAe +q/002yHvtAJg4F5B2JeVejg7VQ8GHB1MKxppu0TP5wKBwQCCpQj8zgKOKz/wmViy +lSYZDC5qWJW7t3bP6TDFr06lOpUsUJ4TgxeiGw778g/RMaKB4RIz3WBoJcgw9BsT +7rFza1ZiucchMcGMmswRDt8kC4wGejpA92Owc8oUdxkMhSdnY5jYlxK2t3/DYEe8 +JFl9L7mFQKVjSSAGUzkiTGrlG1Kf5UfXh9dFBq98uilQfSPIwUaWynyM23CHTKqI +Pw3/vOY9sojrnncWwrEUIG7is5vWfWPwargzSzd29YdRBe8CgcEAuRVewK/YeNOX +B7ZG6gKKsfsvrGtY7FPETzLZAHjoVXYNea4LVZ2kn4hBXXlvw/4HD+YqcTt4wmif +5JQlDvjNobUiKJZpzy7hklVhF7wZFl4pCF7Yh43q9iQ7gKTaeUG7MiaK+G8Zz8aY +HW9rsiihbdZkccMvnPfO9334XMxl3HtBRzLstjUlbLB7Sdh+7tZ3JQidCOFNs5pE +XyWwnASPu4tKfDahH1UUTp1uJcq/6716CSWg080avYxFcn75qqsb +-----END RSA PRIVATE KEY----- From patchwork Sun Mar 17 21:14:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 10856641 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 875FB13B5 for ; Sun, 17 Mar 2019 21:20:14 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6F714290A8 for ; Sun, 17 Mar 2019 21:20:14 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5D97C2916E; Sun, 17 Mar 2019 21:20:14 +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 445DD2914C for ; Sun, 17 Mar 2019 21:20:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727484AbfCQVUG (ORCPT ); Sun, 17 Mar 2019 17:20:06 -0400 Received: from mga01.intel.com ([192.55.52.88]:50822 "EHLO mga01.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727426AbfCQVUF (ORCPT ); Sun, 17 Mar 2019 17:20:05 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Mar 2019 14:20:04 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,491,1544515200"; d="scan'208";a="142817409" Received: from vanderss-mobl1.ger.corp.intel.com (HELO localhost) ([10.249.254.193]) by orsmga002.jf.intel.com with ESMTP; 17 Mar 2019 14:19:55 -0700 From: Jarkko Sakkinen To: x86@kernel.org, linux-sgx@vger.kernel.org Cc: akpm@linux-foundation.org, dave.hansen@intel.com, sean.j.christopherson@intel.com, nhorman@redhat.com, npmccallum@redhat.com, serge.ayoun@intel.com, shay.katz-zamir@intel.com, haitao.huang@intel.com, andriy.shevchenko@linux.intel.com, tglx@linutronix.de, kai.svahn@intel.com, bp@alien8.de, josh@joshtriplett.org, luto@kernel.org, kai.huang@intel.com, rientjes@google.com, Jarkko Sakkinen Subject: [PATCH v19 27/27] x86/sgx: Update MAINTAINERS Date: Sun, 17 Mar 2019 23:14:56 +0200 Message-Id: <20190317211456.13927-28-jarkko.sakkinen@linux.intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> References: <20190317211456.13927-1-jarkko.sakkinen@linux.intel.com> MIME-Version: 1.0 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 Add the maintainer information for the SGX subsystem. Signed-off-by: Jarkko Sakkinen --- MAINTAINERS | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index e17ebf70b548..7abcb460dde9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8044,6 +8044,18 @@ L: linux-gpio@vger.kernel.org S: Maintained F: drivers/gpio/gpio-intel-mid.c +INTEL SGX +M: Jarkko Sakkinen +M: Sean Christopherson +L: linux-sgx@vger.kernel.org +S: Maintained +Q: https://patchwork.kernel.org/project/intel-sgx/list/ +T: git https://github.com/jsakkine-intel/linux-sgx.git +F: arch/x86/include/asm/sgx.h +F: arch/x86/include/uapi/asm/sgx.h +F: arch/x86/kernel/cpu/sgx/* +K: \bSGX_ + INTERCONNECT API M: Georgi Djakov S: Maintained