linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
To: linux-kernel@vger.kernel.org, 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 <jarkko.sakkinen@linux.intel.com>
Subject: [PATCH v19,RESEND 15/27] x86/sgx: Add sgx_einit() for initializing enclaves
Date: Wed, 20 Mar 2019 18:21:07 +0200	[thread overview]
Message-ID: <20190320162119.4469-16-jarkko.sakkinen@linux.intel.com> (raw)
In-Reply-To: <20190320162119.4469-1-jarkko.sakkinen@linux.intel.com>

From: Sean Christopherson <sean.j.christopherson@intel.com>

Add a helper function to perform ENCLS(EINIT) with the correct LE
hash MSR values.  ENCLS[EINIT] initializes an enclave, verifying the
enclave's measurement and preparing it for execution, i.e. the enclave
cannot be run until it has been initialized.  The measurement aspect
of EINIT references the MSR_IA32_SGXLEPUBKEYHASH* MSRs, with the CPU
comparing CPU compares the key (technically its hash) used to sign the
enclave[1] with the key hash stored in the MSRs, and will reject EINIT
if the keys do not match.

A per-cpu cache is used to avoid writing the MSRs as writing the MSRs
is extraordinarily expensive, e.g. 300-400 cycles per MSR.  Because
the cache may become stale, force update the MSRs and retry EINIT if
the first EINIT fails due to an "invalid token".  An invalid token
error does not necessarily mean the MSRs need to be updated, but the
cost of an unnecessary write is minimal relative to the cost of EINIT
itself.

[1] For EINIT's purposes, the effective signer of the enclave may be
    the enclave's owner, or a separate Launch Enclave that has created
    an EINIT token for the target enclave.  When using an EINIT token,
    the key used to sign the token must match the MSRs in order for
    EINIT to succeed.

Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Co-developed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
 arch/x86/kernel/cpu/sgx/main.c | 51 ++++++++++++++++++++++++++++++++++
 arch/x86/kernel/cpu/sgx/sgx.h  |  2 ++
 2 files changed, 53 insertions(+)

diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c
index f88c8d86c2a8..e966f96837c7 100644
--- a/arch/x86/kernel/cpu/sgx/main.c
+++ b/arch/x86/kernel/cpu/sgx/main.c
@@ -17,6 +17,9 @@ EXPORT_SYMBOL_GPL(sgx_epc_sections);
 
 static int sgx_nr_epc_sections;
 
+/* A per-cpu cache for the last known values of IA32_SGXLEPUBKEYHASHx MSRs. */
+static DEFINE_PER_CPU(u64 [4], sgx_lepubkeyhash_cache);
+
 static void sgx_section_put_page(struct sgx_epc_section *section,
 				 struct sgx_epc_page *page)
 {
@@ -112,6 +115,54 @@ void sgx_free_page(struct sgx_epc_page *page)
 }
 EXPORT_SYMBOL_GPL(sgx_free_page);
 
+static void sgx_update_lepubkeyhash_msrs(u64 *lepubkeyhash, bool enforce)
+{
+	u64 *cache;
+	int i;
+
+	cache = per_cpu(sgx_lepubkeyhash_cache, smp_processor_id());
+	for (i = 0; i < 4; i++) {
+		if (enforce || (lepubkeyhash[i] != cache[i])) {
+			wrmsrl(MSR_IA32_SGXLEPUBKEYHASH0 + i, lepubkeyhash[i]);
+			cache[i] = lepubkeyhash[i];
+		}
+	}
+}
+
+/**
+ * sgx_einit - initialize an enclave
+ * @sigstruct:		a pointer a SIGSTRUCT
+ * @token:		a pointer an EINITTOKEN (optional)
+ * @secs:		a pointer a SECS
+ * @lepubkeyhash:	the desired value for IA32_SGXLEPUBKEYHASHx MSRs
+ *
+ * Execute ENCLS[EINIT], writing the IA32_SGXLEPUBKEYHASHx MSRs according
+ * to @lepubkeyhash (if possible and necessary).
+ *
+ * Return:
+ *   0 on success,
+ *   -errno or SGX error on failure
+ */
+int sgx_einit(struct sgx_sigstruct *sigstruct, struct sgx_einittoken *token,
+	      struct sgx_epc_page *secs, u64 *lepubkeyhash)
+{
+	int ret;
+
+	if (!boot_cpu_has(X86_FEATURE_SGX_LC))
+		return __einit(sigstruct, token, sgx_epc_addr(secs));
+
+	preempt_disable();
+	sgx_update_lepubkeyhash_msrs(lepubkeyhash, false);
+	ret = __einit(sigstruct, token, sgx_epc_addr(secs));
+	if (ret == SGX_INVALID_EINITTOKEN) {
+		sgx_update_lepubkeyhash_msrs(lepubkeyhash, true);
+		ret = __einit(sigstruct, token, sgx_epc_addr(secs));
+	}
+	preempt_enable();
+	return ret;
+}
+EXPORT_SYMBOL(sgx_einit);
+
 static __init void sgx_free_epc_section(struct sgx_epc_section *section)
 {
 	struct sgx_epc_page *page;
diff --git a/arch/x86/kernel/cpu/sgx/sgx.h b/arch/x86/kernel/cpu/sgx/sgx.h
index 86b4c74b6089..f90d02fbbbbd 100644
--- a/arch/x86/kernel/cpu/sgx/sgx.h
+++ b/arch/x86/kernel/cpu/sgx/sgx.h
@@ -62,5 +62,7 @@ static inline void *sgx_epc_addr(struct sgx_epc_page *page)
 struct sgx_epc_page *sgx_alloc_page(void);
 int __sgx_free_page(struct sgx_epc_page *page);
 void sgx_free_page(struct sgx_epc_page *page);
+int sgx_einit(struct sgx_sigstruct *sigstruct, struct sgx_einittoken *token,
+	      struct sgx_epc_page *secs, u64 *lepubkeyhash);
 
 #endif /* _X86_SGX_H */
-- 
2.19.1


  parent reply	other threads:[~2019-03-20 16:24 UTC|newest]

Thread overview: 68+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-03-20 16:20 [PATCH v19,RESEND 00/27] Intel SGX1 support Jarkko Sakkinen
2019-03-20 16:20 ` [PATCH v19,RESEND 01/27] x86/cpufeatures: Add Intel-defined SGX feature bit Jarkko Sakkinen
2019-03-20 19:41   ` Neil Horman
2019-03-21 14:16     ` Jarkko Sakkinen
2019-03-20 16:20 ` [PATCH v19,RESEND 02/27] x86/cpufeatures: Add SGX sub-features (as Linux-defined bits) Jarkko Sakkinen
2019-03-20 16:20 ` [PATCH v19,RESEND 03/27] x86/msr: Add IA32_FEATURE_CONTROL.SGX_ENABLE definition Jarkko Sakkinen
2019-03-20 16:20 ` [PATCH v19,RESEND 04/27] x86/cpufeatures: Add Intel-defined SGX_LC feature bit Jarkko Sakkinen
2019-03-20 16:20 ` [PATCH v19,RESEND 05/27] x86/msr: Add SGX Launch Control MSR definitions Jarkko Sakkinen
2019-03-20 16:20 ` [PATCH v19,RESEND 06/27] x86/mm: x86/sgx: Add new 'PF_SGX' page fault error code bit Jarkko Sakkinen
2019-03-20 16:20 ` [PATCH v19,RESEND 07/27] x86/mm: x86/sgx: Signal SIGSEGV for userspace #PFs w/ PF_SGX Jarkko Sakkinen
2019-03-20 16:21 ` [PATCH v19,RESEND 08/27] x86/cpu/intel: Detect SGX support and update caps appropriately Jarkko Sakkinen
2019-03-26 12:17   ` Huang, Kai
2019-03-26 14:27     ` Sean Christopherson
2019-03-26 21:25       ` Huang, Kai
2019-03-26 21:57         ` Sean Christopherson
2019-03-26 23:19           ` Huang, Kai
2019-03-20 16:21 ` [PATCH v19,RESEND 09/27] x86/sgx: Add ENCLS architectural error codes Jarkko Sakkinen
2019-03-20 16:21 ` [PATCH v19,RESEND 10/27] x86/sgx: Add SGX1 and SGX2 architectural data structures Jarkko Sakkinen
2019-03-20 16:21 ` [PATCH v19,RESEND 11/27] x86/sgx: Add definitions for SGX's CPUID leaf and variable sub-leafs Jarkko Sakkinen
2019-03-20 16:21 ` [PATCH v19,RESEND 12/27] x86/sgx: Enumerate and track EPC sections Jarkko Sakkinen
2019-03-20 16:21 ` [PATCH v19,RESEND 13/27] x86/sgx: Add wrappers for ENCLS leaf functions Jarkko Sakkinen
2019-03-20 16:21 ` [PATCH v19,RESEND 14/27] x86/sgx: Add functions to allocate and free EPC pages Jarkko Sakkinen
2019-03-20 16:21 ` Jarkko Sakkinen [this message]
2019-03-20 16:21 ` [PATCH v19,RESEND 16/27] x86/sgx: Add the Linux SGX Enclave Driver Jarkko Sakkinen
2019-03-26 12:01   ` Huang, Kai
2019-03-26 12:40     ` Thomas Gleixner
2019-03-26 14:54       ` Sean Christopherson
2019-03-26 21:11         ` Huang, Kai
2019-03-27  5:02     ` Jarkko Sakkinen
2019-03-20 16:21 ` [PATCH v19,RESEND 17/27] x86/sgx: Add provisioning Jarkko Sakkinen
2019-03-20 16:21 ` [PATCH v19,RESEND 18/27] x86/sgx: Add swapping code to the core and SGX driver Jarkko Sakkinen
2019-03-20 16:21 ` [PATCH v19,RESEND 19/27] x86/sgx: ptrace() support for the " Jarkko Sakkinen
2019-03-20 16:21 ` [PATCH v19,RESEND 20/27] x86/vdso: Add support for exception fixup in vDSO functions Jarkko Sakkinen
2019-03-20 16:21 ` [PATCH v19,RESEND 21/27] x86/fault: Add helper function to sanitize error code Jarkko Sakkinen
2019-03-20 16:21 ` [PATCH v19,RESEND 22/27] x86/fault: Attempt to fixup unhandled #PF in vDSO before signaling Jarkko Sakkinen
2019-03-20 16:21 ` [PATCH v19,RESEND 23/27] x86/traps: Attempt to fixup exceptions " Jarkko Sakkinen
2019-03-20 16:21 ` [PATCH v19,RESEND 24/27] x86/vdso: Add __vdso_sgx_enter_enclave() to wrap SGX enclave transitions Jarkko Sakkinen
2019-03-20 18:30   ` Xing, Cedric
2019-03-20 18:52     ` Andy Lutomirski
2019-03-20 19:57       ` Xing, Cedric
2019-03-20 21:03         ` Sean Christopherson
2019-03-21  0:17           ` Xing, Cedric
2019-03-22 21:20             ` Sean Christopherson
2019-03-21 17:17         ` Andy Lutomirski
2019-03-22 20:31           ` Xing, Cedric
2019-03-20 19:02     ` Jethro Beekman
2019-03-20 20:10       ` Xing, Cedric
2019-03-20 19:13     ` Sean Christopherson
2019-03-20 20:38       ` Xing, Cedric
2019-03-22 21:59         ` Sean Christopherson
2019-03-23 17:36           ` Xing, Cedric
2019-03-23 21:38             ` Andy Lutomirski
2019-03-24  8:59               ` Xing, Cedric
2019-03-25 18:03                 ` Sean Christopherson
2019-03-25 23:59                   ` Andy Lutomirski
2019-03-26  4:53                     ` Xing, Cedric
2019-03-26 17:08                       ` Andy Lutomirski
2019-03-28  4:23                         ` Xing, Cedric
2019-03-28 19:18                           ` Andy Lutomirski
2019-03-28 23:19                             ` Xing, Cedric
2019-03-29  9:48                               ` Jarkko Sakkinen
2019-03-31  8:43                                 ` Dr. Greg
2019-04-03 23:03                             ` Sean Christopherson
2019-03-25 23:54                 ` Andy Lutomirski
2019-03-26  4:16                   ` Xing, Cedric
2019-03-20 16:21 ` [PATCH v19,RESEND 25/27] x86/sgx: SGX documentation Jarkko Sakkinen
2019-03-20 16:21 ` [PATCH v19,RESEND 26/27] selftests/x86: Add a selftest for SGX Jarkko Sakkinen
2019-03-20 16:21 ` [PATCH v19,RESEND 27/27] x86/sgx: Update MAINTAINERS Jarkko Sakkinen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190320162119.4469-16-jarkko.sakkinen@linux.intel.com \
    --to=jarkko.sakkinen@linux.intel.com \
    --cc=akpm@linux-foundation.org \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=bp@alien8.de \
    --cc=dave.hansen@intel.com \
    --cc=haitao.huang@intel.com \
    --cc=josh@joshtriplett.org \
    --cc=kai.huang@intel.com \
    --cc=kai.svahn@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-sgx@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=nhorman@redhat.com \
    --cc=npmccallum@redhat.com \
    --cc=rientjes@google.com \
    --cc=sean.j.christopherson@intel.com \
    --cc=serge.ayoun@intel.com \
    --cc=shay.katz-zamir@intel.com \
    --cc=tglx@linutronix.de \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).