linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v17 01/23] x86/sgx: Update MAINTAINERS
       [not found] <20181116010412.23967-1-jarkko.sakkinen@linux.intel.com>
@ 2018-11-16  1:01 ` Jarkko Sakkinen
  2018-11-16 14:22   ` Borislav Petkov
  2018-11-16  1:01 ` [PATCH v17 02/23] x86/cpufeatures: Add Intel-defined SGX feature bit Jarkko Sakkinen
                   ` (22 subsequent siblings)
  23 siblings, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-16  1:01 UTC (permalink / raw)
  To: x86, platform-driver-x86, linux-sgx
  Cc: dave.hansen, sean.j.christopherson, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Jarkko Sakkinen,
	Mauro Carvalho Chehab, Greg Kroah-Hartman, David S. Miller,
	Andrew Morton, Nicolas Ferre, Arnd Bergmann, open list

Add the maintainer information for the SGX subsystem.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 0abecc528dac..aaf56b544858 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7676,6 +7676,13 @@ L:	linux-gpio@vger.kernel.org
 S:	Maintained
 F:	drivers/gpio/gpio-intel-mid.c
 
+INTEL SGX
+M:	Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+L:	linux-sgx@vger.kernel.org
+Q:	https://patchwork.kernel.org/project/intel-sgx/list/
+F:	drivers/platform/x86/intel_sgx/
+K:	\bSGX_
+
 INVENSENSE MPU-3050 GYROSCOPE DRIVER
 M:	Linus Walleij <linus.walleij@linaro.org>
 L:	linux-iio@vger.kernel.org
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 155+ messages in thread

* [PATCH v17 02/23] x86/cpufeatures: Add Intel-defined SGX feature bit
       [not found] <20181116010412.23967-1-jarkko.sakkinen@linux.intel.com>
  2018-11-16  1:01 ` [PATCH v17 01/23] x86/sgx: Update MAINTAINERS Jarkko Sakkinen
@ 2018-11-16  1:01 ` Jarkko Sakkinen
  2018-11-16 14:28   ` Borislav Petkov
  2018-11-16  1:01 ` [PATCH v17 03/23] x86/cpufeatures: Add SGX sub-features (as Linux-defined bits) Jarkko Sakkinen
                   ` (21 subsequent siblings)
  23 siblings, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-16  1:01 UTC (permalink / raw)
  To: x86, platform-driver-x86, linux-sgx
  Cc: dave.hansen, sean.j.christopherson, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Kai Huang, Jarkko Sakkinen,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Konrad Rzeszutek Wilk, David Woodhouse, Fenghua Yu,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

From: Kai Huang <kai.huang@linux.intel.com>

X86_FEATURE_SGX reflects whether or not the CPU supports Intel's
Software Guard eXtensions (SGX).

Signed-off-by: Kai Huang <kai.huang@linux.intel.com>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
 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 28c4a502b419..da7fed4939a3 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 */
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 155+ messages in thread

* [PATCH v17 03/23] x86/cpufeatures: Add SGX sub-features (as Linux-defined bits)
       [not found] <20181116010412.23967-1-jarkko.sakkinen@linux.intel.com>
  2018-11-16  1:01 ` [PATCH v17 01/23] x86/sgx: Update MAINTAINERS Jarkko Sakkinen
  2018-11-16  1:01 ` [PATCH v17 02/23] x86/cpufeatures: Add Intel-defined SGX feature bit Jarkko Sakkinen
@ 2018-11-16  1:01 ` Jarkko Sakkinen
  2018-11-16 14:37   ` Borislav Petkov
  2018-11-16 23:31   ` Dave Hansen
  2018-11-16  1:01 ` [PATCH v17 04/23] x86/msr: Add IA32_FEATURE_CONTROL.SGX_ENABLE definition Jarkko Sakkinen
                   ` (20 subsequent siblings)
  23 siblings, 2 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-16  1:01 UTC (permalink / raw)
  To: x86, platform-driver-x86, linux-sgx
  Cc: dave.hansen, sean.j.christopherson, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Jarkko Sakkinen,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Konrad Rzeszutek Wilk, David Woodhouse, Fenghua Yu,
	Brijesh Singh, Paolo Bonzini, Tom Lendacky,
	Arnaldo Carvalho de Melo,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

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

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 <sean.j.christopherson@intel.com>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
 arch/x86/include/asm/cpufeatures.h       | 21 +++++++++++++++------
 arch/x86/kernel/cpu/scattered.c          |  2 ++
 tools/arch/x86/include/asm/cpufeatures.h | 21 +++++++++++++++------
 3 files changed, 32 insertions(+), 12 deletions(-)

diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index da7fed4939a3..afdf5f2e13b5 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/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 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 */
+
+#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/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c
index 772c219b6889..f7f0970b8f89 100644
--- a/arch/x86/kernel/cpu/scattered.c
+++ b/arch/x86/kernel/cpu/scattered.c
@@ -26,6 +26,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 89a048c2faec..9cc7628b9845 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 */
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 155+ messages in thread

* [PATCH v17 04/23] x86/msr: Add IA32_FEATURE_CONTROL.SGX_ENABLE definition
       [not found] <20181116010412.23967-1-jarkko.sakkinen@linux.intel.com>
                   ` (2 preceding siblings ...)
  2018-11-16  1:01 ` [PATCH v17 03/23] x86/cpufeatures: Add SGX sub-features (as Linux-defined bits) Jarkko Sakkinen
@ 2018-11-16  1:01 ` Jarkko Sakkinen
  2018-11-16  1:01 ` [PATCH v17 05/23] x86/cpufeatures: Add Intel-defined SGX_LC feature bit Jarkko Sakkinen
                   ` (19 subsequent siblings)
  23 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-16  1:01 UTC (permalink / raw)
  To: x86, platform-driver-x86, linux-sgx
  Cc: dave.hansen, sean.j.christopherson, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Jarkko Sakkinen,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Konrad Rzeszutek Wilk, Tom Lendacky, Paolo Bonzini,
	David Woodhouse, Janakarajan Natarajan, Matt Turner,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

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

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 <sean.j.christopherson@intel.com>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
 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 80f4a4f38c79..082890bff490 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -487,6 +487,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
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 155+ messages in thread

* [PATCH v17 05/23] x86/cpufeatures: Add Intel-defined SGX_LC feature bit
       [not found] <20181116010412.23967-1-jarkko.sakkinen@linux.intel.com>
                   ` (3 preceding siblings ...)
  2018-11-16  1:01 ` [PATCH v17 04/23] x86/msr: Add IA32_FEATURE_CONTROL.SGX_ENABLE definition Jarkko Sakkinen
@ 2018-11-16  1:01 ` Jarkko Sakkinen
  2018-11-16  1:01 ` [PATCH v17 06/23] x86/cpu/intel: Detect SGX support and update caps appropriately Jarkko Sakkinen
                   ` (18 subsequent siblings)
  23 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-16  1:01 UTC (permalink / raw)
  To: x86, platform-driver-x86, linux-sgx
  Cc: dave.hansen, sean.j.christopherson, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Kai Huang, Jarkko Sakkinen,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Konrad Rzeszutek Wilk, David Woodhouse, Fenghua Yu,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

From: Kai Huang <kai.huang@linux.intel.com>

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 <kai.huang@linux.intel.com>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
 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 afdf5f2e13b5..97604c7fdfd2 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -343,6 +343,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 */
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 155+ messages in thread

* [PATCH v17 06/23] x86/cpu/intel: Detect SGX support and update caps appropriately
       [not found] <20181116010412.23967-1-jarkko.sakkinen@linux.intel.com>
                   ` (4 preceding siblings ...)
  2018-11-16  1:01 ` [PATCH v17 05/23] x86/cpufeatures: Add Intel-defined SGX_LC feature bit Jarkko Sakkinen
@ 2018-11-16  1:01 ` Jarkko Sakkinen
  2018-11-16 23:32   ` Dave Hansen
  2018-11-21 18:17   ` Borislav Petkov
  2018-11-16  1:01 ` [PATCH v17 07/23] x86/mm: x86/sgx: Add new 'PF_SGX' page fault error code bit Jarkko Sakkinen
                   ` (17 subsequent siblings)
  23 siblings, 2 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-16  1:01 UTC (permalink / raw)
  To: x86, platform-driver-x86, linux-sgx
  Cc: dave.hansen, sean.j.christopherson, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Jarkko Sakkinen,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Konrad Rzeszutek Wilk, David Woodhouse, Kirill A. Shutemov,
	David Wang, Levin, Alexander (Sasha Levin),
	Jia Zhang, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

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

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 <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/intel.c | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index fc3c07fe7df5..8a20a193d399 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -596,6 +596,40 @@ static void detect_tme(struct cpuinfo_x86 *c)
 	c->x86_phys_bits -= keyid_bits;
 }
 
+static void 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: IA32_FEATURE_CONTROL MSR is not locked\n");
+		goto out_unsupported;
+	}
+
+	if (!(fc & FEATURE_CONTROL_SGX_ENABLE)) {
+		pr_err_once("sgx: not enabled in IA32_FEATURE_CONTROL MSR\n");
+		goto out_unsupported;
+	}
+
+	if (!cpu_has(c, X86_FEATURE_SGX1)) {
+		pr_err_once("sgx: SGX1 instruction set not supported\n");
+		goto out_unsupported;
+	}
+
+	if (!(fc & FEATURE_CONTROL_SGX_LE_WR)) {
+		pr_info_once("sgx: launch control MSRs are not writable\n");
+		goto out_msrs_rdonly;
+	}
+
+	return;
+out_unsupported:
+	setup_clear_cpu_cap(X86_FEATURE_SGX);
+	setup_clear_cpu_cap(X86_FEATURE_SGX1);
+	setup_clear_cpu_cap(X86_FEATURE_SGX2);
+out_msrs_rdonly:
+	setup_clear_cpu_cap(X86_FEATURE_SGX_LC);
+}
+
 static void init_intel_energy_perf(struct cpuinfo_x86 *c)
 {
 	u64 epb;
@@ -763,6 +797,9 @@ static void init_intel(struct cpuinfo_x86 *c)
 	if (cpu_has(c, X86_FEATURE_TME))
 		detect_tme(c);
 
+	if (cpu_has(c, X86_FEATURE_SGX))
+		detect_sgx(c);
+
 	init_intel_energy_perf(c);
 
 	init_intel_misc_features(c);
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 155+ messages in thread

* [PATCH v17 07/23] x86/mm: x86/sgx: Add new 'PF_SGX' page fault error code bit
       [not found] <20181116010412.23967-1-jarkko.sakkinen@linux.intel.com>
                   ` (5 preceding siblings ...)
  2018-11-16  1:01 ` [PATCH v17 06/23] x86/cpu/intel: Detect SGX support and update caps appropriately Jarkko Sakkinen
@ 2018-11-16  1:01 ` Jarkko Sakkinen
  2018-11-16 23:33   ` Dave Hansen
  2018-11-16  1:01 ` [PATCH v17 08/23] x86/mm: x86/sgx: Signal SIGSEGV for userspace #PFs w/ PF_SGX Jarkko Sakkinen
                   ` (16 subsequent siblings)
  23 siblings, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-16  1:01 UTC (permalink / raw)
  To: x86, platform-driver-x86, linux-sgx
  Cc: dave.hansen, sean.j.christopherson, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Dave Hansen,
	Jarkko Sakkinen, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Andy Lutomirski, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

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

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).

Cc: Dave Hansen <dave.hansen@linux.intel.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
 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 3de69330e6c5..165c93dd700e 100644
--- a/arch/x86/include/asm/traps.h
+++ b/arch/x86/include/asm/traps.h
@@ -162,5 +162,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 */
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 155+ messages in thread

* [PATCH v17 08/23] x86/mm: x86/sgx: Signal SIGSEGV for userspace #PFs w/ PF_SGX
       [not found] <20181116010412.23967-1-jarkko.sakkinen@linux.intel.com>
                   ` (6 preceding siblings ...)
  2018-11-16  1:01 ` [PATCH v17 07/23] x86/mm: x86/sgx: Add new 'PF_SGX' page fault error code bit Jarkko Sakkinen
@ 2018-11-16  1:01 ` Jarkko Sakkinen
  2018-11-16  1:01 ` [PATCH v17 09/23] x86/sgx: Define SGX1 and SGX2 ENCLS leafs Jarkko Sakkinen
                   ` (15 subsequent siblings)
  23 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-16  1:01 UTC (permalink / raw)
  To: x86, platform-driver-x86, linux-sgx
  Cc: dave.hansen, sean.j.christopherson, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Dave Hansen,
	Jarkko Sakkinen, Andy Lutomirski, Peter Zijlstra, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, open list:X86 MM

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

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 <luto@amacapital.net>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
 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 71d4b9d4d43f..eb8db2425b5b 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -1108,6 +1108,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
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 155+ messages in thread

* [PATCH v17 09/23] x86/sgx: Define SGX1 and SGX2 ENCLS leafs
       [not found] <20181116010412.23967-1-jarkko.sakkinen@linux.intel.com>
                   ` (7 preceding siblings ...)
  2018-11-16  1:01 ` [PATCH v17 08/23] x86/mm: x86/sgx: Signal SIGSEGV for userspace #PFs w/ PF_SGX Jarkko Sakkinen
@ 2018-11-16  1:01 ` Jarkko Sakkinen
  2018-11-16  1:01 ` [PATCH v17 10/23] x86/sgx: Add ENCLS architectural error codes Jarkko Sakkinen
                   ` (14 subsequent siblings)
  23 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-16  1:01 UTC (permalink / raw)
  To: x86, platform-driver-x86, linux-sgx
  Cc: dave.hansen, sean.j.christopherson, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Jarkko Sakkinen,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

ENCLS, a.k.a. Enclave System instruction, is an umbrella instruction
for a variety of privileged SGX functions.  The ENCLS function to be
executed is specified in EAX, a la GETSEC of SMX/TXT fame.  Leafs may
use additional registers for function-specific operands.  ENCLS also
introduces its own set of error codes that (some) leafs use to return
pass/fail information to software.  Leafs that return an error code
also modify RFLAGS.  And finally, ENCLS generates ENCLS-specific #GPs
and #PFs.

ENCLS leafs functions are organized under SGX sub-features, e.g. SGX1
defines the base ENCLS function set and SGX2 adds ENCLS functions to
enable dynamic EPC management.  At this time, only the SGX1 and SGX2
function sets are supported by Linux; the other published sets relate
to VMM EPC oversubscription, which is far out on the horizon.

Define the ENCLS leafs in a dedicated file as more architecturally
defined SGX constants and data structures will be introduced in short
order.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Co-developed-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
---
 arch/x86/include/asm/sgx_arch.h | 54 +++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)
 create mode 100644 arch/x86/include/asm/sgx_arch.h

diff --git a/arch/x86/include/asm/sgx_arch.h b/arch/x86/include/asm/sgx_arch.h
new file mode 100644
index 000000000000..e068db46835e
--- /dev/null
+++ b/arch/x86/include/asm/sgx_arch.h
@@ -0,0 +1,54 @@
+/* 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
+
+/**
+ * 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,
+};
+
+#endif /* _ASM_X86_SGX_ARCH_H */
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 155+ messages in thread

* [PATCH v17 10/23] x86/sgx: Add ENCLS architectural error codes
       [not found] <20181116010412.23967-1-jarkko.sakkinen@linux.intel.com>
                   ` (8 preceding siblings ...)
  2018-11-16  1:01 ` [PATCH v17 09/23] x86/sgx: Define SGX1 and SGX2 ENCLS leafs Jarkko Sakkinen
@ 2018-11-16  1:01 ` Jarkko Sakkinen
  2018-11-16  1:01 ` [PATCH v17 11/23] x86/sgx: Add SGX1 and SGX2 architectural data structures Jarkko Sakkinen
                   ` (13 subsequent siblings)
  23 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-16  1:01 UTC (permalink / raw)
  To: x86, platform-driver-x86, linux-sgx
  Cc: dave.hansen, sean.j.christopherson, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Jarkko Sakkinen,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

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 <jarkko.sakkinen@linux.intel.com>
Co-developed-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
---
 arch/x86/include/asm/sgx_arch.h       |  2 +
 arch/x86/include/uapi/asm/sgx_errno.h | 91 +++++++++++++++++++++++++++
 2 files changed, 93 insertions(+)
 create mode 100644 arch/x86/include/uapi/asm/sgx_errno.h

diff --git a/arch/x86/include/asm/sgx_arch.h b/arch/x86/include/asm/sgx_arch.h
index e068db46835e..6cd572fa95fa 100644
--- a/arch/x86/include/asm/sgx_arch.h
+++ b/arch/x86/include/asm/sgx_arch.h
@@ -8,6 +8,8 @@
 #ifndef _ASM_X86_SGX_ARCH_H
 #define _ASM_X86_SGX_ARCH_H
 
+#include <uapi/asm/sgx_errno.h>
+
 /**
  * enum sgx_encls_leaves - ENCLS leaf functions
  * %SGX_ECREATE:	Create an enclave.
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 */
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 155+ messages in thread

* [PATCH v17 11/23] x86/sgx: Add SGX1 and SGX2 architectural data structures
       [not found] <20181116010412.23967-1-jarkko.sakkinen@linux.intel.com>
                   ` (9 preceding siblings ...)
  2018-11-16  1:01 ` [PATCH v17 10/23] x86/sgx: Add ENCLS architectural error codes Jarkko Sakkinen
@ 2018-11-16  1:01 ` Jarkko Sakkinen
  2018-11-16  1:01 ` [PATCH v17 12/23] x86/sgx: Add definitions for SGX's CPUID leaf and variable sub-leafs Jarkko Sakkinen
                   ` (12 subsequent siblings)
  23 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-16  1:01 UTC (permalink / raw)
  To: x86, platform-driver-x86, linux-sgx
  Cc: dave.hansen, sean.j.christopherson, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Jarkko Sakkinen,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

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 <jarkko.sakkinen@linux.intel.com>
Co-developed-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
---
 arch/x86/include/asm/sgx_arch.h | 329 ++++++++++++++++++++++++++++++++
 1 file changed, 329 insertions(+)

diff --git a/arch/x86/include/asm/sgx_arch.h b/arch/x86/include/asm/sgx_arch.h
index 6cd572fa95fa..d4c57154e6e6 100644
--- a/arch/x86/include/asm/sgx_arch.h
+++ b/arch/x86/include/asm/sgx_arch.h
@@ -8,6 +8,7 @@
 #ifndef _ASM_X86_SGX_ARCH_H
 #define _ASM_X86_SGX_ARCH_H
 
+#include <linux/types.h>
 #include <uapi/asm/sgx_errno.h>
 
 /**
@@ -53,4 +54,332 @@ enum sgx_encls_leaves {
 	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_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_RESERVED_MASK  = BIT_ULL(3) | GENMASK_ULL(63, 6)
+};
+
+#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 - an enclave signature
+ * @header1:		a constant byte string
+ * @vendor:		must be either 0x0000 or 0x8086
+ * @date:		YYYYMMDD in BCD
+ * @header2:		a costant byte string
+ * @application:	an application defined value
+ * @modulus:		the modulus of the public key
+ * @exponent:		the exponent of the public key
+ * @signature:		the signature calculated over the fields except modulus,
+ *			exponent, signature, reserved4, q1 and q2
+ * @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
+ * @q1:			a value used in RSA signature verification
+ * @q2:			a value used in RSA signature verification
+ */
+struct sgx_sigstruct {
+	u64 header1[2];
+	u32 vendor;
+	u32 date;
+	u64 header2[2];
+	u32 application;
+	u8  reserved1[SGX_SIGSTRUCT_RESERVED1_SIZE];
+	u8  modulus[SGX_MODULUS_SIZE];
+	u32 exponent;
+	u8  signature[SGX_MODULUS_SIZE];
+	u32 miscselect;
+	u32 misc_mask;
+	u8  reserved2[SGX_SIGSTRUCT_RESERVED2_SIZE];
+	u64 attributes;
+	u64 xfrm;
+	u64 attributes_mask;
+	u64 xfrm_mask;
+	u8  mrenclave[32];
+	u8  reserved3[SGX_SIGSTRUCT_RESERVED3_SIZE];
+	u16 isvprodid;
+	u16 isvsvn;
+	u8  reserved4[SGX_SIGSTRUCT_RESERVED4_SIZE];
+	u8  q1[SGX_MODULUS_SIZE];
+	u8  q2[SGX_MODULUS_SIZE];
+} __packed __aligned(4096);
+
+#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 */
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 155+ messages in thread

* [PATCH v17 12/23] x86/sgx: Add definitions for SGX's CPUID leaf and variable sub-leafs
       [not found] <20181116010412.23967-1-jarkko.sakkinen@linux.intel.com>
                   ` (10 preceding siblings ...)
  2018-11-16  1:01 ` [PATCH v17 11/23] x86/sgx: Add SGX1 and SGX2 architectural data structures Jarkko Sakkinen
@ 2018-11-16  1:01 ` Jarkko Sakkinen
  2018-11-16  1:01 ` [PATCH v17 13/23] x86/msr: Add SGX Launch Control MSR definitions Jarkko Sakkinen
                   ` (11 subsequent siblings)
  23 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-16  1:01 UTC (permalink / raw)
  To: x86, platform-driver-x86, linux-sgx
  Cc: dave.hansen, sean.j.christopherson, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Jarkko Sakkinen,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

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 <jarkko.sakkinen@linux.intel.com>
Co-developed-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
---
 arch/x86/include/asm/sgx_arch.h | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/arch/x86/include/asm/sgx_arch.h b/arch/x86/include/asm/sgx_arch.h
index d4c57154e6e6..188243e3eee1 100644
--- a/arch/x86/include/asm/sgx_arch.h
+++ b/arch/x86/include/asm/sgx_arch.h
@@ -11,6 +11,21 @@
 #include <linux/types.h>
 #include <uapi/asm/sgx_errno.h>
 
+#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.
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 155+ messages in thread

* [PATCH v17 13/23] x86/msr: Add SGX Launch Control MSR definitions
       [not found] <20181116010412.23967-1-jarkko.sakkinen@linux.intel.com>
                   ` (11 preceding siblings ...)
  2018-11-16  1:01 ` [PATCH v17 12/23] x86/sgx: Add definitions for SGX's CPUID leaf and variable sub-leafs Jarkko Sakkinen
@ 2018-11-16  1:01 ` Jarkko Sakkinen
  2018-11-16 17:29   ` Sean Christopherson
  2018-11-16  1:01 ` [PATCH v17 14/23] x86/sgx: Add wrappers for ENCLS leaf functions Jarkko Sakkinen
                   ` (10 subsequent siblings)
  23 siblings, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-16  1:01 UTC (permalink / raw)
  To: x86, platform-driver-x86, linux-sgx
  Cc: dave.hansen, sean.j.christopherson, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Haim Cohen,
	Jarkko Sakkinen, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Konrad Rzeszutek Wilk, Tom Lendacky, Paolo Bonzini, Matt Turner,
	Janakarajan Natarajan, David Woodhouse,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

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

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 <sean.j.christopherson@intel.com>
Co-developed-by: Haim Cohen <haim.cohen@intel.com>
Signed-off-by: Haim Cohen <haim.cohen@intel.com>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
 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 082890bff490..9274179a445c 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -487,6 +487,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)
 
@@ -500,6 +501,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
 
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 155+ messages in thread

* [PATCH v17 14/23] x86/sgx: Add wrappers for ENCLS leaf functions
       [not found] <20181116010412.23967-1-jarkko.sakkinen@linux.intel.com>
                   ` (12 preceding siblings ...)
  2018-11-16  1:01 ` [PATCH v17 13/23] x86/msr: Add SGX Launch Control MSR definitions Jarkko Sakkinen
@ 2018-11-16  1:01 ` Jarkko Sakkinen
  2018-11-16  1:01 ` [PATCH v17 15/23] x86/sgx: Enumerate and track EPC sections Jarkko Sakkinen
                   ` (9 subsequent siblings)
  23 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-16  1:01 UTC (permalink / raw)
  To: x86, platform-driver-x86, linux-sgx
  Cc: dave.hansen, sean.j.christopherson, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Jarkko Sakkinen,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin, Suresh Siddha,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

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 <jarkko.sakkinen@linux.intel.com>
Co-developed-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
---
 arch/x86/include/asm/sgx.h | 252 +++++++++++++++++++++++++++++++++++++
 1 file changed, 252 insertions(+)
 create mode 100644 arch/x86/include/asm/sgx.h

diff --git a/arch/x86/include/asm/sgx.h b/arch/x86/include/asm/sgx.h
new file mode 100644
index 000000000000..3d5ba1d23dfb
--- /dev/null
+++ b/arch/x86/include/asm/sgx.h
@@ -0,0 +1,252 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+#ifndef _ASM_X86_SGX_H
+#define _ASM_X86_SGX_H
+
+#include <asm/asm.h>
+#include <asm/sgx_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
+
+/**
+ * Check for a fault by looking for a postive value with the fault
+ * flag set.  The postive value check is needed to filter out system
+ * error codes since negative values will have all higher order bits
+ * set, including ENCLS_FAULT_FLAG.
+ */
+#define IS_ENCLS_FAULT(r) ((int)(r) > 0 && ((r) & ENCLS_FAULT_FLAG))
+
+/**
+ * Retrieve the encoded trapnr from the specified return code.
+ */
+#define ENCLS_TRAPNR(r) ((r) & ~ENCLS_FAULT_FLAG)
+
+/**
+ * encls_to_err - translate an ENCLS fault or SGX code into a system error code
+ * @ret:	positive value return code
+ *
+ * Translate a postive return code, e.g. from ENCLS, into a system error
+ * code.  Primarily used by functions that cannot return a non-negative
+ * error code, e.g. kernel callbacks.
+ *
+ * Return:
+ *	0 on success,
+ *	-errno on failure
+ */
+static inline int encls_to_err(int ret)
+{
+	if (IS_ENCLS_FAULT(ret))
+		return -EFAULT;
+
+	switch (ret) {
+	case SGX_UNMASKED_EVENT:
+		return -EINTR;
+	case SGX_INVALID_SIG_STRUCT:
+	case SGX_INVALID_ATTRIBUTE:
+	case SGX_INVALID_MEASUREMENT:
+	case SGX_INVALID_EINITTOKEN:
+	case SGX_INVALID_CPUSVN:
+	case SGX_INVALID_ISVSVN:
+	case SGX_INVALID_KEYNAME:
+		return -EINVAL;
+	case SGX_ENCLAVE_ACT:
+	case SGX_CHILD_PRESENT:
+	case SGX_ENTRYEPOCH_LOCKED:
+	case SGX_PREV_TRK_INCMPL:
+	case SGX_PAGE_NOT_MODIFIABLE:
+	case SGX_PAGE_NOT_DEBUGGABLE:
+		return -EBUSY;
+	default:
+		return -EIO;
+	};
+}
+
+/**
+ * __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 /* _ASM_X86_SGX_H */
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 155+ messages in thread

* [PATCH v17 15/23] x86/sgx: Enumerate and track EPC sections
       [not found] <20181116010412.23967-1-jarkko.sakkinen@linux.intel.com>
                   ` (13 preceding siblings ...)
  2018-11-16  1:01 ` [PATCH v17 14/23] x86/sgx: Add wrappers for ENCLS leaf functions Jarkko Sakkinen
@ 2018-11-16  1:01 ` Jarkko Sakkinen
  2018-11-16  1:01 ` [PATCH v17 16/23] x86/sgx: Add functions to allocate and free EPC pages Jarkko Sakkinen
                   ` (8 subsequent siblings)
  23 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-16  1:01 UTC (permalink / raw)
  To: x86, platform-driver-x86, linux-sgx
  Cc: dave.hansen, sean.j.christopherson, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Jarkko Sakkinen,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Reinette Chatre, Suravee Suthikulpanit, Kirill A. Shutemov,
	Pu Wen, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

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

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 <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>
Co-developed-by: Suresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Co-developed-by: Serge Ayoun <serge.ayoun@intel.com>
Signed-off-by: Serge Ayoun <serge.ayoun@intel.com>
---
 arch/x86/Kconfig                |  17 ++++
 arch/x86/include/asm/sgx.h      |  58 +++++++++++++
 arch/x86/kernel/cpu/Makefile    |   1 +
 arch/x86/kernel/cpu/intel_sgx.c | 146 ++++++++++++++++++++++++++++++++
 4 files changed, 222 insertions(+)
 create mode 100644 arch/x86/kernel/cpu/intel_sgx.c

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 9d734f3c8234..4c3a325351ce 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1919,6 +1919,23 @@ config X86_INTEL_MEMORY_PROTECTION_KEYS
 
 	  If unsure, say y.
 
+config INTEL_SGX_CORE
+	bool "Intel SGX core functionality"
+	depends on X86_64 && CPU_SUP_INTEL
+	help
+	Intel Software Guard eXtensions (SGX) CPU feature that allows ring 3
+	applications to create enclaves: private regions of memory that are
+	architecturally protected from unauthorized access and/or modification.
+
+	This option enables kernel recognition of SGX, high-level management
+	of the Enclave Page Cache (EPC), tracking and writing of SGX Launch
+	Enclave Hash MSRs, and allows for virtualization of SGX via KVM. By
+	itself, this option does not provide SGX support to userspace.
+
+	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/include/asm/sgx.h b/arch/x86/include/asm/sgx.h
index 3d5ba1d23dfb..efe3e213e582 100644
--- a/arch/x86/include/asm/sgx.h
+++ b/arch/x86/include/asm/sgx.h
@@ -2,9 +2,67 @@
 #ifndef _ASM_X86_SGX_H
 #define _ASM_X86_SGX_H
 
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/rwsem.h>
+#include <linux/types.h>
 #include <asm/asm.h>
 #include <asm/sgx_arch.h>
 
+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 sgx_epc_page **pages;
+	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.
+ * %SGX_EPC_PAGE_RECLAIMABLE:	The page page is reclaimable. Used when freeing
+ *				a page to know that we also need to remove the
+ *				page from the list of reclaimable pages.
+ */
+enum sgx_epc_page_desc {
+	SGX_EPC_SECTION_MASK			= GENMASK_ULL(3, 0),
+	SGX_EPC_PAGE_RECLAIMABLE		= BIT(4),
+	/* 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;
+}
+
 /**
  * ENCLS_FAULT_FLAG - flag signifying an ENCLS return code is a trapnr
  *
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
index 1f5d2291c31e..b496c9360b88 100644
--- a/arch/x86/kernel/cpu/Makefile
+++ b/arch/x86/kernel/cpu/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_CPU_SUP_UMC_32)		+= umc.o
 obj-$(CONFIG_INTEL_RDT)	+= intel_rdt.o intel_rdt_rdtgroup.o intel_rdt_monitor.o
 obj-$(CONFIG_INTEL_RDT)	+= intel_rdt_ctrlmondata.o intel_rdt_pseudo_lock.o
 CFLAGS_intel_rdt_pseudo_lock.o = -I$(src)
+obj-$(CONFIG_INTEL_SGX_CORE)		+= intel_sgx.o
 
 obj-$(CONFIG_X86_MCE)			+= mcheck/
 obj-$(CONFIG_MTRR)			+= mtrr/
diff --git a/arch/x86/kernel/cpu/intel_sgx.c b/arch/x86/kernel/cpu/intel_sgx.c
new file mode 100644
index 000000000000..bfdf907c5d94
--- /dev/null
+++ b/arch/x86/kernel/cpu/intel_sgx.c
@@ -0,0 +1,146 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+// Copyright(c) 2016-17 Intel Corporation.
+
+#include <linux/freezer.h>
+#include <linux/highmem.h>
+#include <linux/kthread.h>
+#include <linux/pagemap.h>
+#include <linux/ratelimit.h>
+#include <linux/sched/signal.h>
+#include <linux/slab.h>
+#include <asm/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 __init void sgx_free_epc_section(struct sgx_epc_section *section)
+{
+	int i;
+
+	if (section->pages) {
+		for (i = 0; i < section->free_cnt && section->pages[i]; i++)
+			kfree(section->pages[i]);
+		kfree(section->pages);
+	}
+	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;
+	unsigned long i;
+
+	section->va = memremap(addr, size, MEMREMAP_WB);
+	if (!section->va)
+		return -ENOMEM;
+
+	section->pa = addr;
+	section->free_cnt = nr_pages;
+	spin_lock_init(&section->lock);
+
+	section->pages = kcalloc(nr_pages, sizeof(struct sgx_epc_page *),
+				 GFP_KERNEL);
+	if (!section->pages) {
+		pr_warn("sgx: EPC section allocation failed\n");
+		goto out;
+	}
+
+	for (i = 0; i < nr_pages; i++) {
+		section->pages[i] = kzalloc(sizeof(struct sgx_epc_page),
+					    GFP_KERNEL);
+		if (!section->pages[i])
+			goto out;
+
+		section->pages[i]->desc = (addr + (i << PAGE_SHIFT)) | index;
+	}
+
+	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);
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 155+ messages in thread

* [PATCH v17 16/23] x86/sgx: Add functions to allocate and free EPC pages
       [not found] <20181116010412.23967-1-jarkko.sakkinen@linux.intel.com>
                   ` (14 preceding siblings ...)
  2018-11-16  1:01 ` [PATCH v17 15/23] x86/sgx: Enumerate and track EPC sections Jarkko Sakkinen
@ 2018-11-16  1:01 ` Jarkko Sakkinen
  2018-11-16  1:01 ` [PATCH v17 17/23] x86/sgx: Add sgx_einit() for initializing enclaves Jarkko Sakkinen
                   ` (7 subsequent siblings)
  23 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-16  1:01 UTC (permalink / raw)
  To: x86, platform-driver-x86, linux-sgx
  Cc: dave.hansen, sean.j.christopherson, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Jarkko Sakkinen,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin, Suresh Siddha,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

At this time there is no support for reclaiming pages prior to the
owner explicitly freeing the page.  As for freeing pages, because
freeing a page is expected to succeed in the vast majority of cases
and because most call sites will not be equipped to handle failure,
provide a variant for freeing a page that warns on failure, e.g. due
to ENCLS[EREMOVE] failing.

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

diff --git a/arch/x86/include/asm/sgx.h b/arch/x86/include/asm/sgx.h
index efe3e213e582..372fc378018b 100644
--- a/arch/x86/include/asm/sgx.h
+++ b/arch/x86/include/asm/sgx.h
@@ -307,4 +307,8 @@ static inline int __emodt(struct sgx_secinfo *secinfo, void *addr)
 	return __encls_ret_2(SGX_EMODT, secinfo, addr);
 }
 
+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);
+
 #endif /* _ASM_X86_SGX_H */
diff --git a/arch/x86/kernel/cpu/intel_sgx.c b/arch/x86/kernel/cpu/intel_sgx.c
index bfdf907c5d94..59750a5df629 100644
--- a/arch/x86/kernel/cpu/intel_sgx.c
+++ b/arch/x86/kernel/cpu/intel_sgx.c
@@ -15,6 +15,83 @@ EXPORT_SYMBOL_GPL(sgx_epc_sections);
 
 static int sgx_nr_epc_sections;
 
+/**
+ * sgx_alloc_page - Allocate an EPC page
+ *
+ * Try to grab a page from the free EPC page list.
+ *
+ * Return:
+ *   a pointer to a &struct sgx_epc_page instance,
+ *   -errno on error
+ */
+struct sgx_epc_page *sgx_alloc_page(void)
+{
+	struct sgx_epc_section *section;
+	struct sgx_epc_page *page;
+	int i;
+
+	for (i = 0; i < sgx_nr_epc_sections; i++) {
+		section = &sgx_epc_sections[i];
+		spin_lock(&section->lock);
+		if (section->free_cnt) {
+			page = section->pages[section->free_cnt - 1];
+			section->free_cnt--;
+		}
+		spin_unlock(&section->lock);
+
+		if (page)
+			return page;
+	}
+
+	return ERR_PTR(-ENOMEM);
+}
+EXPORT_SYMBOL_GPL(sgx_alloc_page);
+
+/**
+ * __sgx_free_page - Free an EPC page
+ * @page:	pointer a previously allocated EPC page
+ *
+ * EREMOVE an EPC page and insert it back to the list of free pages.
+ *
+ * Return:
+ *   0 on success
+ *   SGX error code if EREMOVE fails
+ */
+int __sgx_free_page(struct sgx_epc_page *page)
+{
+	struct sgx_epc_section *section = sgx_epc_section(page);
+	int ret;
+
+	ret = __eremove(sgx_epc_addr(page));
+	if (ret)
+		return ret;
+
+	spin_lock(&section->lock);
+	section->pages[section->free_cnt++] = page;
+	spin_unlock(&section->lock);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(__sgx_free_page);
+
+/**
+ * sgx_free_page - Free an EPC page and WARN on failure
+ * @page:	pointer to a previously allocated EPC page
+ *
+ * EREMOVE an EPC page and insert it back to the list of free pages, and WARN
+ * if EREMOVE fails.  For use when the call site cannot (or chooses not to)
+ * handle failure, i.e. the page is leaked on failure.
+ */
+void sgx_free_page(struct sgx_epc_page *page)
+{
+	int ret;
+
+	ret = __sgx_free_page(page);
+	WARN(ret > 0, "sgx: EREMOVE returned %d (0x%x)", ret, ret);
+}
+EXPORT_SYMBOL_GPL(sgx_free_page);
+
+
 static __init void sgx_free_epc_section(struct sgx_epc_section *section)
 {
 	int i;
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 155+ messages in thread

* [PATCH v17 17/23] x86/sgx: Add sgx_einit() for initializing enclaves
       [not found] <20181116010412.23967-1-jarkko.sakkinen@linux.intel.com>
                   ` (15 preceding siblings ...)
  2018-11-16  1:01 ` [PATCH v17 16/23] x86/sgx: Add functions to allocate and free EPC pages Jarkko Sakkinen
@ 2018-11-16  1:01 ` Jarkko Sakkinen
  2018-11-16  1:01 ` [PATCH v17 18/23] platform/x86: Intel SGX driver Jarkko Sakkinen
                   ` (6 subsequent siblings)
  23 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-16  1:01 UTC (permalink / raw)
  To: x86, platform-driver-x86, linux-sgx
  Cc: dave.hansen, sean.j.christopherson, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Jarkko Sakkinen,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin, Suresh Siddha,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

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/include/asm/sgx.h      |  2 ++
 arch/x86/kernel/cpu/intel_sgx.c | 50 +++++++++++++++++++++++++++++++++
 2 files changed, 52 insertions(+)

diff --git a/arch/x86/include/asm/sgx.h b/arch/x86/include/asm/sgx.h
index 372fc378018b..4cdfa1d22c6e 100644
--- a/arch/x86/include/asm/sgx.h
+++ b/arch/x86/include/asm/sgx.h
@@ -310,5 +310,7 @@ static inline int __emodt(struct sgx_secinfo *secinfo, void *addr)
 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 /* _ASM_X86_SGX_H */
diff --git a/arch/x86/kernel/cpu/intel_sgx.c b/arch/x86/kernel/cpu/intel_sgx.c
index 59750a5df629..0e5fc8fc6b0d 100644
--- a/arch/x86/kernel/cpu/intel_sgx.c
+++ b/arch/x86/kernel/cpu/intel_sgx.c
@@ -15,6 +15,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);
+
 /**
  * sgx_alloc_page - Allocate an EPC page
  *
@@ -91,6 +94,53 @@ 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 __percpu *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)
 {
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 155+ messages in thread

* [PATCH v17 18/23] platform/x86: Intel SGX driver
       [not found] <20181116010412.23967-1-jarkko.sakkinen@linux.intel.com>
                   ` (16 preceding siblings ...)
  2018-11-16  1:01 ` [PATCH v17 17/23] x86/sgx: Add sgx_einit() for initializing enclaves Jarkko Sakkinen
@ 2018-11-16  1:01 ` Jarkko Sakkinen
  2018-11-16  1:37   ` Randy Dunlap
                     ` (4 more replies)
  2018-11-16  1:01 ` [PATCH v17 19/23] platform/x86: sgx: Add swapping functionality to the " Jarkko Sakkinen
                   ` (5 subsequent siblings)
  23 siblings, 5 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-16  1:01 UTC (permalink / raw)
  To: x86, platform-driver-x86, linux-sgx
  Cc: dave.hansen, sean.j.christopherson, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Jarkko Sakkinen,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

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.

SGX driver provides a ioctl API for loading and initializing enclaves.
Address range for enclaves is reserved with mmap() and they are
destroyed with munmap(). Enclave construction, measurement and
initialization is done with the provided the ioctl API.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Co-developed-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Co-developed-by: Serge Ayoun <serge.ayoun@intel.com>
Signed-off-by: Serge Ayoun <serge.ayoun@intel.com>
Co-developed-by: Shay Katz-zamir <shay.katz-zamir@intel.com>
Signed-off-by: Shay Katz-zamir <shay.katz-zamir@intel.com>
Co-developed-by: Suresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
---
 arch/x86/include/uapi/asm/sgx.h            |  59 ++
 drivers/platform/x86/Kconfig               |   2 +
 drivers/platform/x86/Makefile              |   1 +
 drivers/platform/x86/intel_sgx/Kconfig     |  20 +
 drivers/platform/x86/intel_sgx/Makefile    |  12 +
 drivers/platform/x86/intel_sgx/sgx.h       | 180 +++++
 drivers/platform/x86/intel_sgx/sgx_encl.c  | 784 +++++++++++++++++++++
 drivers/platform/x86/intel_sgx/sgx_ioctl.c | 234 ++++++
 drivers/platform/x86/intel_sgx/sgx_main.c  | 267 +++++++
 drivers/platform/x86/intel_sgx/sgx_util.c  |  85 +++
 drivers/platform/x86/intel_sgx/sgx_vma.c   |  43 ++
 11 files changed, 1687 insertions(+)
 create mode 100644 arch/x86/include/uapi/asm/sgx.h
 create mode 100644 drivers/platform/x86/intel_sgx/Kconfig
 create mode 100644 drivers/platform/x86/intel_sgx/Makefile
 create mode 100644 drivers/platform/x86/intel_sgx/sgx.h
 create mode 100644 drivers/platform/x86/intel_sgx/sgx_encl.c
 create mode 100644 drivers/platform/x86/intel_sgx/sgx_ioctl.c
 create mode 100644 drivers/platform/x86/intel_sgx/sgx_main.c
 create mode 100644 drivers/platform/x86/intel_sgx/sgx_util.c
 create mode 100644 drivers/platform/x86/intel_sgx/sgx_vma.c

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 <linux/types.h>
+#include <linux/ioctl.h>
+
+#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/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 54f6a40c75c6..e7c8d7898434 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -1288,6 +1288,8 @@ config INTEL_ATOMISP2_PM
 	  To compile this driver as a module, choose M here: the module
 	  will be called intel_atomisp2_pm.
 
+source "drivers/platform/x86/intel_sgx/Kconfig"
+
 endif # X86_PLATFORM_DEVICES
 
 config PMC_ATOM
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 39ae94135406..a826ab3d7987 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -96,3 +96,4 @@ obj-$(CONFIG_INTEL_TURBO_MAX_3) += intel_turbo_max_3.o
 obj-$(CONFIG_INTEL_CHTDC_TI_PWRBTN)	+= intel_chtdc_ti_pwrbtn.o
 obj-$(CONFIG_I2C_MULTI_INSTANTIATE)	+= i2c-multi-instantiate.o
 obj-$(CONFIG_INTEL_ATOMISP2_PM)	+= intel_atomisp2_pm.o
+obj-$(CONFIG_INTEL_SGX) += intel_sgx/
diff --git a/drivers/platform/x86/intel_sgx/Kconfig b/drivers/platform/x86/intel_sgx/Kconfig
new file mode 100644
index 000000000000..7d22d44acce9
--- /dev/null
+++ b/drivers/platform/x86/intel_sgx/Kconfig
@@ -0,0 +1,20 @@
+#
+# Intel SGX
+#
+
+config INTEL_SGX
+	tristate "Intel(R) SGX Driver"
+	depends on X86_64 && CPU_SUP_INTEL && INTEL_SGX_CORE
+	select MMU_NOTIFIER
+	select CRYPTO
+	select CRYPTO_SHA256
+	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.
diff --git a/drivers/platform/x86/intel_sgx/Makefile b/drivers/platform/x86/intel_sgx/Makefile
new file mode 100644
index 000000000000..117e97effeff
--- /dev/null
+++ b/drivers/platform/x86/intel_sgx/Makefile
@@ -0,0 +1,12 @@
+#
+# Intel SGX
+#
+
+obj-$(CONFIG_INTEL_SGX) += intel_sgx.o
+
+intel_sgx-$(CONFIG_INTEL_SGX) += \
+	sgx_encl.o \
+	sgx_ioctl.o \
+	sgx_main.o \
+	sgx_util.o \
+	sgx_vma.o \
diff --git a/drivers/platform/x86/intel_sgx/sgx.h b/drivers/platform/x86/intel_sgx/sgx.h
new file mode 100644
index 000000000000..67bd8ea1d53d
--- /dev/null
+++ b/drivers/platform/x86/intel_sgx/sgx.h
@@ -0,0 +1,180 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/**
+ * Copyright(c) 2016-18 Intel Corporation.
+ */
+#ifndef __ARCH_INTEL_SGX_H__
+#define __ARCH_INTEL_SGX_H__
+
+#include <crypto/hash.h>
+#include <linux/kref.h>
+#include <linux/mmu_notifier.h>
+#include <linux/mmu_notifier.h>
+#include <linux/radix-tree.h>
+#include <linux/radix-tree.h>
+#include <linux/rbtree.h>
+#include <linux/rwsem.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+#include <asm/sgx.h>
+#include <uapi/asm/sgx.h>
+
+#define sgx_pr(level, encl, fmt, ...)				\
+	pr_ ## level("sgx: [%d:0x%p] " fmt, pid_nr((encl)->tgid),	\
+		     (void *)(encl)->base, ##__VA_ARGS__)
+#define sgx_dbg(encl, fmt, ...) \
+	sgx_pr(debug, encl, fmt, ##__VA_ARGS__)
+#define sgx_info(encl, fmt, ...) \
+	sgx_pr(info, encl, fmt, ##__VA_ARGS__)
+#define sgx_warn(encl, fmt, ...) \
+	sgx_pr(warn, encl, fmt, ##__VA_ARGS__)
+#define sgx_err(encl, fmt, ...) \
+	sgx_pr(err, encl, fmt, ##__VA_ARGS__)
+#define sgx_crit(encl, fmt, ...) \
+	sgx_pr(crit, encl, fmt, ##__VA_ARGS__)
+
+#define SGX_EINIT_SPIN_COUNT	20
+#define SGX_EINIT_SLEEP_COUNT	50
+#define SGX_EINIT_SLEEP_TIME	20
+
+/**
+ * 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_LOADED:		The page is not swapped.
+ * %SGX_ENCL_PAGE_ADDR_MASK:		Holds the virtual address of the page.
+ */
+enum sgx_encl_page_desc {
+	SGX_ENCL_PAGE_TCS		= BIT(0),
+	SGX_ENCL_PAGE_LOADED		= BIT(1),
+	/* 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;
+	union {
+		struct sgx_epc_page *epc_page;
+		struct sgx_va_page *va_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 {
+	unsigned int flags;
+	uint64_t attributes;
+	uint64_t xfrm;
+	unsigned int page_cnt;
+	unsigned int secs_child_cnt;
+	struct mutex lock;
+	struct mm_struct *mm;
+	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 add_page_work;
+	struct sgx_encl_page secs;
+	struct pid *tgid;
+	struct mmu_notifier mmu_notifier;
+	struct notifier_block pm_notifier;
+};
+
+static inline pgoff_t sgx_encl_page_backing_index(struct sgx_encl_page *page,
+						  struct sgx_encl *encl)
+{
+	/* The backing page for SECS is located after the enclave pages. */
+	if (!PFN_DOWN(page->desc))
+		return PFN_DOWN(encl->size);
+
+	return PFN_DOWN(page->desc - encl->base);
+}
+
+extern struct workqueue_struct *sgx_add_page_wq;
+extern u64 sgx_encl_size_max_32;
+extern u64 sgx_encl_size_max_64;
+extern u64 sgx_xfrm_mask;
+extern u32 sgx_misc_reserved;
+extern u32 sgx_xsave_size_tbl[64];
+extern int sgx_epcm_trapnr;
+
+extern const struct vm_operations_struct sgx_vm_ops;
+
+int sgx_encl_find(struct mm_struct *mm, unsigned long addr,
+		  struct vm_area_struct **vma);
+void sgx_invalidate(struct sgx_encl *encl, bool flush_cpus);
+
+/**
+ * SGX_INVD - invalidate an enclave on failure, i.e. if ret != 0
+ *
+ * @ret:	a return code to check
+ * @encl:	pointer to an enclave
+ * @fmt:	message for WARN if failure is detected
+ * @...:	optional arguments used by @fmt
+ *
+ * SGX_INVD is used in flows where an error, i.e. @ret is non-zero, is
+ * indicative of a driver bug.  Invalidate @encl if @ret indicates an
+ * error and WARN on error unless the error was due to a fault signaled
+ * by the EPCM.
+ *
+ * Faults from the EPCM occur in normal kernel operation, e.g. due to
+ * misonfigured mprotect() from userspace or because the EPCM invalidated
+ * all EPC pages.  The EPCM invalidates the EPC on transitions to S3 or
+ * lower sleep states, and VMMs emulate loss of EPC when migrating VMs.
+ *
+ * Defined as a macro instead of a function so that WARN can provide a
+ * more precise trace.
+ */
+#define SGX_INVD(ret, encl, fmt, ...)					  \
+do {									  \
+	if (unlikely(ret)) {						  \
+		int trapnr = IS_ENCLS_FAULT(ret) ? ENCLS_TRAPNR(ret) : 0; \
+		WARN(trapnr != sgx_epcm_trapnr, fmt, ##__VA_ARGS__);	  \
+		sgx_invalidate(encl, true);				  \
+	}								  \
+} while (0)
+
+struct sgx_encl *sgx_encl_alloc(struct sgx_secs *secs);
+int sgx_encl_create(struct sgx_encl *encl, struct sgx_secs *secs);
+struct sgx_encl_page *sgx_encl_alloc_page(struct sgx_encl *encl,
+					  unsigned long addr);
+void sgx_encl_free_page(struct sgx_encl_page *encl_page);
+int sgx_encl_add_page(struct sgx_encl *encl, unsigned long addr, void *data,
+		      struct sgx_secinfo *secinfo, unsigned int mrmask);
+int sgx_encl_init(struct sgx_encl *encl, struct sgx_sigstruct *sigstruct,
+		  struct sgx_einittoken *einittoken);
+void sgx_encl_block(struct sgx_encl_page *encl_page);
+void sgx_encl_track(struct sgx_encl *encl);
+int sgx_encl_load_page(struct sgx_encl_page *encl_page,
+		       struct sgx_epc_page *epc_page);
+void sgx_encl_release(struct kref *ref);
+
+long sgx_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
+#ifdef CONFIG_COMPAT
+long sgx_compat_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
+#endif
+
+struct sgx_encl_page *sgx_fault_page(struct vm_area_struct *vma,
+				     unsigned long addr,
+				     bool do_reserve);
+
+int sgx_test_and_clear_young(struct sgx_encl_page *page);
+void sgx_flush_cpus(struct sgx_encl *encl);
+void sgx_set_page_loaded(struct sgx_encl_page *encl_page,
+			 struct sgx_epc_page *epc_page);
+struct page *sgx_get_backing(struct file *file, pgoff_t index);
+void sgx_put_backing(struct page *backing_page, bool write);
+
+#endif /* __ARCH_X86_INTEL_SGX_H__ */
diff --git a/drivers/platform/x86/intel_sgx/sgx_encl.c b/drivers/platform/x86/intel_sgx/sgx_encl.c
new file mode 100644
index 000000000000..6bed944c2f92
--- /dev/null
+++ b/drivers/platform/x86/intel_sgx/sgx_encl.c
@@ -0,0 +1,784 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+// Copyright(c) 2016-18 Intel Corporation.
+
+#include <asm/mman.h>
+#include <linux/delay.h>
+#include <linux/file.h>
+#include <linux/hashtable.h>
+#include <linux/highmem.h>
+#include <linux/ratelimit.h>
+#include <linux/sched/signal.h>
+#include <linux/shmem_fs.h>
+#include <linux/slab.h>
+#include <linux/suspend.h>
+#include "sgx.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;
+};
+
+/**
+ * sgx_encl_find - find an enclave
+ * @mm:		mm struct of the current process
+ * @addr:	address in the ELRANGE
+ * @vma:	the resulting VMA
+ *
+ * Finds an enclave identified by the given address. Gives back the VMA, that
+ * is part of the enclave, 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;
+}
+
+/**
+ * sgx_invalidate - kill an enclave
+ * @encl:	an &sgx_encl instance
+ * @flush_cpus	Set if there can be active threads inside the enclave.
+ *
+ * Mark the enclave as dead and immediately free its EPC pages (but not
+ * its resources).  For active enclaves, the entry points to the enclave
+ * are destroyed first and hardware threads are kicked out so that the
+ * EPC pages can be safely manipulated.
+ */
+void sgx_invalidate(struct sgx_encl *encl, bool flush_cpus)
+{
+	struct sgx_encl_page *entry;
+	struct radix_tree_iter iter;
+	struct vm_area_struct *vma;
+	unsigned long addr;
+	void **slot;
+
+	if (encl->flags & SGX_ENCL_DEAD)
+		return;
+
+	encl->flags |= SGX_ENCL_DEAD;
+	if (flush_cpus && (encl->flags & SGX_ENCL_INITIALIZED)) {
+		radix_tree_for_each_slot(slot, &encl->page_tree, &iter, 0) {
+			entry = *slot;
+			addr = SGX_ENCL_PAGE_ADDR(entry);
+			if ((entry->desc & SGX_ENCL_PAGE_LOADED) &&
+			    (entry->desc & SGX_ENCL_PAGE_TCS) &&
+			    !sgx_encl_find(encl->mm, addr, &vma))
+				zap_vma_ptes(vma, addr, PAGE_SIZE);
+		}
+		sgx_flush_cpus(encl);
+	}
+	radix_tree_for_each_slot(slot, &encl->page_tree, &iter, 0) {
+		entry = *slot;
+		if (entry->desc & SGX_ENCL_PAGE_LOADED) {
+			if (!__sgx_free_page(entry->epc_page)) {
+				encl->secs_child_cnt--;
+				entry->desc &= ~SGX_ENCL_PAGE_LOADED;
+			}
+		}
+	}
+
+	if (!encl->secs_child_cnt &&
+	    (encl->secs.desc & SGX_ENCL_PAGE_LOADED)) {
+		encl->secs.desc &= ~SGX_ENCL_PAGE_LOADED;
+		sgx_free_page(encl->secs.epc_page);
+	}
+}
+
+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;
+	struct sgx_secinfo secinfo;
+	struct sgx_pageinfo pginfo;
+	struct vm_area_struct *vma;
+	pgoff_t backing_index;
+	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);
+	ret = sgx_encl_find(encl->mm, addr, &vma);
+	if (ret)
+		return false;
+
+	backing_index = sgx_encl_page_backing_index(encl_page, encl);
+	backing = sgx_get_backing(encl->backing, backing_index);
+	if (IS_ERR(backing))
+		return false;
+
+	ret = vmf_insert_pfn(vma, addr, PFN_DOWN(epc_page->desc));
+	if (ret != VM_FAULT_NOPAGE) {
+		sgx_put_backing(backing, false);
+		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);
+
+	sgx_put_backing(backing, false);
+	if (ret) {
+		SGX_INVD(ret, encl, "EADD returned %d (0x%x)", ret, ret);
+		zap_vma_ptes(vma, addr, PAGE_SIZE);
+		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) {
+			SGX_INVD(ret, encl, "EEXTEND returned %d (0x%x)", ret, ret);
+			zap_vma_ptes(vma, addr, PAGE_SIZE);
+			return ret;
+		}
+	}
+
+	encl_page->encl = encl;
+	encl->secs_child_cnt++;
+	sgx_set_page_loaded(encl_page, epc_page);
+	sgx_test_and_clear_young(encl_page);
+	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, add_page_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();
+		down_read(&encl->mm->mmap_sem);
+		mutex_lock(&encl->lock);
+
+		if (IS_ERR(epc_page)) {
+			sgx_invalidate(encl, false);
+			skip_rest = true;
+		} else	if (!sgx_process_add_page_req(req, epc_page)) {
+			sgx_free_page(epc_page);
+			sgx_invalidate(encl, false);
+			skip_rest = true;
+		}
+
+		mutex_unlock(&encl->lock);
+		up_read(&encl->mm->mmap_sem);
+
+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->attributes & SGX_ATTR_RESERVED_MASK ||
+	    secs->miscselect & sgx_misc_reserved)
+		return -EINVAL;
+
+	if (secs->attributes & SGX_ATTR_MODE64BIT) {
+		if (secs->size > sgx_encl_size_max_64)
+			return -EINVAL;
+	} else {
+		/* On 64-bit architecture allow 32-bit encls only in
+		 * the compatibility mode.
+		 */
+		if (!test_thread_flag(TIF_ADDR32))
+			return -EINVAL;
+		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)) ||
+	    (secs->xfrm & ~sgx_xfrm_mask))
+		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 void sgx_mmu_notifier_release(struct mmu_notifier *mn,
+				     struct mm_struct *mm)
+{
+	struct sgx_encl *encl =
+		container_of(mn, struct sgx_encl, mmu_notifier);
+
+	mutex_lock(&encl->lock);
+	encl->flags |= SGX_ENCL_DEAD;
+	mutex_unlock(&encl->lock);
+}
+
+static const struct mmu_notifier_ops sgx_mmu_notifier_ops = {
+	.release	= sgx_mmu_notifier_release,
+};
+
+/**
+ * sgx_encl_alloc - allocate memory for an enclave and set attributes
+ *
+ * @secs:	SECS data (must be page aligned)
+ *
+ * Allocates a new &sgx_encl instance. Validates SECS attributes, creates
+ * backing storage for the enclave and sets enclave attributes to sane initial
+ * values.
+ *
+ * Return:
+ *   an &sgx_encl instance,
+ *   -errno otherwise
+ */
+struct sgx_encl *sgx_encl_alloc(struct sgx_secs *secs)
+{
+	unsigned long ssaframesize;
+	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("[dev/sgx]", secs->size + PAGE_SIZE,
+				   VM_NORESERVE);
+	if (IS_ERR(backing))
+		return ERR_CAST(backing);
+
+	encl = kzalloc(sizeof(*encl), GFP_KERNEL);
+	if (!encl) {
+		fput(backing);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	encl->attributes = secs->attributes;
+	encl->xfrm = secs->xfrm;
+
+	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->add_page_work, sgx_add_page_worker);
+
+	encl->mm = current->mm;
+	encl->base = secs->base;
+	encl->size = secs->size;
+	encl->ssaframesize = secs->ssa_frame_size;
+	encl->backing = backing;
+
+	return encl;
+}
+
+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_invalidate(encl, false);
+	encl->flags |= SGX_ENCL_SUSPEND;
+	mutex_unlock(&encl->lock);
+	flush_work(&encl->add_page_work);
+	return NOTIFY_DONE;
+}
+
+/**
+ * sgx_encl_create - create an enclave
+ *
+ * @encl:	an enclave
+ * @secs:	page aligned SECS data
+ *
+ * Validates SECS attributes, allocates an EPC page for the SECS and creates
+ * the enclave by performing ECREATE.
+ *
+ * Return:
+ *   0 on success,
+ *   -errno otherwise
+ */
+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;
+	}
+
+	sgx_set_page_loaded(&encl->secs, secs_epc);
+	encl->secs.encl = encl;
+	encl->tgid = get_pid(task_tgid(current));
+
+	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) {
+		sgx_dbg(encl, "ECREATE returned %ld\n", ret);
+		return ret;
+	}
+
+	if (secs->attributes & SGX_ATTR_DEBUG)
+		encl->flags |= SGX_ENCL_DEBUG;
+
+	encl->mmu_notifier.ops = &sgx_mmu_notifier_ops;
+	ret = mmu_notifier_register(&encl->mmu_notifier, encl->mm);
+	if (ret) {
+		if (ret == -EINTR)
+			ret = -ERESTARTSYS;
+		encl->mmu_notifier.ops = NULL;
+		return ret;
+	}
+
+	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(&current->mm->mmap_sem);
+	ret = sgx_encl_find(current->mm, secs->base, &vma);
+	if (ret != -ENOENT) {
+		if (!ret)
+			ret = -EINVAL;
+		up_read(&current->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(&current->mm->mmap_sem);
+		return ret;
+	}
+
+	vma->vm_private_data = encl;
+	up_read(&current->mm->mmap_sem);
+	return 0;
+}
+
+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_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)
+{
+	u64 page_type = secinfo->flags & SGX_SECINFO_PAGE_TYPE_MASK;
+	struct sgx_add_page_req *req = NULL;
+	pgoff_t backing_index;
+	struct page *backing;
+	void *backing_ptr;
+	int empty;
+
+	req = kzalloc(sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	backing_index = sgx_encl_page_backing_index(encl_page, encl);
+	backing = sgx_get_backing(encl->backing, backing_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_add_page_wq, &encl->add_page_work);
+	sgx_put_backing(backing, true /* write */);
+	return 0;
+}
+
+/**
+ * sgx_encl_alloc_page - allocate a new enclave page
+ * @encl:	an enclave
+ * @addr:	page address in the ELRANGE
+ *
+ * Return:
+ *   an &sgx_encl_page instance on success,
+ *   -errno otherwise
+ */
+struct sgx_encl_page *sgx_encl_alloc_page(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;
+}
+
+/**
+ * sgx_encl_free_page - free an enclave page
+ * @encl_page:	an enclave page
+ */
+void sgx_encl_free_page(struct sgx_encl_page *encl_page)
+{
+	radix_tree_delete(&encl_page->encl->page_tree,
+			  PFN_DOWN(encl_page->desc));
+	if (encl_page->desc & SGX_ENCL_PAGE_LOADED)
+		sgx_free_page(encl_page->epc_page);
+	kfree(encl_page);
+}
+
+/**
+ * sgx_encl_add_page - add a page to the enclave
+ *
+ * @encl:	an enclave
+ * @addr:	page address in the ELRANGE
+ * @data:	page data
+ * @secinfo:	page permissions
+ * @mrmask:	bitmask to select the 256 byte chunks to be measured
+ *
+ * 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
+ */
+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)) {
+		mutex_unlock(&encl->lock);
+		return -EINVAL;
+	}
+	encl_page = sgx_encl_alloc_page(encl, addr);
+	if (IS_ERR(encl_page)) {
+		mutex_unlock(&encl->lock);
+		return PTR_ERR(encl_page);
+	}
+	ret = __sgx_encl_add_page(encl, encl_page, data, secinfo, mrmask);
+	if (ret)
+		sgx_encl_free_page(encl_page);
+	mutex_unlock(&encl->lock);
+	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;
+}
+
+/**
+ * sgx_encl_init - perform EINIT for the given enclave
+ *
+ * @encl:	an enclave
+ * @sigstruct:	SIGSTRUCT for the enclave
+ * @token:	EINITTOKEN for the enclave
+ *
+ * Retries a few times in order to perform EINIT operation on an enclave
+ * because there could be potentially an interrupt storm.
+ *
+ * Return:
+ *   0 on success,
+ *   SGX error code on EINIT failure,
+ *   -errno otherwise
+ */
+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;
+
+	ret = sgx_get_key_hash(sigstruct->modulus, mrsigner);
+	if (ret)
+		return ret;
+
+	flush_work(&encl->add_page_work);
+
+	mutex_lock(&encl->lock);
+
+	if (encl->flags & SGX_ENCL_INITIALIZED) {
+		mutex_unlock(&encl->lock);
+		return 0;
+	}
+	if (encl->flags & SGX_ENCL_DEAD) {
+		mutex_unlock(&encl->lock);
+		return -EFAULT;
+	}
+
+	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)) {
+			mutex_unlock(&encl->lock);
+			return -ERESTARTSYS;
+		}
+	}
+
+	if (unlikely(IS_ENCLS_FAULT(ret)))
+		SGX_INVD(ret, encl, "EINIT returned %d (%x)", ret, ret);
+	else if (ret > 0)
+		sgx_dbg(encl, "EINIT returned %d\n", ret);
+	else if (!ret)
+		encl->flags |= SGX_ENCL_INITIALIZED;
+	mutex_unlock(&encl->lock);
+
+	return ret;
+}
+
+/**
+ * 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_page *entry;
+	struct radix_tree_iter iter;
+	void **slot;
+
+	if (encl->mmu_notifier.ops)
+		mmu_notifier_unregister(&encl->mmu_notifier, encl->mm);
+
+	if (encl->pm_notifier.notifier_call)
+		unregister_pm_notifier(&encl->pm_notifier);
+
+	radix_tree_for_each_slot(slot, &encl->page_tree, &iter, 0) {
+		entry = *slot;
+		sgx_encl_free_page(entry);
+	}
+
+	if (encl->tgid)
+		put_pid(encl->tgid);
+
+	if (encl->secs.desc & SGX_ENCL_PAGE_LOADED)
+		sgx_free_page(encl->secs.epc_page);
+
+	if (encl->backing)
+		fput(encl->backing);
+
+	kfree(encl);
+}
diff --git a/drivers/platform/x86/intel_sgx/sgx_ioctl.c b/drivers/platform/x86/intel_sgx/sgx_ioctl.c
new file mode 100644
index 000000000000..4edf1cc956b1
--- /dev/null
+++ b/drivers/platform/x86/intel_sgx/sgx_ioctl.c
@@ -0,0 +1,234 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+// Copyright(c) 2016-18 Intel Corporation.
+
+#include <asm/mman.h>
+#include <linux/delay.h>
+#include <linux/file.h>
+#include <linux/hashtable.h>
+#include <linux/highmem.h>
+#include <linux/ratelimit.h>
+#include <linux/sched/signal.h>
+#include <linux/slab.h>
+#include "sgx.h"
+
+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;
+}
+
+/**
+ * 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);
+	ret = copy_from_user(secs, (void __user *)createp->src, sizeof(*secs));
+	if (ret)
+		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;
+}
+
+/**
+ * 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);
+
+	ret = copy_from_user((void *)data, (void __user *)addp->src, PAGE_SIZE);
+	if (ret)
+		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;
+}
+
+/**
+ * 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. Does not
+ * allow the EINITTOKENKEY attribute for an enclave.
+ *
+ * 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));
+
+	ret = copy_from_user(sigstruct, (void __user *)initp->sigstruct,
+			     sizeof(*sigstruct));
+	if (ret)
+		goto out;
+	if (sigstruct->attributes & SGX_ATTR_EINITTOKENKEY) {
+		ret = EINVAL;
+		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;
+	}
+	if (IS_ENCLS_FAULT(ret))
+		return -EFAULT;
+	return ret;
+}
diff --git a/drivers/platform/x86/intel_sgx/sgx_main.c b/drivers/platform/x86/intel_sgx/sgx_main.c
new file mode 100644
index 000000000000..4312eab29775
--- /dev/null
+++ b/drivers/platform/x86/intel_sgx/sgx_main.c
@@ -0,0 +1,267 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+// Copyright(c) 2016-18 Intel Corporation.
+
+#include <linux/acpi.h>
+#include <linux/cdev.h>
+#include <linux/platform_device.h>
+#include <linux/suspend.h>
+#include <asm/traps.h>
+#include "sgx.h"
+
+MODULE_DESCRIPTION("Intel SGX Driver");
+MODULE_AUTHOR("Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>");
+MODULE_LICENSE("Dual BSD/GPL");
+
+struct workqueue_struct *sgx_add_page_wq;
+u64 sgx_encl_size_max_32;
+u64 sgx_encl_size_max_64;
+u64 sgx_xfrm_mask = 0x3;
+u32 sgx_misc_reserved;
+u32 sgx_xsave_size_tbl[64];
+int sgx_epcm_trapnr;
+
+#ifdef CONFIG_COMPAT
+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 |
+			 VM_DONTCOPY;
+
+	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)))
+		return -EINVAL;
+
+	if (len > sgx_encl_size_max_64)
+		return -EINVAL;
+
+	if (len > sgx_encl_size_max_32 && test_thread_flag(TIF_ADDR32))
+		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_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",
+};
+
+struct sgx_context {
+	struct device dev;
+	struct cdev cdev;
+};
+
+static dev_t sgx_devt;
+
+static void sgx_dev_release(struct device *dev)
+{
+	struct sgx_context *ctx = container_of(dev, struct sgx_context, dev);
+
+	kfree(ctx);
+}
+
+static struct sgx_context *sgx_ctx_alloc(struct device *parent)
+{
+	struct sgx_context *ctx;
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return ERR_PTR(-ENOMEM);
+
+	device_initialize(&ctx->dev);
+
+	ctx->dev.bus = &sgx_bus_type;
+	ctx->dev.parent = parent;
+	ctx->dev.devt = MKDEV(MAJOR(sgx_devt), 0);
+	ctx->dev.release = sgx_dev_release;
+
+	dev_set_name(&ctx->dev, "sgx");
+
+	cdev_init(&ctx->cdev, &sgx_fops);
+	ctx->cdev.owner = THIS_MODULE;
+
+	dev_set_drvdata(parent, ctx);
+
+	return ctx;
+}
+
+static struct sgx_context *sgxm_ctx_alloc(struct device *parent)
+{
+	struct sgx_context *ctx;
+	int rc;
+
+	ctx = sgx_ctx_alloc(parent);
+	if (IS_ERR(ctx))
+		return ctx;
+
+	rc = devm_add_action_or_reset(parent, (void (*)(void *))put_device,
+				      &ctx->dev);
+	if (rc) {
+		kfree(ctx);
+		return ERR_PTR(rc);
+	}
+
+	return ctx;
+}
+
+static int sgx_dev_init(struct device *parent)
+{
+	struct sgx_context *sgx_dev;
+	unsigned int eax;
+	unsigned int ebx;
+	unsigned int ecx;
+	unsigned int edx;
+	int ret;
+	int i;
+
+	sgx_dev = sgxm_ctx_alloc(parent);
+
+	cpuid_count(SGX_CPUID, 0, &eax, &ebx, &ecx, &edx);
+	/* Only allow misc bits supported by the driver. */
+	sgx_misc_reserved = ~ebx | SGX_MISC_RESERVED_MASK;
+	sgx_encl_size_max_64 = 1ULL << ((edx >> 8) & 0xFF);
+	sgx_encl_size_max_32 = 1ULL << (edx & 0xFF);
+
+	if (boot_cpu_has(X86_FEATURE_OSXSAVE)) {
+		cpuid_count(SGX_CPUID, 1, &eax, &ebx, &ecx, &edx);
+		sgx_xfrm_mask = (((u64)edx) << 32) + (u64)ecx;
+
+		for (i = 2; i < 64; i++) {
+			cpuid_count(0x0D, i, &eax, &ebx, &ecx, &edx);
+			if ((1 << i) & sgx_xfrm_mask)
+				sgx_xsave_size_tbl[i] = eax + ebx;
+		}
+	}
+
+	sgx_epcm_trapnr = boot_cpu_has(X86_FEATURE_SGX2) ? X86_TRAP_PF :
+							   X86_TRAP_GP;
+
+	sgx_add_page_wq = alloc_workqueue("intel_sgx-add-page-wq",
+					  WQ_UNBOUND | WQ_FREEZABLE, 1);
+	if (!sgx_add_page_wq)
+		return -ENOMEM;
+
+	ret = cdev_device_add(&sgx_dev->cdev, &sgx_dev->dev);
+	if (ret)
+		goto out_workqueue;
+
+	return 0;
+out_workqueue:
+	destroy_workqueue(sgx_add_page_wq);
+	return ret;
+}
+
+static int sgx_drv_probe(struct platform_device *pdev)
+{
+	if (!boot_cpu_has(X86_FEATURE_SGX))
+		return -ENODEV;
+
+	if (!boot_cpu_has(X86_FEATURE_SGX_LC)) {
+		pr_warn("sgx: IA32_SGXLEPUBKEYHASHx MSRs are not writable\n");
+		return -ENODEV;
+	}
+
+	return sgx_dev_init(&pdev->dev);
+}
+
+static int sgx_drv_remove(struct platform_device *pdev)
+{
+	struct sgx_context *ctx = dev_get_drvdata(&pdev->dev);
+
+	cdev_device_del(&ctx->cdev, &ctx->dev);
+	destroy_workqueue(sgx_add_page_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			= "intel_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, 1, "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, 1);
+}
+
+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/drivers/platform/x86/intel_sgx/sgx_util.c b/drivers/platform/x86/intel_sgx/sgx_util.c
new file mode 100644
index 000000000000..cbea4c0e794b
--- /dev/null
+++ b/drivers/platform/x86/intel_sgx/sgx_util.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+// Copyright(c) 2016-18 Intel Corporation.
+
+#include <linux/mm.h>
+#include <linux/shmem_fs.h>
+#include "sgx.h"
+
+static int sgx_test_and_clear_young_cb(pte_t *ptep, pgtable_t token,
+				       unsigned long addr, void *data)
+{
+	pte_t pte;
+	int ret;
+
+	ret = pte_young(*ptep);
+	if (ret) {
+		pte = pte_mkold(*ptep);
+		set_pte_at((struct mm_struct *)data, addr, ptep, pte);
+	}
+
+	return ret;
+}
+
+/**
+ * sgx_test_and_clear_young() - Test and reset the accessed bit
+ * @page:	enclave page to be tested for recent access
+ *
+ * Checks the Access (A) bit from the PTE corresponding to the
+ * enclave page and clears it.  Returns 1 if the page has been
+ * recently accessed and 0 if not.
+ */
+int sgx_test_and_clear_young(struct sgx_encl_page *page)
+{
+	unsigned long addr = SGX_ENCL_PAGE_ADDR(page);
+	struct sgx_encl *encl = page->encl;
+	struct vm_area_struct *vma;
+	int ret;
+
+	ret = sgx_encl_find(encl->mm, addr, &vma);
+	if (ret)
+		return 0;
+
+	if (encl != vma->vm_private_data)
+		return 0;
+
+	return apply_to_page_range(vma->vm_mm, addr, PAGE_SIZE,
+				   sgx_test_and_clear_young_cb, vma->vm_mm);
+}
+
+static void sgx_ipi_cb(void *info)
+{
+}
+
+void sgx_flush_cpus(struct sgx_encl *encl)
+{
+	on_each_cpu_mask(mm_cpumask(encl->mm), sgx_ipi_cb, NULL, 1);
+}
+
+/**
+ * sgx_set_page_loaded - associate an EPC page with an enclave page
+ * @encl_page:	an enclave page
+ * @epc_page:	the EPC page to attach to @encl_page
+ */
+void sgx_set_page_loaded(struct sgx_encl_page *encl_page,
+			 struct sgx_epc_page *epc_page)
+{
+	encl_page->desc |= SGX_ENCL_PAGE_LOADED;
+	encl_page->epc_page = epc_page;
+}
+
+struct page *sgx_get_backing(struct file *file, pgoff_t index)
+{
+	struct inode *inode = file->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);
+}
+
+void sgx_put_backing(struct page *backing_page, bool write)
+{
+	if (write)
+		set_page_dirty(backing_page);
+
+	put_page(backing_page);
+}
diff --git a/drivers/platform/x86/intel_sgx/sgx_vma.c b/drivers/platform/x86/intel_sgx/sgx_vma.c
new file mode 100644
index 000000000000..17e95a0c734c
--- /dev/null
+++ b/drivers/platform/x86/intel_sgx/sgx_vma.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+// Copyright(c) 2016-18 Intel Corporation.
+
+#include <asm/mman.h>
+#include <linux/delay.h>
+#include <linux/file.h>
+#include <linux/hashtable.h>
+#include <linux/highmem.h>
+#include <linux/mm.h>
+#include <linux/ratelimit.h>
+#include <linux/slab.h>
+#include "sgx.h"
+
+static void sgx_vma_open(struct vm_area_struct *vma)
+{
+	struct sgx_encl *encl = vma->vm_private_data;
+
+	if (!encl)
+		return;
+
+	/* kref cannot underflow because ECREATE ioctl checks that there is only
+	 * one single VMA for the enclave before proceeding.
+	 */
+	kref_get(&encl->refcount);
+}
+
+static void sgx_vma_close(struct vm_area_struct *vma)
+{
+	struct sgx_encl *encl = vma->vm_private_data;
+
+	if (!encl)
+		return;
+
+	mutex_lock(&encl->lock);
+	sgx_invalidate(encl, true);
+	mutex_unlock(&encl->lock);
+	kref_put(&encl->refcount, sgx_encl_release);
+}
+
+const struct vm_operations_struct sgx_vm_ops = {
+	.close = sgx_vma_close,
+	.open = sgx_vma_open,
+};
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 155+ messages in thread

* [PATCH v17 19/23] platform/x86: sgx: Add swapping functionality to the Intel SGX driver
       [not found] <20181116010412.23967-1-jarkko.sakkinen@linux.intel.com>
                   ` (17 preceding siblings ...)
  2018-11-16  1:01 ` [PATCH v17 18/23] platform/x86: Intel SGX driver Jarkko Sakkinen
@ 2018-11-16  1:01 ` Jarkko Sakkinen
  2018-11-16  1:01 ` [PATCH v17 20/23] x86/sgx: Add a simple swapper for the EPC memory manager Jarkko Sakkinen
                   ` (4 subsequent siblings)
  23 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-16  1:01 UTC (permalink / raw)
  To: x86, platform-driver-x86, linux-sgx
  Cc: dave.hansen, sean.j.christopherson, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Jarkko Sakkinen,
	Darren Hart, Andy Shevchenko, Suresh Siddha, open list

Because the kernel is untrusted, swapping pages in/out of the Enclave
Page Cache (EPC) has specialized requirements:

* The kernel cannot directly access EPC memory, i.e. cannot copy data
  to/from the EPC.
* To evict a page from the EPC, the kernel must "prove" to hardware that
  are no valid TLB entries for said page since a stale TLB entry would
  allow an attacker to bypass SGX access controls.
* When loading a page back into the EPC, hardware must be able to verify
  the integrity and freshness of the data.
* When loading an enclave page, e.g. regular pages and Thread Control
  Structures (TCS), hardware must be able to associate the page with a
  Secure Enclave Control Structure (SECS).

To satisfy the above requirements, the CPU provides dedicated ENCLS
functions to support paging data in/out of the EPC:

* EBLOCK:   Mark a page as blocked in the EPC Map (EPCM).  Attempting
            to access a blocked page that misses the TLB will fault.
* ETRACK:   Activate blocking tracking.  Hardware verifies that all
            translations for pages marked as "blocked" have been flushed
	    from the TLB.
* EPA:      Add version array page to the EPC.  As the name suggests, a
            VA page is an 512-entry array of version numbers that are
	    used to uniquely identify pages evicted from the EPC.
* EWB:      Write back a page from EPC to memory, e.g. RAM.  Software
            must supply a VA slot, memory to hold the a Paging Crypto
	    Metadata (PCMD) of the page and obviously backing for the
	    evicted page.
* ELD{B,U}: Load a page in {un}blocked state from memory to EPC.  The
            driver only uses the ELDU variant as there is no use case
	    for loading a page as "blocked" in a bare metal environment.

To top things off, all of the above ENCLS functions are subject to
strict concurrency rules, e.g. many operations will #GP fault if two
or more operations attempt to access common pages/structures.

To put it succinctly, paging in/out of the EPC requires coordinating
with the SGX driver where all of an enclave's tracking resides.  But,
simply shoving all reclaim logic into the driver is not desirable as
doing so has unwanted long term implications:

* Oversubscribing EPC to KVM guests, i.e. virtualizing SGX in KVM and
  swapping a guest's EPC pages (without the guest's cooperation) needs
  the same high level flows for reclaim but has painfully different
  semantics in the details.
* Accounting EPC, i.e. adding an EPC cgroup controller, is desirable
  as EPC is effectively a specialized memory type and even more scarce
  than system memory.  Providing a single touchpoint for EPC accounting
  regardless of end consumer greatly simplifies the EPC controller.
* Allowing the userspace-facing driver to be built as a loaded module
  is desirable, e.g. for debug, testing and development.  The cgroup
  infrastructure does not support dependencies on loadable modules.
* Separating EPC swapping from the driver once it has been tightly
  coupled to the driver is non-trivial (speaking from experience).

So, although the SGX driver is currently the sole consumer of EPC,
encapsulate EPC swapping in the driver to minimize the dependencies
between the core SGX code and driver, and do so in a way that can be
extended to an abstracted interface with minimal effort.

To that end, add functions to swap EPC pages to the driver.  The user
of these functions will be the core SGX subsystem, which will be enabled
in a future patch.

* sgx_encl_page_{get,put}() - Attempt to pin/unpin (the owner of) an EPC
  page so that it can be operated on by a reclaimer.
* sgx_encl_page_reclaim()   - Mark a page as being reclaimed. The
  page is considered reclaimable if it hasn't been accessed recently and
  it isn't reserved by the driver for other use.
* sgx_encl_page_block()     - EBLOCK an EPC page
* sgx_encl_page_write()     - Evict an EPC page to the regular memory via
  EWB.  Activates ETRACK (via sgx_encl_track()) if necessary.

Since we also need to be able to fault pages back into the EPC, add a
page fault handler to allocate an EPC page and ELDU a previously evicted
page.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Co-developed-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Co-developed-by: Serge Ayoun <serge.ayoun@intel.com>
Signed-off-by: Serge Ayoun <serge.ayoun@intel.com>
Co-developed-by: Shay Katz-zamir <shay.katz-zamir@intel.com>
Signed-off-by: Shay Katz-zamir <shay.katz-zamir@intel.com>
---
 drivers/platform/x86/intel_sgx/Makefile       |   2 +
 drivers/platform/x86/intel_sgx/sgx.h          |  32 +++
 drivers/platform/x86/intel_sgx/sgx_encl.c     | 194 +++++++++++++++++-
 .../platform/x86/intel_sgx/sgx_encl_page.c    | 179 ++++++++++++++++
 drivers/platform/x86/intel_sgx/sgx_fault.c    | 108 ++++++++++
 drivers/platform/x86/intel_sgx/sgx_util.c     |  71 +++++++
 drivers/platform/x86/intel_sgx/sgx_vma.c      |  15 ++
 7 files changed, 600 insertions(+), 1 deletion(-)
 create mode 100644 drivers/platform/x86/intel_sgx/sgx_encl_page.c
 create mode 100644 drivers/platform/x86/intel_sgx/sgx_fault.c

diff --git a/drivers/platform/x86/intel_sgx/Makefile b/drivers/platform/x86/intel_sgx/Makefile
index 117e97effeff..5023c5ebd57d 100644
--- a/drivers/platform/x86/intel_sgx/Makefile
+++ b/drivers/platform/x86/intel_sgx/Makefile
@@ -6,6 +6,8 @@ obj-$(CONFIG_INTEL_SGX) += intel_sgx.o
 
 intel_sgx-$(CONFIG_INTEL_SGX) += \
 	sgx_encl.o \
+	sgx_encl_page.o \
+	sgx_fault.o \
 	sgx_ioctl.o \
 	sgx_main.o \
 	sgx_util.o \
diff --git a/drivers/platform/x86/intel_sgx/sgx.h b/drivers/platform/x86/intel_sgx/sgx.h
index 67bd8ea1d53d..f707701e422d 100644
--- a/drivers/platform/x86/intel_sgx/sgx.h
+++ b/drivers/platform/x86/intel_sgx/sgx.h
@@ -36,16 +36,32 @@
 #define SGX_EINIT_SLEEP_COUNT	50
 #define SGX_EINIT_SLEEP_TIME	20
 
+#define SGX_VA_SLOT_COUNT 512
+
+struct sgx_va_page {
+	struct sgx_epc_page *epc_page;
+	DECLARE_BITMAP(slots, SGX_VA_SLOT_COUNT);
+	struct list_head list;
+};
+
 /**
  * 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_LOADED:		The page is not swapped.
+ * %SGX_ENCL_PAGE_RESERVED:		The page cannot be reclaimed.
+ * %SGX_ENCL_PAGE_RECLAIMED:		The page is in the process of being
+ *					reclaimed.
+ * %SGX_ENCL_PAGE_VA_OFFSET_MASK:	Holds the offset in the Version Array
+ *					(VA) page for a swapped page.
  * %SGX_ENCL_PAGE_ADDR_MASK:		Holds the virtual address of the page.
  */
 enum sgx_encl_page_desc {
 	SGX_ENCL_PAGE_TCS		= BIT(0),
 	SGX_ENCL_PAGE_LOADED		= BIT(1),
 	/* Bits 11:3 are available when the page is not swapped. */
+	SGX_ENCL_PAGE_RESERVED		= BIT(3),
+	SGX_ENCL_PAGE_RECLAIMED		= BIT(4),
+	SGX_ENCL_PAGE_VA_OFFSET_MASK	= GENMASK_ULL(11, 3),
 	SGX_ENCL_PAGE_ADDR_MASK		= PAGE_MASK,
 };
 
@@ -79,10 +95,12 @@ struct sgx_encl {
 	struct mutex lock;
 	struct mm_struct *mm;
 	struct file *backing;
+	struct file *pcmd;
 	struct kref refcount;
 	unsigned long base;
 	unsigned long size;
 	unsigned long ssaframesize;
+	struct list_head va_pages;
 	struct radix_tree_root page_tree;
 	struct list_head add_page_reqs;
 	struct work_struct add_page_work;
@@ -102,6 +120,16 @@ static inline pgoff_t sgx_encl_page_backing_index(struct sgx_encl_page *page,
 	return PFN_DOWN(page->desc - encl->base);
 }
 
+static inline int sgx_encl_page_pcmd_offset(struct sgx_encl_page *page,
+					    struct sgx_encl *encl)
+{
+	int index;
+
+	index = sgx_encl_page_backing_index(page, encl);
+	return (index & (PAGE_SIZE / sizeof(struct sgx_pcmd) - 1)) *
+	       sizeof(struct sgx_pcmd);
+}
+
 extern struct workqueue_struct *sgx_add_page_wq;
 extern u64 sgx_encl_size_max_32;
 extern u64 sgx_encl_size_max_64;
@@ -174,6 +202,10 @@ int sgx_test_and_clear_young(struct sgx_encl_page *page);
 void sgx_flush_cpus(struct sgx_encl *encl);
 void sgx_set_page_loaded(struct sgx_encl_page *encl_page,
 			 struct sgx_epc_page *epc_page);
+struct sgx_epc_page *sgx_alloc_va_page(void);
+unsigned int sgx_alloc_va_slot(struct sgx_va_page *va_page);
+void sgx_free_va_slot(struct sgx_va_page *va_page, unsigned int offset);
+bool sgx_va_page_full(struct sgx_va_page *va_page);
 struct page *sgx_get_backing(struct file *file, pgoff_t index);
 void sgx_put_backing(struct page *backing_page, bool write);
 
diff --git a/drivers/platform/x86/intel_sgx/sgx_encl.c b/drivers/platform/x86/intel_sgx/sgx_encl.c
index 6bed944c2f92..1d0a51120e3d 100644
--- a/drivers/platform/x86/intel_sgx/sgx_encl.c
+++ b/drivers/platform/x86/intel_sgx/sgx_encl.c
@@ -53,6 +53,19 @@ int sgx_encl_find(struct mm_struct *mm, unsigned long addr,
 	return encl ? 0 : -ENOENT;
 }
 
+static void sgx_free_va_pages(struct sgx_encl *encl)
+{
+	struct sgx_va_page *va_page;
+
+	while (!list_empty(&encl->va_pages)) {
+		va_page = list_first_entry(&encl->va_pages, struct sgx_va_page,
+					   list);
+		list_del(&va_page->list);
+		sgx_free_page(va_page->epc_page);
+		kfree(va_page);
+	}
+}
+
 /**
  * sgx_invalidate - kill an enclave
  * @encl:	an &sgx_encl instance
@@ -88,7 +101,12 @@ void sgx_invalidate(struct sgx_encl *encl, bool flush_cpus)
 	}
 	radix_tree_for_each_slot(slot, &encl->page_tree, &iter, 0) {
 		entry = *slot;
-		if (entry->desc & SGX_ENCL_PAGE_LOADED) {
+		/*
+		 * If the page has RECLAIMED set, the reclaimer effectively
+		 * owns the page, i.e. we need to let the reclaimer free it.
+		 */
+		if ((entry->desc & SGX_ENCL_PAGE_LOADED) &&
+		    !(entry->desc & SGX_ENCL_PAGE_RECLAIMED)) {
 			if (!__sgx_free_page(entry->epc_page)) {
 				encl->secs_child_cnt--;
 				entry->desc &= ~SGX_ENCL_PAGE_LOADED;
@@ -101,6 +119,7 @@ void sgx_invalidate(struct sgx_encl *encl, bool flush_cpus)
 		encl->secs.desc &= ~SGX_ENCL_PAGE_LOADED;
 		sgx_free_page(encl->secs.epc_page);
 	}
+	sgx_free_va_pages(encl);
 }
 
 static bool sgx_process_add_page_req(struct sgx_add_page_req *req,
@@ -303,6 +322,51 @@ static const struct mmu_notifier_ops sgx_mmu_notifier_ops = {
 	.release	= sgx_mmu_notifier_release,
 };
 
+static int sgx_encl_grow(struct sgx_encl *encl)
+{
+	struct sgx_va_page *va_page;
+	int ret;
+
+	BUILD_BUG_ON(SGX_VA_SLOT_COUNT !=
+		(SGX_ENCL_PAGE_VA_OFFSET_MASK >> 3) + 1);
+
+	mutex_lock(&encl->lock);
+	if (encl->flags & SGX_ENCL_DEAD) {
+		mutex_unlock(&encl->lock);
+		return -EFAULT;
+	}
+
+	if (!(encl->page_cnt % SGX_VA_SLOT_COUNT)) {
+		mutex_unlock(&encl->lock);
+
+		va_page = kzalloc(sizeof(*va_page), GFP_KERNEL);
+		if (!va_page)
+			return -ENOMEM;
+		va_page->epc_page = sgx_alloc_va_page();
+		if (IS_ERR(va_page->epc_page)) {
+			ret = PTR_ERR(va_page->epc_page);
+			kfree(va_page);
+			return ret;
+		}
+
+		mutex_lock(&encl->lock);
+		if (encl->flags & SGX_ENCL_DEAD) {
+			sgx_free_page(va_page->epc_page);
+			kfree(va_page);
+			mutex_unlock(&encl->lock);
+			return -EFAULT;
+		} else if (encl->page_cnt % SGX_VA_SLOT_COUNT) {
+			sgx_free_page(va_page->epc_page);
+			kfree(va_page);
+		} else {
+			list_add(&va_page->list, &encl->va_pages);
+		}
+	}
+	encl->page_cnt++;
+	mutex_unlock(&encl->lock);
+	return 0;
+}
+
 /**
  * sgx_encl_alloc - allocate memory for an enclave and set attributes
  *
@@ -321,6 +385,7 @@ struct sgx_encl *sgx_encl_alloc(struct sgx_secs *secs)
 	unsigned long ssaframesize;
 	struct sgx_encl *encl;
 	struct file *backing;
+	struct file *pcmd;
 
 	ssaframesize = sgx_calc_ssaframesize(secs->miscselect, secs->xfrm);
 	if (sgx_validate_secs(secs, ssaframesize))
@@ -331,9 +396,17 @@ struct sgx_encl *sgx_encl_alloc(struct sgx_secs *secs)
 	if (IS_ERR(backing))
 		return ERR_CAST(backing);
 
+	pcmd = shmem_file_setup("[dev/sgx]", (secs->size + PAGE_SIZE) >> 5,
+				VM_NORESERVE);
+	if (IS_ERR(pcmd)) {
+		fput(backing);
+		return ERR_CAST(pcmd);
+	}
+
 	encl = kzalloc(sizeof(*encl), GFP_KERNEL);
 	if (!encl) {
 		fput(backing);
+		fput(pcmd);
 		return ERR_PTR(-ENOMEM);
 	}
 
@@ -342,6 +415,7 @@ struct sgx_encl *sgx_encl_alloc(struct sgx_secs *secs)
 
 	kref_init(&encl->refcount);
 	INIT_LIST_HEAD(&encl->add_page_reqs);
+	INIT_LIST_HEAD(&encl->va_pages);
 	INIT_RADIX_TREE(&encl->page_tree, GFP_KERNEL);
 	mutex_init(&encl->lock);
 	INIT_WORK(&encl->add_page_work, sgx_add_page_worker);
@@ -351,6 +425,7 @@ struct sgx_encl *sgx_encl_alloc(struct sgx_secs *secs)
 	encl->size = secs->size;
 	encl->ssaframesize = secs->ssa_frame_size;
 	encl->backing = backing;
+	encl->pcmd = pcmd;
 
 	return encl;
 }
@@ -402,6 +477,10 @@ int sgx_encl_create(struct sgx_encl *encl, struct sgx_secs *secs)
 	encl->secs.encl = encl;
 	encl->tgid = get_pid(task_tgid(current));
 
+	ret = sgx_encl_grow(encl);
+	if (ret)
+		return ret;
+
 	pginfo.addr = 0;
 	pginfo.contents = (unsigned long)secs;
 	pginfo.metadata = (unsigned long)&secinfo;
@@ -632,6 +711,9 @@ int sgx_encl_add_page(struct sgx_encl *encl, unsigned long addr, void *data,
 		if (ret)
 			return ret;
 	}
+	ret = sgx_encl_grow(encl);
+	if (ret)
+		return ret;
 	mutex_lock(&encl->lock);
 	if (encl->flags & (SGX_ENCL_INITIALIZED | SGX_ENCL_DEAD)) {
 		mutex_unlock(&encl->lock);
@@ -746,6 +828,111 @@ int sgx_encl_init(struct sgx_encl *encl, struct sgx_sigstruct *sigstruct,
 	return ret;
 }
 
+/**
+ * sgx_encl_block - block an enclave page
+ * @encl_page:	an enclave page
+ *
+ * Changes the state of the associated EPC page to blocked.
+ */
+void sgx_encl_block(struct sgx_encl_page *encl_page)
+{
+	unsigned long addr = SGX_ENCL_PAGE_ADDR(encl_page);
+	struct sgx_encl *encl = encl_page->encl;
+	struct vm_area_struct *vma;
+	int ret;
+
+	if (encl->flags & SGX_ENCL_DEAD)
+		return;
+
+	ret = sgx_encl_find(encl->mm, addr, &vma);
+	if (!ret && encl == vma->vm_private_data)
+		zap_vma_ptes(vma, addr, PAGE_SIZE);
+
+	ret = __eblock(sgx_epc_addr(encl_page->epc_page));
+	SGX_INVD(ret, encl, "EBLOCK returned %d (0x%x)", ret, ret);
+}
+
+/**
+ * sgx_encl_track - start tracking pages in the blocked state
+ * @encl:	an enclave
+ *
+ * Start blocking accesses for pages in the blocked state for threads that enter
+ * inside the enclave by executing the ETRACK leaf instruction. This starts a
+ * shootdown sequence for threads that entered before ETRACK.
+ *
+ * The caller must take care (with an IPI when necessary) to make sure that the
+ * previous shootdown sequence was completed before calling this function.  If
+ * this is not the case, the callee prints a critical error to the klog and
+ * kills the enclave.
+ */
+void sgx_encl_track(struct sgx_encl *encl)
+{
+	int ret = __etrack(sgx_epc_addr(encl->secs.epc_page));
+
+	SGX_INVD(ret, encl, "ETRACK returned %d (0x%x)", ret, ret);
+}
+
+/**
+ * sgx_encl_load_page - load an enclave page
+ * @encl_page:	an enclave page
+ * @epc_page:	an EPC page
+ *
+ * Loads an enclave page from the regular memory to the EPC. The pages, which
+ * are not children of a SECS (eg SECS itself and VA pages) should set their
+ * address to zero.
+ *
+ * Return:
+ *   0 on success,
+ *   -errno or SGX error code on failure
+ */
+int sgx_encl_load_page(struct sgx_encl_page *encl_page,
+		       struct sgx_epc_page *epc_page)
+{
+	unsigned long addr = SGX_ENCL_PAGE_ADDR(encl_page);
+	struct sgx_encl *encl = encl_page->encl;
+	struct sgx_pageinfo pginfo;
+	unsigned long pcmd_offset;
+	unsigned long va_offset;
+	pgoff_t backing_index;
+	struct page *backing;
+	struct page *pcmd;
+	int ret;
+
+	backing_index = sgx_encl_page_backing_index(encl_page, encl);
+	pcmd_offset = sgx_encl_page_pcmd_offset(encl_page, encl);
+	va_offset = SGX_ENCL_PAGE_VA_OFFSET(encl_page);
+
+	backing = sgx_get_backing(encl->backing, backing_index);
+	if (IS_ERR(backing))
+		return PTR_ERR(backing);
+
+	pcmd = sgx_get_backing(encl->pcmd, backing_index >> 5);
+	if (IS_ERR(pcmd)) {
+		sgx_put_backing(backing, false);
+		return PTR_ERR(pcmd);
+	}
+
+	pginfo.addr = addr;
+	pginfo.contents = (unsigned long)kmap_atomic(backing);
+	pginfo.metadata = (unsigned long)kmap_atomic(pcmd) + pcmd_offset;
+	pginfo.secs = addr ? (unsigned long)sgx_epc_addr(encl->secs.epc_page) :
+		      0;
+
+	ret = __eldu(&pginfo, sgx_epc_addr(epc_page),
+		     sgx_epc_addr(encl_page->va_page->epc_page) + va_offset);
+	if (ret) {
+		SGX_INVD(ret, encl, "ELDU returned %d (0x%x)", ret, ret);
+		ret = encls_to_err(ret);
+	}
+
+	kunmap_atomic((void *)(unsigned long)(pginfo.metadata - pcmd_offset));
+	kunmap_atomic((void *)(unsigned long)pginfo.contents);
+
+	sgx_put_backing(pcmd, false);
+	sgx_put_backing(backing, false);
+	return ret;
+}
+
 /**
  * sgx_encl_release - destroy an enclave instance
  * @kref:	address of a kref inside &sgx_encl
@@ -774,11 +961,16 @@ void sgx_encl_release(struct kref *ref)
 	if (encl->tgid)
 		put_pid(encl->tgid);
 
+	sgx_free_va_pages(encl);
+
 	if (encl->secs.desc & SGX_ENCL_PAGE_LOADED)
 		sgx_free_page(encl->secs.epc_page);
 
 	if (encl->backing)
 		fput(encl->backing);
 
+	if (encl->pcmd)
+		fput(encl->pcmd);
+
 	kfree(encl);
 }
diff --git a/drivers/platform/x86/intel_sgx/sgx_encl_page.c b/drivers/platform/x86/intel_sgx/sgx_encl_page.c
new file mode 100644
index 000000000000..fc9bea9f4aea
--- /dev/null
+++ b/drivers/platform/x86/intel_sgx/sgx_encl_page.c
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+// Copyright(c) 2016-18 Intel Corporation.
+
+#include <linux/device.h>
+#include <linux/freezer.h>
+#include <linux/highmem.h>
+#include <linux/kthread.h>
+#include <linux/ratelimit.h>
+#include <linux/sched/signal.h>
+#include <linux/slab.h>
+#include "sgx.h"
+
+static inline struct sgx_encl_page *to_encl_page(struct sgx_epc_page *epc_page)
+{
+	WARN_ON_ONCE(1);
+	return NULL;
+}
+
+bool sgx_encl_page_get(struct sgx_epc_page *epc_page)
+{
+	struct sgx_encl_page *encl_page = to_encl_page(epc_page);
+	struct sgx_encl *encl = encl_page->encl;
+
+	return kref_get_unless_zero(&encl->refcount) != 0;
+}
+
+void sgx_encl_page_put(struct sgx_epc_page *epc_page)
+{
+	struct sgx_encl_page *encl_page = to_encl_page(epc_page);
+	struct sgx_encl *encl = encl_page->encl;
+
+	kref_put(&encl->refcount, sgx_encl_release);
+}
+
+bool sgx_encl_page_reclaim(struct sgx_epc_page *epc_page)
+{
+	struct sgx_encl_page *encl_page = to_encl_page(epc_page);
+	struct sgx_encl *encl = encl_page->encl;
+	bool ret;
+
+	down_read(&encl->mm->mmap_sem);
+	mutex_lock(&encl->lock);
+
+	if (encl->flags & SGX_ENCL_DEAD)
+		ret = true;
+	else if (encl_page->desc & SGX_ENCL_PAGE_RESERVED)
+		ret = false;
+	else
+		ret = !sgx_test_and_clear_young(encl_page);
+	if (ret)
+		encl_page->desc |= SGX_ENCL_PAGE_RECLAIMED;
+
+	mutex_unlock(&encl->lock);
+	up_read(&encl->mm->mmap_sem);
+
+	return ret;
+}
+
+void sgx_encl_page_block(struct sgx_epc_page *epc_page)
+{
+	struct sgx_encl_page *encl_page = to_encl_page(epc_page);
+	struct sgx_encl *encl = encl_page->encl;
+
+	down_read(&encl->mm->mmap_sem);
+	mutex_lock(&encl->lock);
+	sgx_encl_block(encl_page);
+	mutex_unlock(&encl->lock);
+	up_read(&encl->mm->mmap_sem);
+}
+
+static int sgx_ewb(struct sgx_encl *encl, struct sgx_epc_page *epc_page,
+		   struct sgx_va_page *va_page, unsigned int va_offset)
+{
+	struct sgx_encl_page *encl_page = to_encl_page(epc_page);
+	int pcmd_offset = sgx_encl_page_pcmd_offset(encl_page, encl);
+	struct sgx_pageinfo pginfo;
+	pgoff_t backing_index;
+	struct page *backing;
+	struct page *pcmd;
+	int ret;
+
+	backing_index = sgx_encl_page_backing_index(encl_page, encl);
+
+	backing = sgx_get_backing(encl->backing, backing_index);
+	if (IS_ERR(backing)) {
+		ret = PTR_ERR(backing);
+		return ret;
+	}
+
+	pcmd = sgx_get_backing(encl->pcmd, backing_index >> 5);
+	if (IS_ERR(pcmd)) {
+		ret = PTR_ERR(pcmd);
+		sgx_put_backing(backing, true);
+		return ret;
+	}
+
+	pginfo.addr = 0;
+	pginfo.contents = (unsigned long)kmap_atomic(backing);
+	pginfo.metadata = (unsigned long)kmap_atomic(pcmd) + pcmd_offset;
+	pginfo.secs = 0;
+	ret = __ewb(&pginfo, sgx_epc_addr(epc_page),
+		    sgx_epc_addr(va_page->epc_page) + va_offset);
+	kunmap_atomic((void *)(unsigned long)(pginfo.metadata - pcmd_offset));
+	kunmap_atomic((void *)(unsigned long)pginfo.contents);
+
+	sgx_put_backing(pcmd, true);
+	sgx_put_backing(backing, true);
+
+	return ret;
+}
+
+/**
+ * sgx_write_page - write a page to the regular memory
+ *
+ * Writes an EPC page to the shmem file associated with the enclave. Flushes
+ * CPUs and retries if there are hardware threads that can potentially have TLB
+ * entries to the page (indicated by SGX_NOT_TRACKED). Clears the reserved flag
+ * after the page is swapped.
+ *
+ * @epc_page:	an EPC page
+ */
+static void sgx_write_page(struct sgx_epc_page *epc_page, bool do_free)
+{
+	struct sgx_encl_page *encl_page = to_encl_page(epc_page);
+	struct sgx_encl *encl = encl_page->encl;
+	struct sgx_va_page *va_page;
+	unsigned int va_offset;
+	int ret;
+
+	encl_page->desc &= ~(SGX_ENCL_PAGE_LOADED | SGX_ENCL_PAGE_RECLAIMED);
+
+	if (!(encl->flags & SGX_ENCL_DEAD)) {
+		va_page = list_first_entry(&encl->va_pages, struct sgx_va_page,
+					   list);
+		va_offset = sgx_alloc_va_slot(va_page);
+		if (sgx_va_page_full(va_page))
+			list_move_tail(&va_page->list, &encl->va_pages);
+
+		ret = sgx_ewb(encl, epc_page, va_page, va_offset);
+		if (ret == SGX_NOT_TRACKED) {
+			sgx_encl_track(encl);
+			ret = sgx_ewb(encl, epc_page, va_page, va_offset);
+			if (ret == SGX_NOT_TRACKED) {
+				/* slow path, IPI needed */
+				sgx_flush_cpus(encl);
+				ret = sgx_ewb(encl, epc_page, va_page,
+					      va_offset);
+			}
+		}
+		SGX_INVD(ret, encl, "EWB returned %d (0x%x)", ret, ret);
+
+		SGX_INVD(encl_page->desc & SGX_ENCL_PAGE_VA_OFFSET_MASK, encl,
+			"Flags set in VA offset area: %lx", encl_page->desc);
+		encl_page->desc |= va_offset;
+		encl_page->va_page = va_page;
+	} else if (!do_free) {
+		ret = __eremove(sgx_epc_addr(epc_page));
+		WARN(ret, "EREMOVE returned %d\n", ret);
+	}
+
+	if (do_free)
+		sgx_free_page(epc_page);
+}
+
+void sgx_encl_page_write(struct sgx_epc_page *epc_page)
+{
+	struct sgx_encl_page *encl_page = to_encl_page(epc_page);
+	struct sgx_encl *encl = encl_page->encl;
+
+	down_read(&encl->mm->mmap_sem);
+	mutex_lock(&encl->lock);
+	sgx_write_page(epc_page, false);
+	encl->secs_child_cnt--;
+	if (!encl->secs_child_cnt &&
+	    (encl->flags & (SGX_ENCL_INITIALIZED | SGX_ENCL_DEAD)))
+		sgx_write_page(encl->secs.epc_page, true);
+	mutex_unlock(&encl->lock);
+	up_read(&encl->mm->mmap_sem);
+}
diff --git a/drivers/platform/x86/intel_sgx/sgx_fault.c b/drivers/platform/x86/intel_sgx/sgx_fault.c
new file mode 100644
index 000000000000..61d77e9f8fec
--- /dev/null
+++ b/drivers/platform/x86/intel_sgx/sgx_fault.c
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+// Copyright(c) 2016-18 Intel Corporation.
+
+#include <linux/highmem.h>
+#include <linux/sched/mm.h>
+#include "sgx.h"
+
+static struct sgx_epc_page *__sgx_load_faulted_page(
+	struct sgx_encl_page *encl_page)
+{
+	unsigned long va_offset = SGX_ENCL_PAGE_VA_OFFSET(encl_page);
+	struct sgx_encl *encl = encl_page->encl;
+	struct sgx_epc_page *epc_page;
+	int ret;
+
+	epc_page = sgx_alloc_page();
+	if (IS_ERR(epc_page))
+		return epc_page;
+	ret = sgx_encl_load_page(encl_page, epc_page);
+	if (ret) {
+		sgx_free_page(epc_page);
+		return ERR_PTR(ret);
+	}
+	sgx_free_va_slot(encl_page->va_page, va_offset);
+	list_move(&encl_page->va_page->list, &encl->va_pages);
+	encl_page->desc &= ~SGX_ENCL_PAGE_VA_OFFSET_MASK;
+	sgx_set_page_loaded(encl_page, epc_page);
+	return epc_page;
+}
+
+static struct sgx_encl_page *__sgx_fault_page(struct vm_area_struct *vma,
+					      unsigned long addr,
+					      bool do_reserve)
+{
+	struct sgx_encl *encl = vma->vm_private_data;
+	struct sgx_epc_page *epc_page;
+	struct sgx_encl_page *entry;
+	int rc = 0;
+
+	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->desc & SGX_ENCL_PAGE_LOADED) {
+		if (entry->desc & SGX_ENCL_PAGE_RESERVED) {
+			sgx_dbg(encl, "EPC page 0x%p is already reserved\n",
+				(void *)SGX_ENCL_PAGE_ADDR(entry));
+			return ERR_PTR(-EBUSY);
+		}
+		if (entry->desc & SGX_ENCL_PAGE_RECLAIMED) {
+			sgx_dbg(encl, "EPC page 0x%p is being reclaimed\n",
+				(void *)SGX_ENCL_PAGE_ADDR(entry));
+			return ERR_PTR(-EBUSY);
+		}
+		if (do_reserve)
+			entry->desc |= SGX_ENCL_PAGE_RESERVED;
+		return entry;
+	}
+
+	if (!(encl->secs.desc & SGX_ENCL_PAGE_LOADED)) {
+		epc_page = __sgx_load_faulted_page(&encl->secs);
+		if (IS_ERR(epc_page))
+			return ERR_CAST(epc_page);
+	}
+	epc_page = __sgx_load_faulted_page(entry);
+	if (IS_ERR(epc_page))
+		return ERR_CAST(epc_page);
+
+	encl->secs_child_cnt++;
+	sgx_test_and_clear_young(entry);
+	if (do_reserve)
+		entry->desc |= SGX_ENCL_PAGE_RESERVED;
+
+	rc = vmf_insert_pfn(vma, addr, PFN_DOWN(entry->epc_page->desc));
+	if (rc != VM_FAULT_NOPAGE) {
+		sgx_invalidate(encl, true);
+		return ERR_PTR(-EFAULT);
+	}
+
+	return entry;
+}
+
+struct sgx_encl_page *sgx_fault_page(struct vm_area_struct *vma,
+				     unsigned long addr, bool do_reserve)
+{
+	struct sgx_encl *encl = vma->vm_private_data;
+	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);
+	do {
+		mutex_lock(&encl->lock);
+		entry = __sgx_fault_page(vma, addr, do_reserve);
+		mutex_unlock(&encl->lock);
+		if (!do_reserve)
+			break;
+	} while (PTR_ERR(entry) == -EBUSY);
+
+	return entry;
+}
diff --git a/drivers/platform/x86/intel_sgx/sgx_util.c b/drivers/platform/x86/intel_sgx/sgx_util.c
index cbea4c0e794b..eb8072b36a47 100644
--- a/drivers/platform/x86/intel_sgx/sgx_util.c
+++ b/drivers/platform/x86/intel_sgx/sgx_util.c
@@ -67,6 +67,77 @@ void sgx_set_page_loaded(struct sgx_encl_page *encl_page,
 	encl_page->epc_page = epc_page;
 }
 
+/**
+ * sgx_alloc_page - allocate a VA page
+ *
+ * Allocates an &sgx_epc_page instance and converts it to a VA page.
+ *
+ * Return:
+ *   a &struct sgx_va_page instance,
+ *   -errno otherwise
+ */
+struct sgx_epc_page *sgx_alloc_va_page(void)
+{
+	struct sgx_epc_page *epc_page;
+	int ret;
+
+	epc_page = sgx_alloc_page();
+	if (IS_ERR(epc_page))
+		return ERR_CAST(epc_page);
+
+	ret = __epa(sgx_epc_addr(epc_page));
+	if (ret) {
+		WARN_ONCE(1, "sgx: EPA returned %d (0x%x)", ret, ret);
+		sgx_free_page(epc_page);
+		return ERR_PTR(encls_to_err(ret));
+	}
+
+	return epc_page;
+}
+
+/**
+ * sgx_alloc_va_slot - allocate a VA slot
+ * @va_page:	a &struct sgx_va_page instance
+ *
+ * Allocates a slot from a &struct sgx_va_page instance.
+ *
+ * Return: offset of the slot inside the VA page
+ */
+unsigned int sgx_alloc_va_slot(struct sgx_va_page *va_page)
+{
+	int slot = find_first_zero_bit(va_page->slots, SGX_VA_SLOT_COUNT);
+
+	if (slot < SGX_VA_SLOT_COUNT)
+		set_bit(slot, va_page->slots);
+
+	return slot << 3;
+}
+
+/**
+ * sgx_free_va_slot - free a VA slot
+ * @va_page:	a &struct sgx_va_page instance
+ * @offset:	offset of the slot inside the VA page
+ *
+ * Frees a slot from a &struct sgx_va_page instance.
+ */
+void sgx_free_va_slot(struct sgx_va_page *va_page, unsigned int offset)
+{
+	clear_bit(offset >> 3, va_page->slots);
+}
+
+/**
+ * sgx_va_page_full - is the VA page full?
+ * @va_page:	a &struct sgx_va_page instance
+ *
+ * Return: true if all slots have been taken
+ */
+bool sgx_va_page_full(struct sgx_va_page *va_page)
+{
+	int slot = find_first_zero_bit(va_page->slots, SGX_VA_SLOT_COUNT);
+
+	return slot == SGX_VA_SLOT_COUNT;
+}
+
 struct page *sgx_get_backing(struct file *file, pgoff_t index)
 {
 	struct inode *inode = file->f_path.dentry->d_inode;
diff --git a/drivers/platform/x86/intel_sgx/sgx_vma.c b/drivers/platform/x86/intel_sgx/sgx_vma.c
index 17e95a0c734c..cc0993b4fd40 100644
--- a/drivers/platform/x86/intel_sgx/sgx_vma.c
+++ b/drivers/platform/x86/intel_sgx/sgx_vma.c
@@ -37,7 +37,22 @@ static void sgx_vma_close(struct vm_area_struct *vma)
 	kref_put(&encl->refcount, sgx_encl_release);
 }
 
+static 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_page *entry;
+
+	entry = sgx_fault_page(vma, addr, 0);
+
+	if (!IS_ERR(entry) || PTR_ERR(entry) == -EBUSY)
+		return VM_FAULT_NOPAGE;
+	else
+		return VM_FAULT_SIGBUS;
+}
+
 const struct vm_operations_struct sgx_vm_ops = {
 	.close = sgx_vma_close,
 	.open = sgx_vma_open,
+	.fault = sgx_vma_fault,
 };
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 155+ messages in thread

* [PATCH v17 20/23] x86/sgx: Add a simple swapper for the EPC memory manager
       [not found] <20181116010412.23967-1-jarkko.sakkinen@linux.intel.com>
                   ` (18 preceding siblings ...)
  2018-11-16  1:01 ` [PATCH v17 19/23] platform/x86: sgx: Add swapping functionality to the " Jarkko Sakkinen
@ 2018-11-16  1:01 ` Jarkko Sakkinen
  2018-11-16  1:01 ` [PATCH v17 21/23] platform/x86: ptrace() support for the SGX driver Jarkko Sakkinen
                   ` (3 subsequent siblings)
  23 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-16  1:01 UTC (permalink / raw)
  To: x86, platform-driver-x86, linux-sgx
  Cc: dave.hansen, sean.j.christopherson, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Jarkko Sakkinen,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin, Darren Hart,
	Andy Shevchenko, Suresh Siddha,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

Wire up the EPC manager's reclaim flow to the SGX driver's swapping
functionality.  In the long term there will be multiple users of the
EPC manager, e.g. SGX driver and KVM, thus the interface between the
EPC manager and the driver is fairly genericized and decoupled.  But
to avoid adding unusued infrastructure, do not add any indirection
between the EPC manager and the SGX driver.  This has the unfortunate
and odd side effect of preventing the SGX driver from being compiled
as a loadable module.  However, this should be a temporary situation
that is remedied when a second user of EPC is added, i.e. KVM.

The swapper thread ksgxswapd reclaims pages on the event when the number
of free EPC pages goes below %SGX_NR_LOW_PAGES up until it reaches
%SGX_NR_HIGH_PAGES.

Pages are reclaimed in LRU fashion from a global list. The consumers
take care of calling EBLOCK (block page from new accesses), ETRACK
(restart counting the entering hardware threads) and EWB (write page to
the regular memory) because executing these operations usually (if not
always) requires to do some subsystem-internal locking operations.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Co-developed-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Co-developed-by: Serge Ayoun <serge.ayoun@intel.com>
Signed-off-by: Serge Ayoun <serge.ayoun@intel.com>
Co-developed-by: Shay Katz-zamir <shay.katz-zamir@intel.com>
Signed-off-by: Shay Katz-zamir <shay.katz-zamir@intel.com>
---
 arch/x86/Kconfig                              |   1 +
 arch/x86/include/asm/sgx.h                    |  10 +-
 arch/x86/kernel/cpu/intel_sgx.c               | 241 +++++++++++++++++-
 drivers/platform/x86/intel_sgx/sgx_encl.c     |   5 +-
 .../platform/x86/intel_sgx/sgx_encl_page.c    |   3 +-
 drivers/platform/x86/intel_sgx/sgx_fault.c    |   3 +-
 drivers/platform/x86/intel_sgx/sgx_util.c     |   2 +-
 7 files changed, 245 insertions(+), 20 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 4c3a325351ce..5d38e30d9563 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1922,6 +1922,7 @@ config X86_INTEL_MEMORY_PROTECTION_KEYS
 config INTEL_SGX_CORE
 	bool "Intel SGX core functionality"
 	depends on X86_64 && CPU_SUP_INTEL
+	select INTEL_SGX
 	help
 	Intel Software Guard eXtensions (SGX) CPU feature that allows ring 3
 	applications to create enclaves: private regions of memory that are
diff --git a/arch/x86/include/asm/sgx.h b/arch/x86/include/asm/sgx.h
index 4cdfa1d22c6e..afe1291a17d5 100644
--- a/arch/x86/include/asm/sgx.h
+++ b/arch/x86/include/asm/sgx.h
@@ -12,6 +12,7 @@
 
 struct sgx_epc_page {
 	unsigned long desc;
+	void *owner;
 	struct list_head list;
 };
 
@@ -307,10 +308,17 @@ static inline int __emodt(struct sgx_secinfo *secinfo, void *addr)
 	return __encls_ret_2(SGX_EMODT, secinfo, addr);
 }
 
-struct sgx_epc_page *sgx_alloc_page(void);
+struct sgx_epc_page *sgx_alloc_page(void *owner, bool reclaim);
 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);
+void sgx_page_reclaimable(struct sgx_epc_page *page);
+
+bool sgx_encl_page_get(struct sgx_epc_page *epc_page);
+void sgx_encl_page_put(struct sgx_epc_page *epc_page);
+bool sgx_encl_page_reclaim(struct sgx_epc_page *epc_page);
+void sgx_encl_page_block(struct sgx_epc_page *epc_page);
+void sgx_encl_page_write(struct sgx_epc_page *epc_page);
 
 #endif /* _ASM_X86_SGX_H */
diff --git a/arch/x86/kernel/cpu/intel_sgx.c b/arch/x86/kernel/cpu/intel_sgx.c
index 0e5fc8fc6b0d..929192d9557e 100644
--- a/arch/x86/kernel/cpu/intel_sgx.c
+++ b/arch/x86/kernel/cpu/intel_sgx.c
@@ -10,24 +10,141 @@
 #include <linux/slab.h>
 #include <asm/sgx.h>
 
+/**
+ * enum sgx_swap_constants - the constants used by the swapping code
+ * %SGX_NR_TO_SCAN:	the number of pages to scan in a single round
+ * %SGX_NR_LOW_PAGES:	the low watermark for ksgxswapd when it starts to swap
+ *			pages.
+ * %SGX_NR_HIGH_PAGES:	the high watermark for ksgxswapd what it stops swapping
+ *			pages.
+ */
+enum sgx_swap_constants {
+	SGX_NR_TO_SCAN		= 16,
+	SGX_NR_LOW_PAGES	= 32,
+	SGX_NR_HIGH_PAGES	= 64,
+};
+
 struct sgx_epc_section sgx_epc_sections[SGX_MAX_EPC_SECTIONS];
 EXPORT_SYMBOL_GPL(sgx_epc_sections);
 
 static int sgx_nr_epc_sections;
+static LIST_HEAD(sgx_active_page_list);
+static DEFINE_SPINLOCK(sgx_active_page_list_lock);
+static struct task_struct *ksgxswapd_tsk;
+static DECLARE_WAIT_QUEUE_HEAD(ksgxswapd_waitq);
 
 /* A per-cpu cache for the last known values of IA32_SGXLEPUBKEYHASHx MSRs. */
 static DEFINE_PER_CPU(u64 [4], sgx_lepubkeyhash_cache);
 
 /**
- * sgx_alloc_page - Allocate an EPC page
- *
- * Try to grab a page from the free EPC page list.
+ * sgx_reclaim_pages - reclaim EPC pages from the consumers
  *
- * Return:
- *   a pointer to a &struct sgx_epc_page instance,
- *   -errno on error
+ * Takes a fixed chunk of pages from the global list of consumed EPC pages and
+ * tries to swap them. Only the pages that are either being freed by the
+ * consumer or actively used are skipped.
  */
-struct sgx_epc_page *sgx_alloc_page(void)
+static void sgx_reclaim_pages(void)
+{
+	struct sgx_epc_page *chunk[SGX_NR_TO_SCAN + 1];
+	struct sgx_epc_page *epc_page;
+	struct sgx_epc_section *section;
+	int i, j;
+
+	spin_lock(&sgx_active_page_list_lock);
+	for (i = 0, j = 0; i < SGX_NR_TO_SCAN; i++) {
+		if (list_empty(&sgx_active_page_list))
+			break;
+
+		epc_page = list_first_entry(&sgx_active_page_list,
+					    struct sgx_epc_page, list);
+		list_del_init(&epc_page->list);
+
+		if (sgx_encl_page_get(epc_page))
+			chunk[j++] = epc_page;
+		else
+			/* The owner is freeing the page. No need to add the
+			 * page back to the list of reclaimable pages.
+			 */
+			epc_page->desc &= ~SGX_EPC_PAGE_RECLAIMABLE;
+	}
+	spin_unlock(&sgx_active_page_list_lock);
+
+	for (i = 0; i < j; i++) {
+		epc_page = chunk[i];
+		if (sgx_encl_page_reclaim(epc_page))
+			continue;
+
+		sgx_encl_page_put(epc_page);
+
+		spin_lock(&sgx_active_page_list_lock);
+		list_add_tail(&epc_page->list, &sgx_active_page_list);
+		spin_unlock(&sgx_active_page_list_lock);
+
+		chunk[i] = NULL;
+	}
+
+	for (i = 0; i < j; i++) {
+		epc_page = chunk[i];
+		if (epc_page)
+			sgx_encl_page_block(epc_page);
+	}
+
+	for (i = 0; i < j; i++) {
+		epc_page = chunk[i];
+		if (epc_page) {
+			sgx_encl_page_write(epc_page);
+			sgx_encl_page_put(epc_page);
+			epc_page->desc &= ~SGX_EPC_PAGE_RECLAIMABLE;
+
+			section = sgx_epc_section(epc_page);
+			spin_lock(&section->lock);
+			section->pages[section->free_cnt++] = epc_page;
+			spin_unlock(&section->lock);
+		}
+	}
+}
+
+static unsigned long sgx_calc_free_cnt(void)
+{
+	struct sgx_epc_section *section;
+	unsigned long free_cnt = 0;
+	int i;
+
+	for (i = 0; i < sgx_nr_epc_sections; i++) {
+		section = &sgx_epc_sections[i];
+		free_cnt += section->free_cnt;
+	}
+
+	return free_cnt;
+}
+
+static inline bool sgx_should_reclaim(void)
+{
+	return sgx_calc_free_cnt() < SGX_NR_HIGH_PAGES &&
+	       !list_empty(&sgx_active_page_list);
+}
+
+static int ksgxswapd(void *p)
+{
+	set_freezable();
+
+	while (!kthread_should_stop()) {
+		if (try_to_freeze())
+			continue;
+
+		wait_event_freezable(ksgxswapd_waitq, kthread_should_stop() ||
+						      sgx_should_reclaim());
+
+		if (sgx_should_reclaim())
+			sgx_reclaim_pages();
+
+		cond_resched();
+	}
+
+	return 0;
+}
+
+static struct sgx_epc_page *sgx_try_alloc_page(void *owner)
 {
 	struct sgx_epc_section *section;
 	struct sgx_epc_page *page;
@@ -42,11 +159,58 @@ struct sgx_epc_page *sgx_alloc_page(void)
 		}
 		spin_unlock(&section->lock);
 
-		if (page)
+		if (page) {
+			page->owner = owner;
 			return page;
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * sgx_alloc_page - Allocate an EPC page
+ * @owner:	the owner of the EPC page
+ * @reclaim:	reclaim pages if necessary
+ *
+ * Try to grab a page from the free EPC page list. If there is a free page
+ * available, it is returned to the caller. The @reclaim parameter hints
+ * the EPC memory manager to swap pages when required.
+ *
+ * Return:
+ *   a pointer to a &struct sgx_epc_page instance,
+ *   -errno on error
+ */
+struct sgx_epc_page *sgx_alloc_page(void *owner, bool reclaim)
+{
+	struct sgx_epc_page *entry;
+
+	for ( ; ; ) {
+		entry = sgx_try_alloc_page(owner);
+		if (entry)
+			break;
+
+		if (list_empty(&sgx_active_page_list))
+			return ERR_PTR(-ENOMEM);
+
+		if (!reclaim) {
+			entry = ERR_PTR(-EBUSY);
+			break;
+		}
+
+		if (signal_pending(current)) {
+			entry = ERR_PTR(-ERESTARTSYS);
+			break;
+		}
+
+		sgx_reclaim_pages();
+		schedule();
 	}
 
-	return ERR_PTR(-ENOMEM);
+	if (sgx_calc_free_cnt() < SGX_NR_LOW_PAGES)
+		wake_up(&ksgxswapd_waitq);
+
+	return entry;
 }
 EXPORT_SYMBOL_GPL(sgx_alloc_page);
 
@@ -54,10 +218,12 @@ EXPORT_SYMBOL_GPL(sgx_alloc_page);
  * __sgx_free_page - Free an EPC page
  * @page:	pointer a previously allocated EPC page
  *
- * EREMOVE an EPC page and insert it back to the list of free pages.
+ * EREMOVE an EPC page and insert it back to the list of free pages.  If the
+ * page is reclaimable, delete it from the active page list.
  *
  * Return:
  *   0 on success
+ *   -EBUSY if the page cannot be removed from the active list
  *   SGX error code if EREMOVE fails
  */
 int __sgx_free_page(struct sgx_epc_page *page)
@@ -65,6 +231,23 @@ int __sgx_free_page(struct sgx_epc_page *page)
 	struct sgx_epc_section *section = sgx_epc_section(page);
 	int ret;
 
+	/*
+	 * Remove the page from the active list if necessary.  If the page
+	 * is actively being reclaimed, i.e. RECLAIMABLE is set but the
+	 * page isn't on the active list, return -EBUSY as we can't free
+	 * the page at this time since it is "owned" by the reclaimer.
+	 */
+	spin_lock(&sgx_active_page_list_lock);
+	if (page->desc & SGX_EPC_PAGE_RECLAIMABLE) {
+		if (list_empty(&page->list)) {
+			spin_unlock(&sgx_active_page_list_lock);
+			return -EBUSY;
+		}
+		list_del(&page->list);
+		page->desc &= ~SGX_EPC_PAGE_RECLAIMABLE;
+	}
+	spin_unlock(&sgx_active_page_list_lock);
+
 	ret = __eremove(sgx_epc_addr(page));
 	if (ret)
 		return ret;
@@ -81,15 +264,17 @@ EXPORT_SYMBOL_GPL(__sgx_free_page);
  * sgx_free_page - Free an EPC page and WARN on failure
  * @page:	pointer to a previously allocated EPC page
  *
- * EREMOVE an EPC page and insert it back to the list of free pages, and WARN
- * if EREMOVE fails.  For use when the call site cannot (or chooses not to)
- * handle failure, i.e. the page is leaked on failure.
+ * EREMOVE an EPC page and insert it back to the list of free pages.  If the
+ * page is reclaimable, delete it from the active page list.  WARN on any
+ * failure.  For use when the call site cannot (or chooses not to) handle
+ * failure, i.e. the page is leaked on failure.
  */
 void sgx_free_page(struct sgx_epc_page *page)
 {
 	int ret;
 
 	ret = __sgx_free_page(page);
+	WARN(ret < 0, "sgx: cannot free page, reclaim in-progress");
 	WARN(ret > 0, "sgx: EREMOVE returned %d (0x%x)", ret, ret);
 }
 EXPORT_SYMBOL_GPL(sgx_free_page);
@@ -142,6 +327,23 @@ int sgx_einit(struct sgx_sigstruct *sigstruct, struct sgx_einittoken *token,
 }
 EXPORT_SYMBOL(sgx_einit);
 
+/**
+ * sgx_page_reclaimable - mark a page as reclaimable
+ *
+ * @page:	EPC page
+ *
+ * Mark a page as reclaimable and add it to the active page list.  Pages
+ * are automatically removed from the active list when freed.
+ */
+void sgx_page_reclaimable(struct sgx_epc_page *page)
+{
+	spin_lock(&sgx_active_page_list_lock);
+	page->desc |= SGX_EPC_PAGE_RECLAIMABLE;
+	list_add_tail(&page->list, &sgx_active_page_list);
+	spin_unlock(&sgx_active_page_list_lock);
+}
+EXPORT_SYMBOL_GPL(sgx_page_reclaimable);
+
 static __init void sgx_free_epc_section(struct sgx_epc_section *section)
 {
 	int i;
@@ -194,6 +396,11 @@ static __init void sgx_page_cache_teardown(void)
 {
 	int i;
 
+	if (ksgxswapd_tsk) {
+		kthread_stop(ksgxswapd_tsk);
+		ksgxswapd_tsk = NULL;
+	}
+
 	for (i = 0; i < sgx_nr_epc_sections; i++)
 		sgx_free_epc_section(&sgx_epc_sections[i]);
 }
@@ -258,6 +465,7 @@ static __init int sgx_page_cache_init(void)
 
 static __init int sgx_init(void)
 {
+	struct task_struct *tsk;
 	int ret;
 
 	if (!boot_cpu_has(X86_FEATURE_SGX))
@@ -267,6 +475,13 @@ static __init int sgx_init(void)
 	if (ret)
 		return ret;
 
+	tsk = kthread_run(ksgxswapd, NULL, "ksgxswapd");
+	if (IS_ERR(tsk)) {
+		sgx_page_cache_teardown();
+		return PTR_ERR(tsk);
+	}
+	ksgxswapd_tsk = tsk;
+
 	return 0;
 }
 
diff --git a/drivers/platform/x86/intel_sgx/sgx_encl.c b/drivers/platform/x86/intel_sgx/sgx_encl.c
index 1d0a51120e3d..5ef2fa7e92c3 100644
--- a/drivers/platform/x86/intel_sgx/sgx_encl.c
+++ b/drivers/platform/x86/intel_sgx/sgx_encl.c
@@ -191,6 +191,7 @@ static bool sgx_process_add_page_req(struct sgx_add_page_req *req,
 	encl->secs_child_cnt++;
 	sgx_set_page_loaded(encl_page, epc_page);
 	sgx_test_and_clear_young(encl_page);
+	sgx_page_reclaimable(encl_page->epc_page);
 	return true;
 }
 
@@ -220,7 +221,7 @@ static void sgx_add_page_worker(struct work_struct *work)
 		if (skip_rest)
 			goto next;
 
-		epc_page = sgx_alloc_page();
+		epc_page = sgx_alloc_page(req->encl_page, true);
 		down_read(&encl->mm->mmap_sem);
 		mutex_lock(&encl->lock);
 
@@ -467,7 +468,7 @@ int sgx_encl_create(struct sgx_encl *encl, struct sgx_secs *secs)
 	struct sgx_epc_page *secs_epc;
 	long ret;
 
-	secs_epc = sgx_alloc_page();
+	secs_epc = sgx_alloc_page(&encl->secs, true);
 	if (IS_ERR(secs_epc)) {
 		ret = PTR_ERR(secs_epc);
 		return ret;
diff --git a/drivers/platform/x86/intel_sgx/sgx_encl_page.c b/drivers/platform/x86/intel_sgx/sgx_encl_page.c
index fc9bea9f4aea..885eea019c86 100644
--- a/drivers/platform/x86/intel_sgx/sgx_encl_page.c
+++ b/drivers/platform/x86/intel_sgx/sgx_encl_page.c
@@ -12,8 +12,7 @@
 
 static inline struct sgx_encl_page *to_encl_page(struct sgx_epc_page *epc_page)
 {
-	WARN_ON_ONCE(1);
-	return NULL;
+	return (struct sgx_encl_page *)epc_page->owner;
 }
 
 bool sgx_encl_page_get(struct sgx_epc_page *epc_page)
diff --git a/drivers/platform/x86/intel_sgx/sgx_fault.c b/drivers/platform/x86/intel_sgx/sgx_fault.c
index 61d77e9f8fec..71acb2d3f65c 100644
--- a/drivers/platform/x86/intel_sgx/sgx_fault.c
+++ b/drivers/platform/x86/intel_sgx/sgx_fault.c
@@ -13,7 +13,7 @@ static struct sgx_epc_page *__sgx_load_faulted_page(
 	struct sgx_epc_page *epc_page;
 	int ret;
 
-	epc_page = sgx_alloc_page();
+	epc_page = sgx_alloc_page(encl_page, false);
 	if (IS_ERR(epc_page))
 		return epc_page;
 	ret = sgx_encl_load_page(encl_page, epc_page);
@@ -73,6 +73,7 @@ static struct sgx_encl_page *__sgx_fault_page(struct vm_area_struct *vma,
 
 	encl->secs_child_cnt++;
 	sgx_test_and_clear_young(entry);
+	sgx_page_reclaimable(entry->epc_page);
 	if (do_reserve)
 		entry->desc |= SGX_ENCL_PAGE_RESERVED;
 
diff --git a/drivers/platform/x86/intel_sgx/sgx_util.c b/drivers/platform/x86/intel_sgx/sgx_util.c
index eb8072b36a47..1480c4ad0d33 100644
--- a/drivers/platform/x86/intel_sgx/sgx_util.c
+++ b/drivers/platform/x86/intel_sgx/sgx_util.c
@@ -81,7 +81,7 @@ struct sgx_epc_page *sgx_alloc_va_page(void)
 	struct sgx_epc_page *epc_page;
 	int ret;
 
-	epc_page = sgx_alloc_page();
+	epc_page = sgx_alloc_page(NULL, true);
 	if (IS_ERR(epc_page))
 		return ERR_CAST(epc_page);
 
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 155+ messages in thread

* [PATCH v17 21/23] platform/x86: ptrace() support for the SGX driver
       [not found] <20181116010412.23967-1-jarkko.sakkinen@linux.intel.com>
                   ` (19 preceding siblings ...)
  2018-11-16  1:01 ` [PATCH v17 20/23] x86/sgx: Add a simple swapper for the EPC memory manager Jarkko Sakkinen
@ 2018-11-16  1:01 ` Jarkko Sakkinen
  2018-11-16  1:01 ` [PATCH v17 22/23] x86/sgx: SGX documentation Jarkko Sakkinen
                   ` (2 subsequent siblings)
  23 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-16  1:01 UTC (permalink / raw)
  To: x86, platform-driver-x86, linux-sgx
  Cc: dave.hansen, sean.j.christopherson, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Jarkko Sakkinen,
	Darren Hart, Andy Shevchenko, Suresh Siddha, open list

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 <jarkko.sakkinen@linux.intel.com>
---
 drivers/platform/x86/intel_sgx/sgx_vma.c | 109 +++++++++++++++++++++++
 1 file changed, 109 insertions(+)

diff --git a/drivers/platform/x86/intel_sgx/sgx_vma.c b/drivers/platform/x86/intel_sgx/sgx_vma.c
index cc0993b4fd40..df604e4d0d0a 100644
--- a/drivers/platform/x86/intel_sgx/sgx_vma.c
+++ b/drivers/platform/x86/intel_sgx/sgx_vma.c
@@ -51,8 +51,117 @@ static int sgx_vma_fault(struct vm_fault *vmf)
 		return VM_FAULT_SIGBUS;
 }
 
+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) {
+		sgx_dbg(encl, "EDBGRD returned %d\n", ret);
+		return encls_to_err(ret);
+	}
+
+	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) {
+		sgx_dbg(encl, "EDBGWR returned %d\n", ret);
+		return encls_to_err(ret);
+	}
+
+	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) {
+		if (!entry || !((addr + i) & (PAGE_SIZE - 1))) {
+			if (entry)
+				entry->desc &= ~SGX_ENCL_PAGE_RESERVED;
+
+			entry = sgx_fault_page(vma, (addr + i) & PAGE_MASK,
+					       true);
+			if (IS_ERR(entry)) {
+				ret = PTR_ERR(entry);
+				entry = NULL;
+				break;
+			}
+		}
+
+		/* Locking is not needed because only immutable fields of the
+		 * page are accessed and page itself is reserved so that it
+		 * cannot be swapped out in the middle.
+		 */
+
+		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)
+			break;
+		if (write) {
+			memcpy(data + offset, buf + i, cnt);
+			ret = sgx_edbgwr(encl, entry, align, data);
+			if (ret)
+				break;
+		} else
+			memcpy(buf + i, data + offset, cnt);
+	}
+
+	if (entry)
+		entry->desc &= ~SGX_ENCL_PAGE_RESERVED;
+
+	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,
 };
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 155+ messages in thread

* [PATCH v17 22/23] x86/sgx: SGX documentation
       [not found] <20181116010412.23967-1-jarkko.sakkinen@linux.intel.com>
                   ` (20 preceding siblings ...)
  2018-11-16  1:01 ` [PATCH v17 21/23] platform/x86: ptrace() support for the SGX driver Jarkko Sakkinen
@ 2018-11-16  1:01 ` Jarkko Sakkinen
  2018-12-03  3:28   ` Randy Dunlap
  2018-11-16  1:01 ` [PATCH v17 23/23] selftests/x86: Add a selftest for SGX Jarkko Sakkinen
  2018-11-16 11:17 ` [PATCH v17 00/23] Intel SGX1 support Jarkko Sakkinen
  23 siblings, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-16  1:01 UTC (permalink / raw)
  To: x86, platform-driver-x86, linux-sgx
  Cc: dave.hansen, sean.j.christopherson, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Jarkko Sakkinen,
	Jonathan Corbet, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	open list:DOCUMENTATION, open list

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=a, Size: 11858 bytes --]

Documentation of the features of the Software Guard eXtensions used
by the Linux kernel and basic design choices for the core and driver
and functionality.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Co-developed-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
---
 Documentation/index.rst         |   1 +
 Documentation/x86/index.rst     |   8 ++
 Documentation/x86/intel_sgx.rst | 233 ++++++++++++++++++++++++++++++++
 3 files changed, 242 insertions(+)
 create mode 100644 Documentation/x86/index.rst
 create mode 100644 Documentation/x86/intel_sgx.rst

diff --git a/Documentation/index.rst b/Documentation/index.rst
index c858c2e66e36..63864826dcd6 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -101,6 +101,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..11d5b18d9537
--- /dev/null
+++ b/Documentation/x86/index.rst
@@ -0,0 +1,8 @@
+======================
+x86 Architecture Guide
+======================
+
+.. toctree::
+   :maxdepth: 2
+
+   intel_sgx
diff --git a/Documentation/x86/intel_sgx.rst b/Documentation/x86/intel_sgx.rst
new file mode 100644
index 000000000000..f51b43f9e125
--- /dev/null
+++ b/Documentation/x86/intel_sgx.rst
@@ -0,0 +1,233 @@
+===================
+Intel(R) SGX driver
+===================
+
+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 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 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.
+
+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 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 to 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 re-generated 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[17]** 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 out 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 ENCLS(EWB) 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.
+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 ENCLS(ETRACK), 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
+couner value because that means that there might be hardware thread 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 unlocked MSRs i.e.
+FEATURE_CONTROL_SGX_LE_WR must be set. The launch is performed by setting the
+MSRs to the hash of the public key modulus of the enclave signer, which is one
+of the fields in the SIGSTRUCT.
+
+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
+
+Noteably, (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 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.
+
+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
+  <https://eprint.iacr.org/2016/204.pdf>
+* System Programming Manual: 39.1.4 Intel® SGX Launch Control Configuration
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 155+ messages in thread

* [PATCH v17 23/23] selftests/x86: Add a selftest for SGX
       [not found] <20181116010412.23967-1-jarkko.sakkinen@linux.intel.com>
                   ` (21 preceding siblings ...)
  2018-11-16  1:01 ` [PATCH v17 22/23] x86/sgx: SGX documentation Jarkko Sakkinen
@ 2018-11-16  1:01 ` Jarkko Sakkinen
  2018-11-16 11:17 ` [PATCH v17 00/23] Intel SGX1 support Jarkko Sakkinen
  23 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-16  1:01 UTC (permalink / raw)
  To: x86, platform-driver-x86, linux-sgx
  Cc: dave.hansen, sean.j.christopherson, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Jarkko Sakkinen,
	Shuah Khan, Ingo Molnar, Dominik Brodowski, Andy Lutomirski,
	Florian Weimer, Kirill A. Shutemov, Dmitry Safonov,
	Suresh Siddha, open list, open list:KERNEL SELFTEST FRAMEWORK

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 <jarkko.sakkinen@linux.intel.com>
---
 tools/testing/selftests/x86/Makefile          |  10 +
 tools/testing/selftests/x86/sgx/Makefile      |  47 ++
 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  |  16 +
 tools/testing/selftests/x86/sgx/encl_piggy.h  |  13 +
 .../testing/selftests/x86/sgx/sgx-selftest.c  | 149 ++++++
 tools/testing/selftests/x86/sgx/sgx_arch.h    | 109 ++++
 tools/testing/selftests/x86/sgx/sgx_call.S    |  20 +
 tools/testing/selftests/x86/sgx/sgx_uapi.h    | 100 ++++
 tools/testing/selftests/x86/sgx/sgxsign.c     | 503 ++++++++++++++++++
 .../testing/selftests/x86/sgx/signing_key.pem |  39 ++
 13 files changed, 1153 insertions(+)
 create mode 100644 tools/testing/selftests/x86/sgx/Makefile
 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/sgx-selftest.c
 create mode 100644 tools/testing/selftests/x86/sgx/sgx_arch.h
 create mode 100644 tools/testing/selftests/x86/sgx/sgx_call.S
 create mode 100644 tools/testing/selftests/x86/sgx/sgx_uapi.h
 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..04004d244de4
--- /dev/null
+++ b/tools/testing/selftests/x86/sgx/Makefile
@@ -0,0 +1,47 @@
+top_srcdir = ../../../../..
+
+include ../../lib.mk
+
+HOST_CFLAGS := -Wall -Werror -g
+ENCL_CFLAGS := -Wall -Werror -static -nostdlib -nostartfiles -fPIC \
+	       -fno-stack-protector -mrdrnd
+
+TEST_CUSTOM_PROGS := $(OUTPUT)/sgx-selftest
+all_64: $(TEST_CUSTOM_PROGS)
+
+$(TEST_CUSTOM_PROGS): $(OUTPUT)/sgx-selftest.o $(OUTPUT)/sgx_call.o \
+		      $(OUTPUT)/encl_piggy.o
+	$(CC) $(HOST_CFLAGS) -o $@ $^
+
+$(OUTPUT)/sgx-selftest.o: sgx-selftest.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
+
+$(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/encl.c b/tools/testing/selftests/x86/sgx/encl.c
new file mode 100644
index 000000000000..eb6aa318d3f1
--- /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 <stddef.h>
+#include "sgx_arch.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..c5d5787a7c89
--- /dev/null
+++ b/tools/testing/selftests/x86/sgx/encl_piggy.S
@@ -0,0 +1,16 @@
+/* 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"
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..6692d3a8cee0
--- /dev/null
+++ b/tools/testing/selftests/x86/sgx/encl_piggy.h
@@ -0,0 +1,13 @@
+/* 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[];
+
+#endif /* ENCL_PIGGY_H */
diff --git a/tools/testing/selftests/x86/sgx/sgx-selftest.c b/tools/testing/selftests/x86/sgx/sgx-selftest.c
new file mode 100644
index 000000000000..dec649584752
--- /dev/null
+++ b/tools/testing/selftests/x86/sgx/sgx-selftest.c
@@ -0,0 +1,149 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+// Copyright(c) 2016-18 Intel Corporation.
+
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include "encl_piggy.h"
+#include "sgx_arch.h"
+#include "sgx_uapi.h"
+
+static const uint64_t MAGIC = 0x1122334455667788ULL;
+
+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->ssaframesize = 1;
+#ifndef CONFIG_EINITTOKENKEY
+	secs->attributes = SGX_ATTR_MODE64BIT;
+#else
+	secs->attributes = SGX_ATTR_MODE64BIT | SGX_ATTR_EINITTOKENKEY;
+#endif
+	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)
+		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 *entry);
+
+int main(int argc, char **argv)
+{
+	unsigned long bin_size = (unsigned long)&encl_bin_end -
+				 (unsigned long)&encl_bin;
+	struct sgx_secs secs;
+	uint64_t result = 0;
+
+	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);
+	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_arch.h b/tools/testing/selftests/x86/sgx/sgx_arch.h
new file mode 100644
index 000000000000..7711a1be8ad4
--- /dev/null
+++ b/tools/testing/selftests/x86/sgx/sgx_arch.h
@@ -0,0 +1,109 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/*
+ * Copyright(c) 2016-18 Intel Corporation.
+ */
+
+#ifndef SGX_ARCH_H
+#define SGX_ARCH_H
+
+#include <stdint.h>
+
+enum sgx_attribute {
+	SGX_ATTR_DEBUG		= 0x02,
+	SGX_ATTR_MODE64BIT	= 0x04,
+	SGX_ATTR_PROVISIONKEY	= 0x10,
+	SGX_ATTR_EINITTOKENKEY	= 0x20,
+};
+
+#define SGX_ATTR_RESERVED_MASK 0xFFFFFFFFFFFFFFC9L
+
+#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 {
+	uint64_t size;
+	uint64_t base;
+	uint32_t ssaframesize;
+	uint32_t miscselect;
+	uint8_t reserved1[SGX_SECS_RESERVED1_SIZE];
+	uint64_t attributes;
+	uint64_t xfrm;
+	uint32_t mrenclave[8];
+	uint8_t reserved2[SGX_SECS_RESERVED2_SIZE];
+	uint32_t mrsigner[8];
+	uint8_t	reserved3[SGX_SECS_RESERVED3_SIZE];
+	uint16_t isvvprodid;
+	uint16_t isvsvn;
+	uint8_t reserved4[SGX_SECS_RESERVED4_SIZE];
+};
+
+#define SGX_SECINFO_PERMISSION_MASK	0x0000000000000007L
+#define SGX_SECINFO_PAGE_TYPE_MASK	0x000000000000FF00L
+#define SGX_SECINFO_RESERVED_MASK	0xFFFFFFFFFFFF00F8L
+
+enum sgx_page_type {
+	SGX_PAGE_TYPE_SECS	= 0x00,
+	SGX_PAGE_TYPE_TCS	= 0x01,
+	SGX_PAGE_TYPE_REG	= 0x02,
+	SGX_PAGE_TYPE_VA	= 0x03,
+	SGX_PAGE_TYPE_TRIM	= 0x04,
+};
+
+enum sgx_secinfo_flags {
+	SGX_SECINFO_R		= 0x01,
+	SGX_SECINFO_W		= 0x02,
+	SGX_SECINFO_X		= 0x04,
+	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_TRIM	= (SGX_PAGE_TYPE_TRIM << 8),
+};
+
+struct sgx_secinfo {
+	uint64_t flags;
+	uint64_t reserved[7];
+} __attribute__((aligned(64)));
+
+#define SGX_MODULUS_SIZE 384
+
+struct sgx_sigstruct_header {
+	uint64_t header1[2];
+	uint32_t vendor;
+	uint32_t date;
+	uint64_t header2[2];
+	uint32_t swdefined;
+	uint8_t reserved1[84];
+};
+
+struct sgx_sigstruct_body {
+	uint32_t miscselect;
+	uint32_t miscmask;
+	uint8_t reserved2[20];
+	uint64_t attributes;
+	uint64_t xfrm;
+	uint8_t attributemask[16];
+	uint8_t mrenclave[32];
+	uint8_t reserved3[32];
+	uint16_t isvprodid;
+	uint16_t isvsvn;
+} __attribute__((__packed__));
+
+struct sgx_sigstruct {
+	struct sgx_sigstruct_header header;
+	uint8_t modulus[SGX_MODULUS_SIZE];
+	uint32_t exponent;
+	uint8_t signature[SGX_MODULUS_SIZE];
+	struct sgx_sigstruct_body body;
+	uint8_t reserved4[12];
+	uint8_t q1[SGX_MODULUS_SIZE];
+	uint8_t q2[SGX_MODULUS_SIZE];
+};
+
+struct sgx_sigstruct_payload {
+	struct sgx_sigstruct_header header;
+	struct sgx_sigstruct_body body;
+};
+
+#endif /* SGX_ARCH_H */
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..b841d7345533
--- /dev/null
+++ b/tools/testing/selftests/x86/sgx/sgx_call.S
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/**
+* Copyright(c) 2016-18 Intel Corporation.
+*/
+.macro ENCLU
+.byte 0x0f, 0x01, 0xd7
+.endm
+
+	.text
+
+	.global sgx_call
+sgx_call:
+	push	%rbx
+	mov	$0x02, %rax
+	mov	%rdx, %rbx
+	lea	sgx_async_exit(%rip), %rcx
+sgx_async_exit:
+	ENCLU
+	pop	%rbx
+	ret
diff --git a/tools/testing/selftests/x86/sgx/sgx_uapi.h b/tools/testing/selftests/x86/sgx/sgx_uapi.h
new file mode 100644
index 000000000000..ef19f1c013d1
--- /dev/null
+++ b/tools/testing/selftests/x86/sgx/sgx_uapi.h
@@ -0,0 +1,100 @@
+/* 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 <linux/types.h>
+#include <linux/ioctl.h>
+
+#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)
+#define SGX_IOC_ENCLAVE_REMOVE_PAGES \
+	_IOW(SGX_MAGIC, 0x03, struct sgx_enclave_remove_pages)
+#define SGX_IOC_ENCLAVE_MODIFY_PAGES \
+	_IOW(SGX_MAGIC, 0x04, struct sgx_enclave_modify_pages)
+
+/* 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;
+};
+
+/**
+ * struct sgx_enclave_remove_pages - parameter structure for the
+ *                                   %SGX_IOC_ENCLAVE_REMOVE_PAGES ioctl
+ * @addr:	address in the ELRANGE for the first page
+ * @length:	length of the address range (must be multiple of the page size)
+ */
+struct sgx_enclave_remove_pages {
+	__u64	addr;
+	__u64	length;
+} __packed;
+
+/**
+ * enum sgx_enclave_modify_ops - page modification operations
+ * @SGX_ENCLAVE_MODIFY_PERMISSIONS:	change page permissions
+ * @SGX_ENCLAVE_MODIFY_TYPES:		change page type
+ */
+enum sgx_enclave_modify_ops {
+	SGX_ENCLAVE_MODIFY_PERMISSIONS	= 0,
+	SGX_ENCLAVE_MODIFY_TYPES	= 1,
+};
+
+/**
+ * struct sgx_enclave_modify_pages - parameter structure for the
+ *                                   %SGX_IOC_ENCLAVE_MOD_PAGES ioctl
+ * @addr:	address in the ELRANGE for the first page
+ * @length:	length of the address range (must be multiple of the page size)
+ * @secinfo:	address of the new SECINFO data
+ * @op:		a value of &sgx_enclave_modify_ops
+ */
+struct sgx_enclave_modify_pages {
+	__u64	addr;
+	__u64	length;
+	__u64	secinfo;
+	__u8	op;
+} __attribute__((__packed__));
+
+#endif /* _UAPI_ASM_X86_SGX_H */
diff --git a/tools/testing/selftests/x86/sgx/sgxsign.c b/tools/testing/selftests/x86/sgx/sgxsign.c
new file mode 100644
index 000000000000..a670aa186dba
--- /dev/null
+++ b/tools/testing/selftests/x86/sgx/sgxsign.c
@@ -0,0 +1,503 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+// Copyright(c) 2016-18 Intel Corporation.
+
+#define _GNU_SOURCE
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include "sgx_arch.h"
+
+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 <key> <enclave> <sigstruct>\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-----
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-16  1:01 ` [PATCH v17 18/23] platform/x86: Intel SGX driver Jarkko Sakkinen
@ 2018-11-16  1:37   ` Randy Dunlap
  2018-11-16 11:23     ` Jarkko Sakkinen
  2018-11-19 15:06   ` Jarkko Sakkinen
                     ` (3 subsequent siblings)
  4 siblings, 1 reply; 155+ messages in thread
From: Randy Dunlap @ 2018-11-16  1:37 UTC (permalink / raw)
  To: Jarkko Sakkinen, x86, platform-driver-x86, linux-sgx
  Cc: dave.hansen, sean.j.christopherson, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Suresh Siddha, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On 11/15/18 5:01 PM, Jarkko Sakkinen wrote:
> 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.
> 
> SGX driver provides a ioctl API for loading and initializing enclaves.
> Address range for enclaves is reserved with mmap() and they are
> destroyed with munmap(). Enclave construction, measurement and
> initialization is done with the provided the ioctl API.
> 
> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> Co-developed-by: Sean Christopherson <sean.j.christopherson@intel.com>
> Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
> Co-developed-by: Serge Ayoun <serge.ayoun@intel.com>
> Signed-off-by: Serge Ayoun <serge.ayoun@intel.com>
> Co-developed-by: Shay Katz-zamir <shay.katz-zamir@intel.com>
> Signed-off-by: Shay Katz-zamir <shay.katz-zamir@intel.com>
> Co-developed-by: Suresh Siddha <suresh.b.siddha@intel.com>
> Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
> ---

> 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 <linux/types.h>
> +#include <linux/ioctl.h>
> +
> +#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


Hi,
The ioctl magic number should be documented in
Documentation/ioctl/ioctl-number.txt.

ta.
-- 
~Randy

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 00/23] Intel SGX1 support
       [not found] <20181116010412.23967-1-jarkko.sakkinen@linux.intel.com>
                   ` (22 preceding siblings ...)
  2018-11-16  1:01 ` [PATCH v17 23/23] selftests/x86: Add a selftest for SGX Jarkko Sakkinen
@ 2018-11-16 11:17 ` Jarkko Sakkinen
  23 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-16 11:17 UTC (permalink / raw)
  To: x86, platform-driver-x86, linux-sgx
  Cc: dave.hansen, sean.j.christopherson, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Andrew Morton,
	Andy Lutomirski, Arnaldo Carvalho de Melo, Arnd Bergmann,
	Borislav Petkov, Borislav Petkov, Brijesh Singh, David S. Miller,
	David Wang, David Woodhouse, Dmitry Safonov, Dominik Brodowski,
	Fenghua Yu, Florian Weimer, Greg Kroah-Hartman, H. Peter Anvin,
	Ingo Molnar, Janakarajan Natarajan, Jia Zhang,
	Kirill A. Shutemov, Konrad Rzeszutek Wilk, Levin,
	Alexander (Sasha Levin),
	open list:DOCUMENTATION, open list,
	open list:KERNEL SELFTEST FRAMEWORK, Matt Turner,
	Mauro Carvalho Chehab, Nicolas Ferre, Paolo Bonzini, Pu Wen,
	Reinette Chatre, Shuah Khan (Samsung OSG),
	Suresh Siddha, Tom Lendacky

For unknown reason this never reached any MLs (used the same command
line for git send-email as usual).

/Jarkko

On Fri, Nov 16, 2018 at 03:38:08AM +0200, Jarkko Sakkinen wrote:
> 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 inverted sandbox. It
> protects the application from a malicious host.
> 
> There is a new hardware unit in the processor called Memory Encryption
> Engine (MEE) starting from the Skylake microacrhitecture. BIOS can define
> one or many MEE regions that can hold enclave data by configuring them with
> PRMRR registers.
> 
> The MEE automatically encrypts the data leaving the processor package to
> the MEE regions. The data is encrypted using a random key whose life-time
> is exactly one power cycle.
> 
> The current implementation requires that the firmware sets
> IA32_SGXLEPUBKEYHASH* MSRs as writable so that ultimately the kernel can
> decide what enclaves it wants run. The implementation does not create
> any bottlenecks to support read-only MSRs later on.
> 
> You can tell if your CPU supports SGX by looking into /proc/cpuinfo:
> 
> 	cat /proc/cpuinfo  | grep sgx
> 
> v17:
> * Add a simple selftest.
> * Fix a null pointer dereference to section->pages when its
>   allocation fails.
> * Add Sean's description of the exception handling to the documentation.
> 
> v16:
> * Fixed SOB's in the commits that were a bit corrupted in v15.
> * Implemented exceptio handling properly to detect_sgx().
> * Use GENMASK() to define SGX_CPUID_SUB_LEAF_TYPE_MASK.
> * Updated the documentation to use rst definition lists.
> * Added the missing Documentation/x86/index.rst, which has a link to
>   intel_sgx.rst. Now the SGX and uapi documentation is properly generated
>   with 'make htmldocs'.
> * While enumerating EPC sections, if an undefined section is found, fail
>   the driver initialization instead of continuing the initialization.
> * Issue a warning if there are more than %SGX_MAX_EPC_SECTIONS.
> * Remove copyright notice from arch/x86/include/asm/sgx.h.
> * Migrated from ioremap_cache() to memremap().
> 
> v15:
> * Split into more digestable size patches.
> * Lots of small fixes and clean ups.
> * Signal a "plain" SIGSEGV on an EPCM violation.
> 
> v14:
> * Change the comment about X86_FEATURE_SGX_LC from “SGX launch
>   configuration” to “SGX launch control”.
> * Move the SGX-related CPU feature flags as part of the Linux defined
>   virtual leaf 8.
> * Add SGX_ prefix to the constants defining the ENCLS leaf functions.
> * Use GENMASK*() and BIT*() in sgx_arch.h instead of raw hex numbers.
> * Refine the long description for CONFIG_INTEL_SGX_CORE.
> * Do not use pr_*_ratelimited()  in the driver. The use of the rate limited
>   versions is legacy cruft from the prototyping phase.
> * Detect sleep with SGX_INVALID_EINIT_TOKEN instead of counting power
>   cycles.
> * Manually prefix with “sgx:” in the core SGX code instead of redefining
>   pr_fmt.
> * Report if IA32_SGXLEPUBKEYHASHx MSRs are not writable in the driver
>   instead of core because it is a driver requirement.
> * Change prompt to bool in the entry for CONFIG_INTEL_SGX_CORE because the
>   default is ‘n’.
> * Rename struct sgx_epc_bank as struct sgx_epc_section in order to match
>   the SDM.
> * Allocate struct sgx_epc_page instances one at a time.
> * Use “__iomem void *” pointers for the mapped EPC memory consistently.
> * Retry once on SGX_INVALID_TOKEN in sgx_einit() instead of counting power
>   cycles.
> * Call enclave swapping operations directly from the driver instead of
>   calling them .indirectly through struct sgx_epc_page_ops because indirect
>   calls are not required yet as the patch set does not contain the KVM
>   support.
> * Added special signal SEGV_SGXERR to notify about SGX EPCM violation
>   errors.
> 
> v13:
> * Always use SGX_CPUID constant instead of a hardcoded value.
> * Simplified and documented the macros and functions for ENCLS leaves.
> * Enable sgx_free_page() to free active enclave pages on demand
>   in order to allow sgx_invalidate() to delete enclave pages.
>   It no longer performs EREMOVE if a page is in the process of
>   being reclaimed.
> * Use PM notifier per enclave so that we don't have to traverse
>   the global list of active EPC pages to find enclaves.
> * Removed unused SGX_LE_ROLLBACK constant from uapi/asm/sgx.h
> * Always use ioremap() to map EPC banks as we only support 64-bit kernel.
> * Invalidate IA32_SGXLEPUBKEYHASH cache used by sgx_einit() when going
>   to sleep.
> 
> v12:
> * Split to more narrow scoped commits in order to ease the review process and
>   use co-developed-by tag for co-authors of commits instead of listing them in
>   the source files.
> * Removed cruft EXPORT_SYMBOL() declarations and converted to static variables.
> * Removed in-kernel LE i.e. this version of the SGX software stack only
>   supports unlocked IA32_SGXLEPUBKEYHASHx MSRs.
> * Refined documentation on launching enclaves, swapping and enclave
>   construction.
> * Refined sgx_arch.h to include alignment information for every struct that
>   requires it and removed structs that are not needed without an LE.
> * Got rid of SGX_CPUID.
> * SGX detection now prints log messages about firmware configuration issues.
> 
> v11:
> * Polished ENCLS wrappers with refined exception handling.
> * ksgxswapd was not stopped (regression in v5) in
>   sgx_page_cache_teardown(), which causes a leaked kthread after driver
>   deinitialization.
> * Shutdown sgx_le_proxy when going to suspend because its EPC pages will be
>   invalidated when resuming, which will cause it not function properly
>   anymore.
> * Set EINITTOKEN.VALID to zero for a token that is passed when
>   SGXLEPUBKEYHASH matches MRSIGNER as alloc_page() does not give a zero
>   page.
> * Fixed the check in sgx_edbgrd() for a TCS page. Allowed to read offsets
>   around the flags field, which causes a #GP. Only flags read is readable.
> * On read access memcpy() call inside sgx_vma_access() had src and dest
>   parameters in wrong order.
> * The build issue with CONFIG_KASAN is now fixed. Added undefined symbols
>   to LE even if “KASAN_SANITIZE := false” was set in the makefile. 
> * Fixed a regression in the #PF handler. If a page has
>   SGX_ENCL_PAGE_RESERVED flag the #PF handler should unconditionally fail.
>   It did not, which caused weird races when trying to change other parts of
>   swapping code.
> * EPC management has been refactored to a flat LRU cache and moved to
>   arch/x86. The swapper thread reads a cluster of EPC pages and swaps all
>   of them. It can now swap from multiple enclaves in the same round.
> * For the sake of consistency with SGX_IOC_ENCLAVE_ADD_PAGE, return -EINVAL
>   when an enclave is already initialized or dead instead of zero.
> 
> v10:
> * Cleaned up anon inode based IPC between the ring-0 and ring-3 parts
>   of the driver.
> * Unset the reserved flag from an enclave page if EDBGRD/WR fails
>   (regression in v6).
> * Close the anon inode when LE is stopped (regression in v9).
> * Update the documentation with a more detailed description of SGX.
> 
> v9:
> * Replaced kernel-LE IPC based on pipes with an anonymous inode.
>   The driver does not require anymore new exports.
> 
> v8:
> * Check that public key MSRs match the LE public key hash in the
>   driver initialization when the MSRs are read-only.
> * Fix the race in VA slot allocation by checking the fullness
>   immediately after succeesful allocation.
> * Fix the race in hash mrsigner calculation between the launch
>   enclave and user enclaves by having a separate lock for hash
>   calculation.
> 
> v7:
> * Fixed offset calculation in sgx_edbgr/wr(). Address was masked with PAGE_MASK
>   when it should have been masked with ~PAGE_MASK.
> * Fixed a memory leak in sgx_ioc_enclave_create().
> * Simplified swapping code by using a pointer array for a cluster
>   instead of a linked list.
> * Squeezed struct sgx_encl_page to 32 bytes.
> * Fixed deferencing of an RSA key on OpenSSL 1.1.0.
> * Modified TC's CMAC to use kernel AES-NI. Restructured the code
>   a bit in order to better align with kernel conventions.
> 
> v6:
> * Fixed semaphore underrun when accessing /dev/sgx from the launch enclave.
> * In sgx_encl_create() s/IS_ERR(secs)/IS_ERR(encl)/.
> * Removed virtualization chapter from the documentation.
> * Changed the default filename for the signing key as signing_key.pem.
> * Reworked EPC management in a way that instead of a linked list of
>   struct sgx_epc_page instances there is an array of integers that
>   encodes address and bank of an EPC page (the same data as 'pa' field
>   earlier). The locking has been moved to the EPC bank level instead
>   of a global lock.
> * Relaxed locking requirements for EPC management. EPC pages can be
>   released back to the EPC bank concurrently.
> * Cleaned up ptrace() code.
> * Refined commit messages for new architectural constants.
> * Sorted includes in every source file.
> * Sorted local variable declarations according to the line length in
>   every function.
> * Style fixes based on Darren's comments to sgx_le.c.
> 
> v5:
> * Described IPC between the Launch Enclave and kernel in the commit messages.
> * Fixed all relevant checkpatch.pl issues that I have forgot fix in earlier
>   versions except those that exist in the imported TinyCrypt code.
> * Fixed spelling mistakes in the documentation.
> * Forgot to check the return value of sgx_drv_subsys_init().
> * Encapsulated properly page cache init and teardown.
> * Collect epc pages to a temp list in sgx_add_epc_bank
> * Removed SGX_ENCLAVE_INIT_ARCH constant.
> 
> v4:
> * Tied life-cycle of the sgx_le_proxy process to /dev/sgx.
> * Removed __exit annotation from sgx_drv_subsys_exit().
> * Fixed a leak of a backing page in sgx_process_add_page_req() in the
>   case when vm_insert_pfn() fails.
> * Removed unused symbol exports for sgx_page_cache.c.
> * Updated sgx_alloc_page() to require encl parameter and documented the
>   behavior (Sean Christopherson).
> * Refactored a more lean API for sgx_encl_find() and documented the behavior.
> * Moved #PF handler to sgx_fault.c.
> * Replaced subsys_system_register() with plain bus_register().
> * Retry EINIT 2nd time only if MSRs are not locked.
> 
> v3:
> * Check that FEATURE_CONTROL_LOCKED and FEATURE_CONTROL_SGX_ENABLE are set.
> * Return -ERESTARTSYS in __sgx_encl_add_page() when sgx_alloc_page() fails.
> * Use unused bits in epc_page->pa to store the bank number.
> * Removed #ifdef for WQ_NONREENTRANT.
> * If mmu_notifier_register() fails with -EINTR, return -ERESTARTSYS.
> * Added --remove-section=.got.plt to objcopy flags in order to prevent a
>   dummy .got.plt, which will cause an inconsistent size for the LE.
> * Documented sgx_encl_* functions.
> * Added remark about AES implementation used inside the LE.
> * Removed redundant sgx_sys_exit() from le/main.c.
> * Fixed struct sgx_secinfo alignment from 128 to 64 bytes.
> * Validate miscselect in sgx_encl_create().
> * Fixed SSA frame size calculation to take the misc region into account.
> * Implemented consistent exception handling to __encls() and __encls_ret().
> * Implemented a proper device model in order to allow sysfs attributes
>   and in-kernel API.
> * Cleaned up various "find enclave" implementations to the unified
>   sgx_encl_find().
> * Validate that vm_pgoff is zero.
> * Discard backing pages with shmem_truncate_range() after EADD.
> * Added missing EEXTEND operations to LE signing and launch.
> * Fixed SSA size for GPRS region from 168 to 184 bytes.
> * Fixed the checks for TCS flags. Now DBGOPTIN is allowed.
> * Check that TCS addresses are in ELRANGE and not just page aligned.
> * Require kernel to be compiled with X64_64 and CPU_SUP_INTEL.
> * Fixed an incorrect value for SGX_ATTR_DEBUG from 0x01 to 0x02.
> 
> v2:
> * get_rand_uint32() changed the value of the pointer instead of value
>   where it is pointing at.
> * Launch enclave incorrectly used sigstruct attributes-field instead of
>   enclave attributes-field.
> * Removed unused struct sgx_add_page_req from sgx_ioctl.c
> * Removed unused sgx_has_sgx2.
> * Updated arch/x86/include/asm/sgx.h so that it provides stub
>   implementations when sgx in not enabled.
> * Removed cruft rdmsr-calls from sgx_set_pubkeyhash_msrs().
> * return -ENOMEM in sgx_alloc_page() when VA pages consume too much space
> * removed unused global sgx_nr_pids
> * moved sgx_encl_release to sgx_encl.c
> * return -ERESTARTSYS instead of -EINTR in sgx_encl_init()
> 
> 
> Jarkko Sakkinen (13):
>   x86/sgx: Update MAINTAINERS
>   x86/sgx: Define SGX1 and SGX2 ENCLS leafs
>   x86/sgx: Add ENCLS architectural error codes
>   x86/sgx: Add SGX1 and SGX2 architectural data structures
>   x86/sgx: Add definitions for SGX's CPUID leaf and variable sub-leafs
>   x86/sgx: Add wrappers for ENCLS leaf functions
>   x86/sgx: Add functions to allocate and free EPC pages
>   platform/x86: Intel SGX driver
>   platform/x86: sgx: Add swapping functionality to the Intel SGX driver
>   x86/sgx: Add a simple swapper for the EPC memory manager
>   platform/x86: ptrace() support for the SGX driver
>   x86/sgx: SGX documentation
>   selftests/x86: Add a selftest for SGX
> 
> Kai Huang (2):
>   x86/cpufeatures: Add Intel-defined SGX feature bit
>   x86/cpufeatures: Add Intel-defined SGX_LC feature bit
> 
> Sean Christopherson (8):
>   x86/cpufeatures: Add SGX sub-features (as Linux-defined bits)
>   x86/msr: Add IA32_FEATURE_CONTROL.SGX_ENABLE definition
>   x86/cpu/intel: Detect SGX support and update caps appropriately
>   x86/mm: x86/sgx: Add new 'PF_SGX' page fault error code bit
>   x86/mm: x86/sgx: Signal SIGSEGV for userspace #PFs w/ PF_SGX
>   x86/msr: Add SGX Launch Control MSR definitions
>   x86/sgx: Enumerate and track EPC sections
>   x86/sgx: Add sgx_einit() for initializing enclaves
> 
>  Documentation/index.rst                       |   1 +
>  Documentation/x86/index.rst                   |   8 +
>  Documentation/x86/intel_sgx.rst               | 233 +++++
>  MAINTAINERS                                   |   7 +
>  arch/x86/Kconfig                              |  18 +
>  arch/x86/include/asm/cpufeatures.h            |  23 +-
>  arch/x86/include/asm/msr-index.h              |   8 +
>  arch/x86/include/asm/sgx.h                    | 324 ++++++
>  arch/x86/include/asm/sgx_arch.h               | 400 +++++++
>  arch/x86/include/asm/traps.h                  |   1 +
>  arch/x86/include/uapi/asm/sgx.h               |  59 ++
>  arch/x86/include/uapi/asm/sgx_errno.h         |  91 ++
>  arch/x86/kernel/cpu/Makefile                  |   1 +
>  arch/x86/kernel/cpu/intel.c                   |  37 +
>  arch/x86/kernel/cpu/intel_sgx.c               | 488 +++++++++
>  arch/x86/kernel/cpu/scattered.c               |   2 +
>  arch/x86/mm/fault.c                           |  13 +
>  drivers/platform/x86/Kconfig                  |   2 +
>  drivers/platform/x86/Makefile                 |   1 +
>  drivers/platform/x86/intel_sgx/Kconfig        |  20 +
>  drivers/platform/x86/intel_sgx/Makefile       |  14 +
>  drivers/platform/x86/intel_sgx/sgx.h          | 212 ++++
>  drivers/platform/x86/intel_sgx/sgx_encl.c     | 977 ++++++++++++++++++
>  .../platform/x86/intel_sgx/sgx_encl_page.c    | 178 ++++
>  drivers/platform/x86/intel_sgx/sgx_fault.c    | 109 ++
>  drivers/platform/x86/intel_sgx/sgx_ioctl.c    | 234 +++++
>  drivers/platform/x86/intel_sgx/sgx_main.c     | 267 +++++
>  drivers/platform/x86/intel_sgx/sgx_util.c     | 156 +++
>  drivers/platform/x86/intel_sgx/sgx_vma.c      | 167 +++
>  tools/arch/x86/include/asm/cpufeatures.h      |  21 +-
>  tools/testing/selftests/x86/Makefile          |  10 +
>  tools/testing/selftests/x86/sgx/Makefile      |  47 +
>  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  |  16 +
>  tools/testing/selftests/x86/sgx/encl_piggy.h  |  13 +
>  .../testing/selftests/x86/sgx/sgx-selftest.c  | 149 +++
>  tools/testing/selftests/x86/sgx/sgx_arch.h    | 109 ++
>  tools/testing/selftests/x86/sgx/sgx_call.S    |  20 +
>  tools/testing/selftests/x86/sgx/sgx_uapi.h    | 100 ++
>  tools/testing/selftests/x86/sgx/sgxsign.c     | 503 +++++++++
>  .../testing/selftests/x86/sgx/signing_key.pem |  39 +
>  43 files changed, 5213 insertions(+), 12 deletions(-)
>  create mode 100644 Documentation/x86/index.rst
>  create mode 100644 Documentation/x86/intel_sgx.rst
>  create mode 100644 arch/x86/include/asm/sgx.h
>  create mode 100644 arch/x86/include/asm/sgx_arch.h
>  create mode 100644 arch/x86/include/uapi/asm/sgx.h
>  create mode 100644 arch/x86/include/uapi/asm/sgx_errno.h
>  create mode 100644 arch/x86/kernel/cpu/intel_sgx.c
>  create mode 100644 drivers/platform/x86/intel_sgx/Kconfig
>  create mode 100644 drivers/platform/x86/intel_sgx/Makefile
>  create mode 100644 drivers/platform/x86/intel_sgx/sgx.h
>  create mode 100644 drivers/platform/x86/intel_sgx/sgx_encl.c
>  create mode 100644 drivers/platform/x86/intel_sgx/sgx_encl_page.c
>  create mode 100644 drivers/platform/x86/intel_sgx/sgx_fault.c
>  create mode 100644 drivers/platform/x86/intel_sgx/sgx_ioctl.c
>  create mode 100644 drivers/platform/x86/intel_sgx/sgx_main.c
>  create mode 100644 drivers/platform/x86/intel_sgx/sgx_util.c
>  create mode 100644 drivers/platform/x86/intel_sgx/sgx_vma.c
>  create mode 100644 tools/testing/selftests/x86/sgx/Makefile
>  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/sgx-selftest.c
>  create mode 100644 tools/testing/selftests/x86/sgx/sgx_arch.h
>  create mode 100644 tools/testing/selftests/x86/sgx/sgx_call.S
>  create mode 100644 tools/testing/selftests/x86/sgx/sgx_uapi.h
>  create mode 100644 tools/testing/selftests/x86/sgx/sgxsign.c
>  create mode 100644 tools/testing/selftests/x86/sgx/signing_key.pem
> 
> -- 
> 2.19.1
> 
> 

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-16  1:37   ` Randy Dunlap
@ 2018-11-16 11:23     ` Jarkko Sakkinen
  0 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-16 11:23 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: x86, platform-driver-x86, linux-sgx, dave.hansen,
	sean.j.christopherson, nhorman, npmccallum, serge.ayoun,
	shay.katz-zamir, haitao.huang, andriy.shevchenko, tglx,
	kai.svahn, mark.shanahan, luto, Suresh Siddha, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Thu, Nov 15, 2018 at 05:37:27PM -0800, Randy Dunlap wrote:
> On 11/15/18 5:01 PM, Jarkko Sakkinen wrote:
> > 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.
> > 
> > SGX driver provides a ioctl API for loading and initializing enclaves.
> > Address range for enclaves is reserved with mmap() and they are
> > destroyed with munmap(). Enclave construction, measurement and
> > initialization is done with the provided the ioctl API.
> > 
> > Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> > Co-developed-by: Sean Christopherson <sean.j.christopherson@intel.com>
> > Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
> > Co-developed-by: Serge Ayoun <serge.ayoun@intel.com>
> > Signed-off-by: Serge Ayoun <serge.ayoun@intel.com>
> > Co-developed-by: Shay Katz-zamir <shay.katz-zamir@intel.com>
> > Signed-off-by: Shay Katz-zamir <shay.katz-zamir@intel.com>
> > Co-developed-by: Suresh Siddha <suresh.b.siddha@intel.com>
> > Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
> > ---
> 
> > 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 <linux/types.h>
> > +#include <linux/ioctl.h>
> > +
> > +#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
> 
> 
> Hi,
> The ioctl magic number should be documented in
> Documentation/ioctl/ioctl-number.txt.
> 
> ta.
> -- 
> ~Randy

Thank you. Addressed now in https://github.com/jsakkine-intel/linux-sgx.git.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 01/23] x86/sgx: Update MAINTAINERS
  2018-11-16  1:01 ` [PATCH v17 01/23] x86/sgx: Update MAINTAINERS Jarkko Sakkinen
@ 2018-11-16 14:22   ` Borislav Petkov
  2018-11-16 15:07     ` Jarkko Sakkinen
  0 siblings, 1 reply; 155+ messages in thread
From: Borislav Petkov @ 2018-11-16 14:22 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: x86, platform-driver-x86, linux-sgx, dave.hansen,
	sean.j.christopherson, nhorman, npmccallum, serge.ayoun,
	shay.katz-zamir, haitao.huang, andriy.shevchenko, tglx,
	kai.svahn, mark.shanahan, luto, Mauro Carvalho Chehab,
	Greg Kroah-Hartman, David S. Miller, Andrew Morton,
	Nicolas Ferre, Arnd Bergmann, open list

On Fri, Nov 16, 2018 at 03:01:08AM +0200, Jarkko Sakkinen wrote:
> Add the maintainer information for the SGX subsystem.
> 
> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> ---
>  MAINTAINERS | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 0abecc528dac..aaf56b544858 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -7676,6 +7676,13 @@ L:	linux-gpio@vger.kernel.org
>  S:	Maintained
>  F:	drivers/gpio/gpio-intel-mid.c
>  
> +INTEL SGX
> +M:	Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> +L:	linux-sgx@vger.kernel.org
> +Q:	https://patchwork.kernel.org/project/intel-sgx/list/
> +F:	drivers/platform/x86/intel_sgx/

Looking at your diffstat, this doesn't cover it all.

One example: arch/x86/kernel/cpu/intel_sgx.c

Also, was there any particular reasoning for calling the file
intel_sgx.c instead of simply sgx.c ?

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 02/23] x86/cpufeatures: Add Intel-defined SGX feature bit
  2018-11-16  1:01 ` [PATCH v17 02/23] x86/cpufeatures: Add Intel-defined SGX feature bit Jarkko Sakkinen
@ 2018-11-16 14:28   ` Borislav Petkov
  2018-11-16 15:13     ` Jarkko Sakkinen
  0 siblings, 1 reply; 155+ messages in thread
From: Borislav Petkov @ 2018-11-16 14:28 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: x86, platform-driver-x86, linux-sgx, dave.hansen,
	sean.j.christopherson, nhorman, npmccallum, serge.ayoun,
	shay.katz-zamir, haitao.huang, andriy.shevchenko, tglx,
	kai.svahn, mark.shanahan, luto, Kai Huang, Ingo Molnar,
	H. Peter Anvin, Konrad Rzeszutek Wilk, David Woodhouse,
	Fenghua Yu, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Fri, Nov 16, 2018 at 03:01:09AM +0200, Jarkko Sakkinen wrote:
> From: Kai Huang <kai.huang@linux.intel.com>
> 
> X86_FEATURE_SGX reflects whether or not the CPU supports Intel's
> Software Guard eXtensions (SGX).
> 
> Signed-off-by: Kai Huang <kai.huang@linux.intel.com>
> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> ---
>  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 28c4a502b419..da7fed4939a3 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 */
> -- 

Reviewed-by: Borislav Petkov <bp@suse.de>

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 03/23] x86/cpufeatures: Add SGX sub-features (as Linux-defined bits)
  2018-11-16  1:01 ` [PATCH v17 03/23] x86/cpufeatures: Add SGX sub-features (as Linux-defined bits) Jarkko Sakkinen
@ 2018-11-16 14:37   ` Borislav Petkov
  2018-11-16 15:38     ` Sean Christopherson
  2018-11-16 23:31   ` Dave Hansen
  1 sibling, 1 reply; 155+ messages in thread
From: Borislav Petkov @ 2018-11-16 14:37 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: x86, platform-driver-x86, linux-sgx, dave.hansen,
	sean.j.christopherson, nhorman, npmccallum, serge.ayoun,
	shay.katz-zamir, haitao.huang, andriy.shevchenko, tglx,
	kai.svahn, mark.shanahan, luto, Ingo Molnar, H. Peter Anvin,
	Konrad Rzeszutek Wilk, David Woodhouse, Fenghua Yu,
	Brijesh Singh, Paolo Bonzini, Tom Lendacky,
	Arnaldo Carvalho de Melo,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Fri, Nov 16, 2018 at 03:01:10AM +0200, Jarkko Sakkinen wrote:
> From: Sean Christopherson <sean.j.christopherson@intel.com>
> 
> 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 <sean.j.christopherson@intel.com>
> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> ---
>  arch/x86/include/asm/cpufeatures.h       | 21 +++++++++++++++------
>  arch/x86/kernel/cpu/scattered.c          |  2 ++
>  tools/arch/x86/include/asm/cpufeatures.h | 21 +++++++++++++++------
>  3 files changed, 32 insertions(+), 12 deletions(-)
> 
> diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
> index da7fed4939a3..afdf5f2e13b5 100644
> --- a/arch/x86/include/asm/cpufeatures.h
> +++ b/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 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 */
> +

Yeah, add here	^^^^

/* Bits [0:7] are reserved for SGX */

or so, so that people don't use those. Once CPUID(12) gets more bits
added to it, I don't see anything wrong with allocating a separate leaf
for that.

BUT(!), the question then is whether kvm would still be ok with that?
I'm thinking yes, as it will simply use the new definitions, or?

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 01/23] x86/sgx: Update MAINTAINERS
  2018-11-16 14:22   ` Borislav Petkov
@ 2018-11-16 15:07     ` Jarkko Sakkinen
  2018-11-16 20:24       ` Borislav Petkov
  0 siblings, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-16 15:07 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: x86, platform-driver-x86, linux-sgx, dave.hansen,
	sean.j.christopherson, nhorman, npmccallum, serge.ayoun,
	shay.katz-zamir, haitao.huang, andriy.shevchenko, tglx,
	kai.svahn, mark.shanahan, luto, Mauro Carvalho Chehab,
	Greg Kroah-Hartman, David S. Miller, Andrew Morton,
	Nicolas Ferre, Arnd Bergmann, open list

On Fri, Nov 16, 2018 at 03:22:48PM +0100, Borislav Petkov wrote:
> On Fri, Nov 16, 2018 at 03:01:08AM +0200, Jarkko Sakkinen wrote:
> > Add the maintainer information for the SGX subsystem.
> > 
> > Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> > ---
> >  MAINTAINERS | 7 +++++++
> >  1 file changed, 7 insertions(+)
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 0abecc528dac..aaf56b544858 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -7676,6 +7676,13 @@ L:	linux-gpio@vger.kernel.org
> >  S:	Maintained
> >  F:	drivers/gpio/gpio-intel-mid.c
> >  
> > +INTEL SGX
> > +M:	Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> > +L:	linux-sgx@vger.kernel.org
> > +Q:	https://patchwork.kernel.org/project/intel-sgx/list/
> > +F:	drivers/platform/x86/intel_sgx/
> 
> Looking at your diffstat, this doesn't cover it all.
> 
> One example: arch/x86/kernel/cpu/intel_sgx.c
> 
> Also, was there any particular reasoning for calling the file
> intel_sgx.c instead of simply sgx.c ?

Ouch. There has been so much work in other patches that I've forgot
to update it :-( Sorry.

Yes, I think it could be renamed as sgx.c. Should the driver part be
also called as sgx.ko?

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 02/23] x86/cpufeatures: Add Intel-defined SGX feature bit
  2018-11-16 14:28   ` Borislav Petkov
@ 2018-11-16 15:13     ` Jarkko Sakkinen
  2018-11-16 15:18       ` Jarkko Sakkinen
  0 siblings, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-16 15:13 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: x86, platform-driver-x86, linux-sgx, dave.hansen,
	sean.j.christopherson, nhorman, npmccallum, serge.ayoun,
	shay.katz-zamir, haitao.huang, andriy.shevchenko, tglx,
	kai.svahn, mark.shanahan, luto, Kai Huang, Ingo Molnar,
	H. Peter Anvin, Konrad Rzeszutek Wilk, David Woodhouse,
	Fenghua Yu, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Fri, Nov 16, 2018 at 03:28:40PM +0100, Borislav Petkov wrote:
> Reviewed-by: Borislav Petkov <bp@suse.de>

Thank you, the very first reviewed-by 8-)

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 02/23] x86/cpufeatures: Add Intel-defined SGX feature bit
  2018-11-16 15:13     ` Jarkko Sakkinen
@ 2018-11-16 15:18       ` Jarkko Sakkinen
  2018-11-16 20:53         ` Borislav Petkov
  0 siblings, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-16 15:18 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: x86, platform-driver-x86, linux-sgx, dave.hansen,
	sean.j.christopherson, nhorman, npmccallum, serge.ayoun,
	shay.katz-zamir, haitao.huang, andriy.shevchenko, tglx,
	kai.svahn, mark.shanahan, luto, Kai Huang, Ingo Molnar,
	H. Peter Anvin, Konrad Rzeszutek Wilk, David Woodhouse,
	Fenghua Yu, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Fri, Nov 16, 2018 at 05:13:51PM +0200, Jarkko Sakkinen wrote:
> On Fri, Nov 16, 2018 at 03:28:40PM +0100, Borislav Petkov wrote:
> > Reviewed-by: Borislav Petkov <bp@suse.de>
> 
> Thank you, the very first reviewed-by 8-)

I will also add Sean as co-maintainer as he has the KVM angle and is
needed to ack patches in the future. This functionality really needs
two eyes. Has shown to have value in many occasions.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 03/23] x86/cpufeatures: Add SGX sub-features (as Linux-defined bits)
  2018-11-16 14:37   ` Borislav Petkov
@ 2018-11-16 15:38     ` Sean Christopherson
  0 siblings, 0 replies; 155+ messages in thread
From: Sean Christopherson @ 2018-11-16 15:38 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Jarkko Sakkinen, x86, platform-driver-x86, linux-sgx,
	dave.hansen, nhorman, npmccallum, serge.ayoun, shay.katz-zamir,
	haitao.huang, andriy.shevchenko, tglx, kai.svahn, mark.shanahan,
	luto, Ingo Molnar, H. Peter Anvin, Konrad Rzeszutek Wilk,
	David Woodhouse, Fenghua Yu, Brijesh Singh, Paolo Bonzini,
	Tom Lendacky, Arnaldo Carvalho de Melo,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Fri, Nov 16, 2018 at 03:37:15PM +0100, Borislav Petkov wrote:
> On Fri, Nov 16, 2018 at 03:01:10AM +0200, Jarkko Sakkinen wrote:
> > From: Sean Christopherson <sean.j.christopherson@intel.com>
> > 
> > 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 <sean.j.christopherson@intel.com>
> > Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> > ---
> >  arch/x86/include/asm/cpufeatures.h       | 21 +++++++++++++++------
> >  arch/x86/kernel/cpu/scattered.c          |  2 ++
> >  tools/arch/x86/include/asm/cpufeatures.h | 21 +++++++++++++++------
> >  3 files changed, 32 insertions(+), 12 deletions(-)
> > 
> > diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
> > index da7fed4939a3..afdf5f2e13b5 100644
> > --- a/arch/x86/include/asm/cpufeatures.h
> > +++ b/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 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 */
> > +
> 
> Yeah, add here	^^^^
> 
> /* Bits [0:7] are reserved for SGX */
> 
> or so, so that people don't use those. Once CPUID(12) gets more bits
> added to it, I don't see anything wrong with allocating a separate leaf
> for that.
> 
> BUT(!), the question then is whether kvm would still be ok with that?
> I'm thinking yes, as it will simply use the new definitions, or?

Yep, wouldn't be a problem for KVM.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 13/23] x86/msr: Add SGX Launch Control MSR definitions
  2018-11-16  1:01 ` [PATCH v17 13/23] x86/msr: Add SGX Launch Control MSR definitions Jarkko Sakkinen
@ 2018-11-16 17:29   ` Sean Christopherson
  2018-11-18  8:19     ` Jarkko Sakkinen
  0 siblings, 1 reply; 155+ messages in thread
From: Sean Christopherson @ 2018-11-16 17:29 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: x86, platform-driver-x86, linux-sgx, dave.hansen, nhorman,
	npmccallum, serge.ayoun, shay.katz-zamir, haitao.huang,
	andriy.shevchenko, tglx, kai.svahn, mark.shanahan, luto,
	Haim Cohen, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Konrad Rzeszutek Wilk, Tom Lendacky, Paolo Bonzini, Matt Turner,
	Janakarajan Natarajan, David Woodhouse,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Fri, Nov 16, 2018 at 03:01:20AM +0200, Jarkko Sakkinen wrote:
> From: Sean Christopherson <sean.j.christopherson@intel.com>
> 
> Add a new IA32_FEATURE_CONTROL bit, SGX_LE_WR.

Introducing SGX_LE_WR needs to land before patch 06/23, which references
the flag when updating feature bits.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 01/23] x86/sgx: Update MAINTAINERS
  2018-11-16 15:07     ` Jarkko Sakkinen
@ 2018-11-16 20:24       ` Borislav Petkov
  2018-11-18  8:20         ` Jarkko Sakkinen
  0 siblings, 1 reply; 155+ messages in thread
From: Borislav Petkov @ 2018-11-16 20:24 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: x86, platform-driver-x86, linux-sgx, dave.hansen,
	sean.j.christopherson, nhorman, npmccallum, serge.ayoun,
	shay.katz-zamir, haitao.huang, andriy.shevchenko, tglx,
	kai.svahn, mark.shanahan, luto, Mauro Carvalho Chehab,
	Greg Kroah-Hartman, David S. Miller, Andrew Morton,
	Nicolas Ferre, Arnd Bergmann, open list

On Fri, Nov 16, 2018 at 05:07:14PM +0200, Jarkko Sakkinen wrote:
> Yes, I think it could be renamed as sgx.c. Should the driver part be
> also called as sgx.ko?

I guess that's your call guys. The reason why I asked is because I like
shorter names and "sgx" is unambiguous enough. AFAICT, there's no one
else doing SGX atm.

:-)

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 02/23] x86/cpufeatures: Add Intel-defined SGX feature bit
  2018-11-16 15:18       ` Jarkko Sakkinen
@ 2018-11-16 20:53         ` Borislav Petkov
  0 siblings, 0 replies; 155+ messages in thread
From: Borislav Petkov @ 2018-11-16 20:53 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: x86, platform-driver-x86, linux-sgx, dave.hansen,
	sean.j.christopherson, nhorman, npmccallum, serge.ayoun,
	shay.katz-zamir, haitao.huang, andriy.shevchenko, tglx,
	kai.svahn, mark.shanahan, luto, Kai Huang, Ingo Molnar,
	H. Peter Anvin, Konrad Rzeszutek Wilk, David Woodhouse,
	Fenghua Yu, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Fri, Nov 16, 2018 at 05:18:45PM +0200, Jarkko Sakkinen wrote:
> I will also add Sean as co-maintainer as he has the KVM angle and is
> needed to ack patches in the future. This functionality really needs
> two eyes. Has shown to have value in many occasions.

Yap, two maintainers or a maintainer group for a bigger subsystem or
arch is always much better than a single poor dude trying to cover it
all.

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 03/23] x86/cpufeatures: Add SGX sub-features (as Linux-defined bits)
  2018-11-16  1:01 ` [PATCH v17 03/23] x86/cpufeatures: Add SGX sub-features (as Linux-defined bits) Jarkko Sakkinen
  2018-11-16 14:37   ` Borislav Petkov
@ 2018-11-16 23:31   ` Dave Hansen
  2018-11-18  8:36     ` Jarkko Sakkinen
  1 sibling, 1 reply; 155+ messages in thread
From: Dave Hansen @ 2018-11-16 23:31 UTC (permalink / raw)
  To: Jarkko Sakkinen, x86, platform-driver-x86, linux-sgx
  Cc: sean.j.christopherson, nhorman, npmccallum, serge.ayoun,
	shay.katz-zamir, haitao.huang, andriy.shevchenko, tglx,
	kai.svahn, mark.shanahan, luto, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Konrad Rzeszutek Wilk, David Woodhouse,
	Fenghua Yu, Brijesh Singh, Paolo Bonzini, Tom Lendacky,
	Arnaldo Carvalho de Melo,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On 11/15/18 5:01 PM, Jarkko Sakkinen wrote:
> +#define X86_FEATURE_SGX1		( 8*32+ 0) /* SGX1 leaf functions */
> +#define X86_FEATURE_SGX2		( 8*32+ 1) /* SGX2 leaf functions */

Is there a reason these are not (all) tied to CONFIG_INTEL_SGX via:

arch/x86/include/asm/disabled-features.h

?

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 06/23] x86/cpu/intel: Detect SGX support and update caps appropriately
  2018-11-16  1:01 ` [PATCH v17 06/23] x86/cpu/intel: Detect SGX support and update caps appropriately Jarkko Sakkinen
@ 2018-11-16 23:32   ` Dave Hansen
  2018-11-18  8:37     ` Jarkko Sakkinen
  2018-11-21 18:17   ` Borislav Petkov
  1 sibling, 1 reply; 155+ messages in thread
From: Dave Hansen @ 2018-11-16 23:32 UTC (permalink / raw)
  To: Jarkko Sakkinen, x86, platform-driver-x86, linux-sgx
  Cc: sean.j.christopherson, nhorman, npmccallum, serge.ayoun,
	shay.katz-zamir, haitao.huang, andriy.shevchenko, tglx,
	kai.svahn, mark.shanahan, luto, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Konrad Rzeszutek Wilk, David Woodhouse,
	Kirill A. Shutemov, David Wang, Levin, Alexander (Sasha Levin),
	Jia Zhang, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On 11/15/18 5:01 PM, Jarkko Sakkinen wrote:
> +static void 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: IA32_FEATURE_CONTROL MSR is not locked\n");
> +		goto out_unsupported;
> +	}

This needs a check against the config option somewhere so the compiler
can toss it in its entirety if SGX is config'd out.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 07/23] x86/mm: x86/sgx: Add new 'PF_SGX' page fault error code bit
  2018-11-16  1:01 ` [PATCH v17 07/23] x86/mm: x86/sgx: Add new 'PF_SGX' page fault error code bit Jarkko Sakkinen
@ 2018-11-16 23:33   ` Dave Hansen
  2018-11-18  8:38     ` Jarkko Sakkinen
  0 siblings, 1 reply; 155+ messages in thread
From: Dave Hansen @ 2018-11-16 23:33 UTC (permalink / raw)
  To: Jarkko Sakkinen, x86, platform-driver-x86, linux-sgx
  Cc: sean.j.christopherson, nhorman, npmccallum, serge.ayoun,
	shay.katz-zamir, haitao.huang, andriy.shevchenko, tglx,
	kai.svahn, mark.shanahan, luto, Dave Hansen, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, Andy Lutomirski,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On 11/15/18 5:01 PM, Jarkko Sakkinen wrote:
> 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).

This should probably also mention that, despite being a page fault,
X86_PF_SGX has nothing to do with paging itself.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 13/23] x86/msr: Add SGX Launch Control MSR definitions
  2018-11-16 17:29   ` Sean Christopherson
@ 2018-11-18  8:19     ` Jarkko Sakkinen
  0 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-18  8:19 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: x86, platform-driver-x86, linux-sgx, dave.hansen, nhorman,
	npmccallum, serge.ayoun, shay.katz-zamir, haitao.huang,
	andriy.shevchenko, tglx, kai.svahn, mark.shanahan, luto,
	Haim Cohen, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Konrad Rzeszutek Wilk, Tom Lendacky, Paolo Bonzini, Matt Turner,
	Janakarajan Natarajan, David Woodhouse,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Fri, Nov 16, 2018 at 09:29:08AM -0800, Sean Christopherson wrote:
> On Fri, Nov 16, 2018 at 03:01:20AM +0200, Jarkko Sakkinen wrote:
> > From: Sean Christopherson <sean.j.christopherson@intel.com>
> > 
> > Add a new IA32_FEATURE_CONTROL bit, SGX_LE_WR.
> 
> Introducing SGX_LE_WR needs to land before patch 06/23, which references
> the flag when updating feature bits.

Ugh, I guess this feedback was given already to earlier version.
Forgot to fix it.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 01/23] x86/sgx: Update MAINTAINERS
  2018-11-16 20:24       ` Borislav Petkov
@ 2018-11-18  8:20         ` Jarkko Sakkinen
  0 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-18  8:20 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: x86, platform-driver-x86, linux-sgx, dave.hansen,
	sean.j.christopherson, nhorman, npmccallum, serge.ayoun,
	shay.katz-zamir, haitao.huang, andriy.shevchenko, tglx,
	kai.svahn, mark.shanahan, luto, Mauro Carvalho Chehab,
	Greg Kroah-Hartman, David S. Miller, Andrew Morton,
	Nicolas Ferre, Arnd Bergmann, open list

On Fri, Nov 16, 2018 at 09:24:03PM +0100, Borislav Petkov wrote:
> On Fri, Nov 16, 2018 at 05:07:14PM +0200, Jarkko Sakkinen wrote:
> > Yes, I think it could be renamed as sgx.c. Should the driver part be
> > also called as sgx.ko?
> 
> I guess that's your call guys. The reason why I asked is because I like
> shorter names and "sgx" is unambiguous enough. AFAICT, there's no one
> else doing SGX atm.
> 
> :-)

We go with that! Thanks for the feedback.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 03/23] x86/cpufeatures: Add SGX sub-features (as Linux-defined bits)
  2018-11-16 23:31   ` Dave Hansen
@ 2018-11-18  8:36     ` Jarkko Sakkinen
  0 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-18  8:36 UTC (permalink / raw)
  To: Dave Hansen
  Cc: x86, platform-driver-x86, linux-sgx, sean.j.christopherson,
	nhorman, npmccallum, serge.ayoun, shay.katz-zamir, haitao.huang,
	andriy.shevchenko, tglx, kai.svahn, mark.shanahan, luto,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Konrad Rzeszutek Wilk, David Woodhouse, Fenghua Yu,
	Brijesh Singh, Paolo Bonzini, Tom Lendacky,
	Arnaldo Carvalho de Melo,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Fri, Nov 16, 2018 at 03:31:28PM -0800, Dave Hansen wrote:
> On 11/15/18 5:01 PM, Jarkko Sakkinen wrote:
> > +#define X86_FEATURE_SGX1		( 8*32+ 0) /* SGX1 leaf functions */
> > +#define X86_FEATURE_SGX2		( 8*32+ 1) /* SGX2 leaf functions */
> 
> Is there a reason these are not (all) tied to CONFIG_INTEL_SGX via:
> 
> arch/x86/include/asm/disabled-features.h
> 
> ?

No any particular reason.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 06/23] x86/cpu/intel: Detect SGX support and update caps appropriately
  2018-11-16 23:32   ` Dave Hansen
@ 2018-11-18  8:37     ` Jarkko Sakkinen
  0 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-18  8:37 UTC (permalink / raw)
  To: Dave Hansen
  Cc: x86, platform-driver-x86, linux-sgx, sean.j.christopherson,
	nhorman, npmccallum, serge.ayoun, shay.katz-zamir, haitao.huang,
	andriy.shevchenko, tglx, kai.svahn, mark.shanahan, luto,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Konrad Rzeszutek Wilk, David Woodhouse, Kirill A. Shutemov,
	David Wang, Levin, Alexander (Sasha Levin),
	Jia Zhang, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Fri, Nov 16, 2018 at 03:32:36PM -0800, Dave Hansen wrote:
> On 11/15/18 5:01 PM, Jarkko Sakkinen wrote:
> > +static void 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: IA32_FEATURE_CONTROL MSR is not locked\n");
> > +		goto out_unsupported;
> > +	}
> 
> This needs a check against the config option somewhere so the compiler
> can toss it in its entirety if SGX is config'd out.

Certainly. I'll flag it in the next version.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 07/23] x86/mm: x86/sgx: Add new 'PF_SGX' page fault error code bit
  2018-11-16 23:33   ` Dave Hansen
@ 2018-11-18  8:38     ` Jarkko Sakkinen
  0 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-18  8:38 UTC (permalink / raw)
  To: Dave Hansen
  Cc: x86, platform-driver-x86, linux-sgx, sean.j.christopherson,
	nhorman, npmccallum, serge.ayoun, shay.katz-zamir, haitao.huang,
	andriy.shevchenko, tglx, kai.svahn, mark.shanahan, luto,
	Dave Hansen, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Andy Lutomirski, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Fri, Nov 16, 2018 at 03:33:35PM -0800, Dave Hansen wrote:
> On 11/15/18 5:01 PM, Jarkko Sakkinen wrote:
> > 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).
> 
> This should probably also mention that, despite being a page fault,
> X86_PF_SGX has nothing to do with paging itself.

A valid point.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-16  1:01 ` [PATCH v17 18/23] platform/x86: Intel SGX driver Jarkko Sakkinen
  2018-11-16  1:37   ` Randy Dunlap
@ 2018-11-19 15:06   ` Jarkko Sakkinen
  2018-11-19 16:22     ` Jethro Beekman
  2018-11-19 15:29   ` Andy Lutomirski
                     ` (2 subsequent siblings)
  4 siblings, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-19 15:06 UTC (permalink / raw)
  To: x86, platform-driver-x86, linux-sgx
  Cc: dave.hansen, sean.j.christopherson, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Suresh Siddha, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Fri, Nov 16, 2018 at 03:01:25AM +0200, Jarkko Sakkinen wrote:
> 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.
> 
> SGX driver provides a ioctl API for loading and initializing enclaves.
> Address range for enclaves is reserved with mmap() and they are
> destroyed with munmap(). Enclave construction, measurement and
> initialization is done with the provided the ioctl API.
> 
> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> Co-developed-by: Sean Christopherson <sean.j.christopherson@intel.com>
> Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
> Co-developed-by: Serge Ayoun <serge.ayoun@intel.com>
> Signed-off-by: Serge Ayoun <serge.ayoun@intel.com>
> Co-developed-by: Shay Katz-zamir <shay.katz-zamir@intel.com>
> Signed-off-by: Shay Katz-zamir <shay.katz-zamir@intel.com>
> Co-developed-by: Suresh Siddha <suresh.b.siddha@intel.com>
> Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>

Question: should be dissolve the driver completely and move this code to
arch/x86/kernel/cpu/sgx/ (and rename intel_sgx.c as main.c)? Swapping
patch removes the possibility to compile this as a module anyway.

Would make also maintainer hierarchy more clear and clean albeit that
cannot be a guiding reason to do such change. Here's the current
MAINTAINERS entry in my master:

INTEL SGX
M:	Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
M:	Sean Christopherson <sean.j.christopherson@intel.com>
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/intel_sgx.c
F:	drivers/platform/x86/intel_sgx/*
K:	\bSGX_

If we do this, we would end up with this:

INTEL SGX
M:	Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
M:	Sean Christopherson <sean.j.christopherson@intel.com>
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_

Then once the base code has been merged I would put my PRs to x86
maintainers for subsequent kernel releases.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-16  1:01 ` [PATCH v17 18/23] platform/x86: Intel SGX driver Jarkko Sakkinen
  2018-11-16  1:37   ` Randy Dunlap
  2018-11-19 15:06   ` Jarkko Sakkinen
@ 2018-11-19 15:29   ` Andy Lutomirski
  2018-11-19 16:19     ` Jarkko Sakkinen
                       ` (2 more replies)
  2018-12-17 17:45   ` Dave Hansen
  2018-12-18  5:55   ` Andy Lutomirski
  4 siblings, 3 replies; 155+ messages in thread
From: Andy Lutomirski @ 2018-11-19 15:29 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: X86 ML, Platform Driver, linux-sgx, Dave Hansen, Christopherson,
	Sean J, nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir,
	haitao.huang, Andy Shevchenko, Thomas Gleixner, Svahn, Kai,
	mark.shanahan, Suresh Siddha, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Darren Hart, andy, LKML

On Thu, Nov 15, 2018 at 5:08 PM Jarkko Sakkinen
<jarkko.sakkinen@linux.intel.com> wrote:
>
> 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.
>
> SGX driver provides a ioctl API for loading and initializing enclaves.
> Address range for enclaves is reserved with mmap() and they are
> destroyed with munmap(). Enclave construction, measurement and
> initialization is done with the provided the ioctl API.
>

I brought this up a while back, and I think I should re-ask it now
that this driver is getting close to ready:

As it stands, there's just one SGX character device, and I imagine
that it'll be available to unprivileged applications.  I'm concerned
that this isn't quite what we want.  I certainly think that everyone,
or at least almost everyone, ought to be able to run normal enclaves.
But I think that we should consider restricting who can run specially
privileged enclaves.  In particular, the ability to run enclaves with
the provisioning bit set is somewhat sensitive, since it effectively
allows access to a stable fingerprint of the system.  Before flexible
LC, this wasn't such a big deal, since only Intel's provisioning
enclave could see the key, and Intel's enclave has some degree of
control of what is done with the key.  With flex LC, this protection
is lost.

But this is maybe more of a big deal than just access to a stable
fingerprint.  The ability to provision a remote attestation protocol
is a key part of running SGX malware, and SGX malware is surely going
to exist some day.  (Sure, Intel will try to block access to the
actual attestation service for malware, but I doubt that Intel will be
able to fully defend it.)

So I propose that there be a few device nodes.  Maybe
/dev/sgx/unprivilegd and /dev/sgx/provisioning?  The default mode of
the latter could be 0600.  If you've opened the unprivileged node, you
can only run enclaves without any special permission bits set.

We should also consider whether we allow the unprivileged node to run
launch enclaves, and, for that matter, whether we allow user code to
run launch enclaves at all, given that they're not useful with the
current architecture of the driver.

--Andy

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-19 15:29   ` Andy Lutomirski
@ 2018-11-19 16:19     ` Jarkko Sakkinen
  2018-11-19 16:59       ` Andy Lutomirski
  2018-11-20 11:15     ` Dr. Greg
  2018-12-09 17:01     ` Pavel Machek
  2 siblings, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-19 16:19 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: X86 ML, Platform Driver, linux-sgx, Dave Hansen, Christopherson,
	Sean J, nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir,
	haitao.huang, Andy Shevchenko, Thomas Gleixner, Svahn, Kai,
	mark.shanahan, Suresh Siddha, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Darren Hart, andy, LKML

On Mon, Nov 19, 2018 at 07:29:25AM -0800, Andy Lutomirski wrote:
> On Thu, Nov 15, 2018 at 5:08 PM Jarkko Sakkinen
> <jarkko.sakkinen@linux.intel.com> wrote:
> >
> > 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.
> >
> > SGX driver provides a ioctl API for loading and initializing enclaves.
> > Address range for enclaves is reserved with mmap() and they are
> > destroyed with munmap(). Enclave construction, measurement and
> > initialization is done with the provided the ioctl API.
> >
> 
> I brought this up a while back, and I think I should re-ask it now
> that this driver is getting close to ready:
> 
> As it stands, there's just one SGX character device, and I imagine
> that it'll be available to unprivileged applications.  I'm concerned
> that this isn't quite what we want.  I certainly think that everyone,
> or at least almost everyone, ought to be able to run normal enclaves.
> But I think that we should consider restricting who can run specially
> privileged enclaves.  In particular, the ability to run enclaves with
> the provisioning bit set is somewhat sensitive, since it effectively
> allows access to a stable fingerprint of the system.  Before flexible
> LC, this wasn't such a big deal, since only Intel's provisioning
> enclave could see the key, and Intel's enclave has some degree of
> control of what is done with the key.  With flex LC, this protection
> is lost.
> 
> But this is maybe more of a big deal than just access to a stable
> fingerprint.  The ability to provision a remote attestation protocol
> is a key part of running SGX malware, and SGX malware is surely going
> to exist some day.  (Sure, Intel will try to block access to the
> actual attestation service for malware, but I doubt that Intel will be
> able to fully defend it.)
> 
> So I propose that there be a few device nodes.  Maybe
> /dev/sgx/unprivilegd and /dev/sgx/provisioning?  The default mode of
> the latter could be 0600.  If you've opened the unprivileged node, you
> can only run enclaves without any special permission bits set.

What would the use case for unprivileged i.e. this configuration would
mean depending on permissions?

There would be three types of users:

1. Ones that have access to neither of the devices.
2. Ones that have access to unprivileged. Who are these?
3. Ones that have access to provisioning.

> We should also consider whether we allow the unprivileged node to run
> launch enclaves, and, for that matter, whether we allow user code to
> run launch enclaves at all, given that they're not useful with the
> current architecture of the driver.

ATM the launch enclave bit is disallowed by the kernel in the current
patch set. I don't really see any use case to allow them except if we
want to allow run enclaves in an environment where the MSRs are rdonly.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-19 15:06   ` Jarkko Sakkinen
@ 2018-11-19 16:22     ` Jethro Beekman
  2018-11-19 17:19       ` Jarkko Sakkinen
  0 siblings, 1 reply; 155+ messages in thread
From: Jethro Beekman @ 2018-11-19 16:22 UTC (permalink / raw)
  To: Jarkko Sakkinen, x86, platform-driver-x86, linux-sgx
  Cc: dave.hansen, sean.j.christopherson, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Suresh Siddha, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

[-- Attachment #1: Type: text/plain, Size: 460 bytes --]

On 2018-11-19 20:36, Jarkko Sakkinen wrote:
> Question: should be dissolve the driver completely and move this code to
> arch/x86/kernel/cpu/sgx/ (and rename intel_sgx.c as main.c)? Swapping
> patch removes the possibility to compile this as a module anyway.

No. We should keep the capability to build this as a module for other 
users of SGX. What is the swapping patch and why doesn't allow building 
as a module?

--
Jethro Beekman | Fortanix


[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 3990 bytes --]

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-19 16:19     ` Jarkko Sakkinen
@ 2018-11-19 16:59       ` Andy Lutomirski
  2018-11-20 12:04         ` Jarkko Sakkinen
  2018-12-09 17:01         ` Pavel Machek
  0 siblings, 2 replies; 155+ messages in thread
From: Andy Lutomirski @ 2018-11-19 16:59 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: X86 ML, Platform Driver, linux-sgx, Dave Hansen, Christopherson,
	Sean J, nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir,
	haitao.huang, Andy Shevchenko, Thomas Gleixner, Svahn, Kai,
	mark.shanahan, Suresh Siddha, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Darren Hart, andy, LKML

On Mon, Nov 19, 2018 at 8:19 AM Jarkko Sakkinen
<jarkko.sakkinen@linux.intel.com> wrote:
>
> On Mon, Nov 19, 2018 at 07:29:25AM -0800, Andy Lutomirski wrote:
> > On Thu, Nov 15, 2018 at 5:08 PM Jarkko Sakkinen
> > <jarkko.sakkinen@linux.intel.com> wrote:
> > >
> > > 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.
> > >
> > > SGX driver provides a ioctl API for loading and initializing enclaves.
> > > Address range for enclaves is reserved with mmap() and they are
> > > destroyed with munmap(). Enclave construction, measurement and
> > > initialization is done with the provided the ioctl API.
> > >
> >
> > I brought this up a while back, and I think I should re-ask it now
> > that this driver is getting close to ready:
> >
> > As it stands, there's just one SGX character device, and I imagine
> > that it'll be available to unprivileged applications.  I'm concerned
> > that this isn't quite what we want.  I certainly think that everyone,
> > or at least almost everyone, ought to be able to run normal enclaves.
> > But I think that we should consider restricting who can run specially
> > privileged enclaves.  In particular, the ability to run enclaves with
> > the provisioning bit set is somewhat sensitive, since it effectively
> > allows access to a stable fingerprint of the system.  Before flexible
> > LC, this wasn't such a big deal, since only Intel's provisioning
> > enclave could see the key, and Intel's enclave has some degree of
> > control of what is done with the key.  With flex LC, this protection
> > is lost.
> >
> > But this is maybe more of a big deal than just access to a stable
> > fingerprint.  The ability to provision a remote attestation protocol
> > is a key part of running SGX malware, and SGX malware is surely going
> > to exist some day.  (Sure, Intel will try to block access to the
> > actual attestation service for malware, but I doubt that Intel will be
> > able to fully defend it.)
> >
> > So I propose that there be a few device nodes.  Maybe
> > /dev/sgx/unprivilegd and /dev/sgx/provisioning?  The default mode of
> > the latter could be 0600.  If you've opened the unprivileged node, you
> > can only run enclaves without any special permission bits set.
>
> What would the use case for unprivileged i.e. this configuration would
> mean depending on permissions?

Everything except the quoting/provisioning code would use the unprivileged node.

>
> There would be three types of users:
>
> 1. Ones that have access to neither of the devices.
> 2. Ones that have access to unprivileged. Who are these?

Either 0666 (world) or an sgx group.

> 3. Ones that have access to provisioning.

Root only.

The idea here is that, under normal circumstances, provisioning only
runs once, or at least only runs rarely.  So, rather than the SDK
running provisioning whenever it feels like doing so (which is the
current behavior, I imagine, although I haven't looked), there would
be a privileged program, perhaps a systemd unit that runs when needed,
that produces the key material needed for remote attestation, and
non-root users that need attestation would get the keying material
from the provisioning service.  And the provisioning service could
implement its own policy.  Ideally, the service wouldn't give the
sealed keys to users at all but would, instead, just provide the
entire attestation service over a UNIX socket, which would make
provisioning capabilities revocable.

Does this make sense?

--Andy

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-19 16:22     ` Jethro Beekman
@ 2018-11-19 17:19       ` Jarkko Sakkinen
  2018-11-19 18:18         ` Andy Lutomirski
  0 siblings, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-19 17:19 UTC (permalink / raw)
  To: Jethro Beekman
  Cc: x86, platform-driver-x86, linux-sgx, dave.hansen,
	sean.j.christopherson, nhorman, npmccallum, serge.ayoun,
	shay.katz-zamir, haitao.huang, andriy.shevchenko, tglx,
	kai.svahn, mark.shanahan, luto, Suresh Siddha, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Nov 19, 2018 at 04:22:54PM +0000, Jethro Beekman wrote:
> On 2018-11-19 20:36, Jarkko Sakkinen wrote:
> > Question: should be dissolve the driver completely and move this code to
> > arch/x86/kernel/cpu/sgx/ (and rename intel_sgx.c as main.c)? Swapping
> > patch removes the possibility to compile this as a module anyway.
> 
> No. We should keep the capability to build this as a module for other users
> of SGX. What is the swapping patch and why doesn't allow building as a
> module?

In some earlier version of the patch set the request was to remove the
callback interface to the driver so now core does direct calls to the
swapping operations.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-19 17:19       ` Jarkko Sakkinen
@ 2018-11-19 18:18         ` Andy Lutomirski
  2018-11-20 11:00           ` Jarkko Sakkinen
  0 siblings, 1 reply; 155+ messages in thread
From: Andy Lutomirski @ 2018-11-19 18:18 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Jethro Beekman, x86, platform-driver-x86, linux-sgx, dave.hansen,
	sean.j.christopherson, nhorman, npmccallum, serge.ayoun,
	shay.katz-zamir, haitao.huang, andriy.shevchenko, tglx,
	kai.svahn, mark.shanahan, Suresh Siddha, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)



> On Nov 19, 2018, at 10:19 AM, Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> wrote:
> 
>> On Mon, Nov 19, 2018 at 04:22:54PM +0000, Jethro Beekman wrote:
>>> On 2018-11-19 20:36, Jarkko Sakkinen wrote:
>>> Question: should be dissolve the driver completely and move this code to
>>> arch/x86/kernel/cpu/sgx/ (and rename intel_sgx.c as main.c)? Swapping
>>> patch removes the possibility to compile this as a module anyway.
>> 
>> No. We should keep the capability to build this as a module for other users
>> of SGX. What is the swapping patch and why doesn't allow building as a
>> module?
> 
> In some earlier version of the patch set the request was to remove the
> callback interface to the driver so now core does direct calls to the
> swapping operations.
> 
> 

Once static_call lands, this will be a great use for it.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-19 18:18         ` Andy Lutomirski
@ 2018-11-20 11:00           ` Jarkko Sakkinen
  0 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-20 11:00 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Jethro Beekman, x86, platform-driver-x86, linux-sgx, dave.hansen,
	sean.j.christopherson, nhorman, npmccallum, serge.ayoun,
	shay.katz-zamir, haitao.huang, andriy.shevchenko, tglx,
	kai.svahn, mark.shanahan, Suresh Siddha, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Nov 19, 2018 at 11:18:54AM -0700, Andy Lutomirski wrote:
> Once static_call lands, this will be a great use for it.

When is it expected to land? Cool feature BTW!

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-19 15:29   ` Andy Lutomirski
  2018-11-19 16:19     ` Jarkko Sakkinen
@ 2018-11-20 11:15     ` Dr. Greg
  2018-11-24 16:15       ` Jarkko Sakkinen
  2018-12-09 17:01     ` Pavel Machek
  2 siblings, 1 reply; 155+ messages in thread
From: Dr. Greg @ 2018-11-20 11:15 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Jarkko Sakkinen, X86 ML, Platform Driver, linux-sgx, Dave Hansen,
	Christopherson, Sean J, nhorman, npmccallum, Ayoun, Serge,
	shay.katz-zamir, haitao.huang, Andy Shevchenko, Thomas Gleixner,
	Svahn, Kai, mark.shanahan, Suresh Siddha, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, Darren Hart, andy, LKML

On Mon, Nov 19, 2018 at 07:29:25AM -0800, Andy Lutomirski wrote:

Good morning, I hope this note finds the week going well for everyone.

> On Thu, Nov 15, 2018 at 5:08 PM Jarkko Sakkinen
> <jarkko.sakkinen@linux.intel.com> wrote:
> >
> > 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.
> >
> > SGX driver provides a ioctl API for loading and initializing enclaves.
> > Address range for enclaves is reserved with mmap() and they are
> > destroyed with munmap(). Enclave construction, measurement and
> > initialization is done with the provided the ioctl API.

> I brought this up a while back, and I think I should re-ask it now
> that this driver is getting close to ready:
>
> As it stands, there's just one SGX character device, and I imagine
> that it'll be available to unprivileged applications.  I'm concerned
> that this isn't quite what we want.  I certainly think that
> everyone, or at least almost everyone, ought to be able to run
> normal enclaves.  But I think that we should consider restricting
> who can run specially privileged enclaves.  In particular, the
> ability to run enclaves with the provisioning bit set is somewhat
> sensitive, since it effectively allows access to a stable
> fingerprint of the system.  Before flexible LC, this wasn't such a
> big deal, since only Intel's provisioning enclave could see the key,
> and Intel's enclave has some degree of control of what is done with
> the key.  With flex LC, this protection is lost.

When I saw this thread over the weekend I was going to reply to it and
raise this issue but Andy beat me to it.  Beyond that I was busy
trying to get enough firwewood ready to stay warm for the winter so
other priorities prevailed.. :-)

About 6-8 months ago, Andy and I had a lively discussion on this list
about whether or not there was a need, from a security perspective,
for enclave based LC.  I understand the sentiment against enclave
based LC, particularly with only a single vendor in control, but when
the entire spectrum of SGX security guarantees are considered, things
begin to fray at the edges a bit when LC is delegated to the kernel.

As everyone knows, in the most general sense, SGX is designed to
implement security in an IAGO threat environment, ie. where the entire
platform is compromised.  This is conceptually, if not provably
possible, when all of the security contracts are fulfilled by
enclaves.  Placing LC in the kernel has the effect of bringing the
kernel into the TCB footprint of the overall security guarantees the
technology is designed to deliver, which include privacy and
anonymity.

So, as Andy points out, we now need to work these security
considerations into the design of what will be 'the' Linux SGX driver.

Moving LC into the kernel means that rigid security controls are no
longer available for two security sensitive assets; The Provisioning
Key (PK) and the Provisioning Seal Key (PSK).

The PK is used to generate a unique Platform Provisioning IDentity
(PPID) in the Endpoint Selection (ES) phase of the Intel Enhanced
Privacy ID (EPID) provisioning protocol.  With the proposed driver, as
Andy notes above, there is now the opportunity for adversarial
generation of a unique platform identity by anyone who can create and
run an enclave.

The ENCLU[EGETKEY] instruction does not include the OWNEREPOCH values
in the key derivation process so the PK is in effect a permanent and
unique identity for a platform.

The PSK is one of the statically derived symmetric keys that are
available for sealing/encryption of data.  The PSK is used to encrypt
and protect the EPID private key that Intel provisions to a platform.
This private key is used by the quoting enclave to sign attestation
reports for enclaves running on the platform.  The SGX privacy
guarantees are a function of the security characteristics of EPID
keys.

So, loss of the PSK has implications with respect to the binding of an
EPID to a platform and what entities can use the EPID private key.  In
the enclave LC model the only entities with access to the key are the
provisioning (PVE) and quoting (QE) enclaves.

For the benefit of those not deeply involved in all this.  Shortly
after the release of the Linux SDK/PSW, Intel evolved the ability to
uniquely identify a platform and verify that an enclave is running on
a 'GenuineIntel' platform into the Platform Certification Enclave
(PCE).  This enclave has the provisioning attribute set and uses
access to the PK to implement this functionality.

Section 5.8.2 of the Costan and Devadas SGX review paper talk about
the PK and the PSK.  This section notes, in a referral to section
5.9.3, that restriction of general access to the PROVISION attribute
by enclaves is important for SGX privacy guarantees.

So I believe it is fair to state that this issue requires careful
consideration as we move the Linux SGX eco-system forward.

> But this is maybe more of a big deal than just access to a stable
> fingerprint.  The ability to provision a remote attestation protocol
> is a key part of running SGX malware, and SGX malware is surely
> going to exist some day.  (Sure, Intel will try to block access to
> the actual attestation service for malware, but I doubt that Intel
> will be able to fully defend it.)

Malware would not necessarily need the Intel attestation service.
Once access to the PROVISION bit is available, malware teams could
simply build their own attestation service.

Malware authors are a bit limited now by the general design of the
Intel PSW that mediates all enclave platform functionality through the
aesm_service binary.  The group that I direct SGX engineering for,
IDfusion, developed a complete replacement for the Intel PSW.  Our
work is a minimum footprint implementation that focuses on the
application of SGX to intelligent network endpoint devices and
embedded environments.

Our PSW supports the generation of 'fat binaries' where all of the
functionality, including enclaves, can be embedded into a single
statically linked and self-contained binary.  We developed a proof of
concept application, based on the Apache Struts vulnerability, that
loads one of these binaries on a platform which then sets up a secured
and attested channel for spirting information off of the malware
target.

So the malware concerns are not theoretical, as we are not an
extraordinarily clever group of individuals.  We are considering an
open-source release of the tooling we have developed and even if we
don't end up doing that someone else could easily implement equivalent
functionality.

We've written at some length about these issues in the following Intel
SGX developer forum threads if anyone is interested:

https://software.intel.com/en-us/forums/intel-software-guard-extensions-intel-sgx/topic/781730

https://software.intel.com/en-us/forums/intel-software-guard-extensions-intel-sgx/topic/671517

From a hardware perspective, FLC has now emerged on the Xeon E series
of processors.  FLC isn't being deployed for the sake of openness or
the open-source community, it is rather, secondary to a vertical
marketing strategy that Intel is implementing for SGX.

Intel is offering a subscription based service for data-center
applications of SGX.  Attestation is based on an ECDSA secured
certification that the enclave is running on a 'GenuineIntel' platform
with a specific platform security version (PSVN), see the discussion
on the PCE enclave above.

Non server class, ie. workstations and embedded class devices, will
presumably use a provisioning and EPID based strategy.

> So I propose that there be a few device nodes.  Maybe
> /dev/sgx/unprivilegd and /dev/sgx/provisioning?  The default mode of
> the latter could be 0600.  If you've opened the unprivileged node,
> you can only run enclaves without any special permission bits set.
>
> We should also consider whether we allow the unprivileged node to
> run launch enclaves, and, for that matter, whether we allow user
> code to run launch enclaves at all, given that they're not useful
> with the current architecture of the driver.

Doing this right is probably going to take a bit more then two
separate device nodes.

I believe what the Linux community needs to do is to step back and
consider how to create a driver architecture that supports what will
be the certain stratification of SGX hardware.  I don't see the
current driver being useful for anything but data-center class
hardware for the intermediate if not foreseeable future.

In addition, given what was detailed above, I don't see how this
driver is going to be satisfactory for those of us delivering
platforms with stringent security and privacy guarantees that are
relevant in an IAGO model.  Like it or not the most stringent security
contracts are only available in a full enclave based model.

As a result, like it or not, the current driver needs the ability to
function in both launch control modes.

> --Andy

Hopefully the above information is useful to the development dialogue.

Developing a community driver is tedious at best, particularly for
hardware such as this.  Our personal thanks to Jarkko and others who
have been working through these issues.

Best wishes for a productive remainder of the week and for a pleasant
Thanksgiving holiday for those who will be celebrating that.

Dr. Greg

As always,
Dr. G.W. Wettstein, Ph.D.   Enjellic Systems Development, LLC.
4206 N. 19th Ave.           Specializing in information infra-structure
Fargo, ND  58102            development.
PH: 701-281-1686
FAX: 701-281-3949           EMAIL: greg@enjellic.com
------------------------------------------------------------------------------
"So you got your butt kicked by an 'old' guy.

 Before you taunted him did it ever cross your mind that the $1200
 Schmoelke aero-bars he was laying on and the $900 Rocket7 cycling
 shoes he was wearing might mean that the $10,000 custom bike frame he
 was riding was used for more than transportation to the Dairy Queen
 each night for a Dilly Bar?"
                                -- Dr. G.W. Wettstein
                                   Resurrection

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-19 16:59       ` Andy Lutomirski
@ 2018-11-20 12:04         ` Jarkko Sakkinen
  2018-11-22 11:12           ` Dr. Greg
  2018-12-09 17:01         ` Pavel Machek
  1 sibling, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-20 12:04 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: X86 ML, Platform Driver, linux-sgx, Dave Hansen, Christopherson,
	Sean J, nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir,
	haitao.huang, Andy Shevchenko, Thomas Gleixner, Svahn, Kai,
	mark.shanahan, Suresh Siddha, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Darren Hart, andy, LKML

On Mon, Nov 19, 2018 at 08:59:24AM -0800, Andy Lutomirski wrote:
> The idea here is that, under normal circumstances, provisioning only
> runs once, or at least only runs rarely.  So, rather than the SDK
> running provisioning whenever it feels like doing so (which is the
> current behavior, I imagine, although I haven't looked), there would
> be a privileged program, perhaps a systemd unit that runs when needed,
> that produces the key material needed for remote attestation, and
> non-root users that need attestation would get the keying material
> from the provisioning service.  And the provisioning service could
> implement its own policy.  Ideally, the service wouldn't give the
> sealed keys to users at all but would, instead, just provide the
> entire attestation service over a UNIX socket, which would make
> provisioning capabilities revocable.
> 
> Does this make sense?

Yes, it does for me at least now that you brought some context.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 06/23] x86/cpu/intel: Detect SGX support and update caps appropriately
  2018-11-16  1:01 ` [PATCH v17 06/23] x86/cpu/intel: Detect SGX support and update caps appropriately Jarkko Sakkinen
  2018-11-16 23:32   ` Dave Hansen
@ 2018-11-21 18:17   ` Borislav Petkov
  2018-11-24 13:54     ` Jarkko Sakkinen
  1 sibling, 1 reply; 155+ messages in thread
From: Borislav Petkov @ 2018-11-21 18:17 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: x86, platform-driver-x86, linux-sgx, dave.hansen,
	sean.j.christopherson, nhorman, npmccallum, serge.ayoun,
	shay.katz-zamir, haitao.huang, andriy.shevchenko, tglx,
	kai.svahn, mark.shanahan, luto, Ingo Molnar, H. Peter Anvin,
	Konrad Rzeszutek Wilk, David Woodhouse, Kirill A. Shutemov,
	David Wang, Levin, Alexander (Sasha Levin),
	Jia Zhang, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Fri, Nov 16, 2018 at 03:01:13AM +0200, Jarkko Sakkinen wrote:
> From: Sean Christopherson <sean.j.christopherson@intel.com>
> 
> 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 <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/intel.c | 37 +++++++++++++++++++++++++++++++++++++
>  1 file changed, 37 insertions(+)
> 
> diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
> index fc3c07fe7df5..8a20a193d399 100644
> --- a/arch/x86/kernel/cpu/intel.c
> +++ b/arch/x86/kernel/cpu/intel.c
> @@ -596,6 +596,40 @@ static void detect_tme(struct cpuinfo_x86 *c)
>  	c->x86_phys_bits -= keyid_bits;
>  }
>  
> +static void 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: IA32_FEATURE_CONTROL MSR is not locked\n");
> +		goto out_unsupported;
> +	}
> +
> +	if (!(fc & FEATURE_CONTROL_SGX_ENABLE)) {
> +		pr_err_once("sgx: not enabled in IA32_FEATURE_CONTROL MSR\n");

Start those messages with a capital letter: "sgx: SGX is not enabled ...".

> +		goto out_unsupported;
> +	}
> +
> +	if (!cpu_has(c, X86_FEATURE_SGX1)) {
> +		pr_err_once("sgx: SGX1 instruction set not supported\n");
> +		goto out_unsupported;
> +	}
> +
> +	if (!(fc & FEATURE_CONTROL_SGX_LE_WR)) {

I see the build failure here has been pointed out already but lemme
repeat it out for another reason:

It is very important that no patch we merge breaks bisectability -
please build every patch before sending:

arch/x86/kernel/cpu/intel.c: In function ‘detect_sgx’:
arch/x86/kernel/cpu/intel.c:619:13: error: ‘FEATURE_CONTROL_SGX_LE_WR’ undeclared (first use in this function); did you mean ‘FEATURE_CONTROL_SGX_ENABLE’?
  if (!(fc & FEATURE_CONTROL_SGX_LE_WR)) {
             ^~~~~~~~~~~~~~~~~~~~~~~~~
             FEATURE_CONTROL_SGX_ENABLE
arch/x86/kernel/cpu/intel.c:619:13: note: each undeclared identifier is reported only once for each function it appears in
make[3]: *** [scripts/Makefile.build:291: arch/x86/kernel/cpu/intel.o] Error 1
make[3]: *** Waiting for unfinished jobs....
make[2]: *** [scripts/Makefile.build:516: arch/x86/kernel/cpu] Error 2
make[1]: *** [scripts/Makefile.build:516: arch/x86/kernel] Error 2
make: *** [Makefile:1060: arch/x86] Error 2
make: *** Waiting for unfinished jobs....


> +		pr_info_once("sgx: launch control MSRs are not writable\n");
> +		goto out_msrs_rdonly;
> +	}
> +
> +	return;

<---- newline here.

> +out_unsupported:
> +	setup_clear_cpu_cap(X86_FEATURE_SGX);
> +	setup_clear_cpu_cap(X86_FEATURE_SGX1);
> +	setup_clear_cpu_cap(X86_FEATURE_SGX2);

<---- newline here.

> +out_msrs_rdonly:
> +	setup_clear_cpu_cap(X86_FEATURE_SGX_LC);
> +}

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-20 12:04         ` Jarkko Sakkinen
@ 2018-11-22 11:12           ` Dr. Greg
  2018-11-22 15:21             ` Andy Lutomirski
  2018-11-22 20:56             ` Andy Lutomirski
  0 siblings, 2 replies; 155+ messages in thread
From: Dr. Greg @ 2018-11-22 11:12 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Andy Lutomirski, X86 ML, Platform Driver, linux-sgx, Dave Hansen,
	Christopherson, Sean J, nhorman, npmccallum, Ayoun, Serge,
	shay.katz-zamir, haitao.huang, Andy Shevchenko, Thomas Gleixner,
	Svahn, Kai, mark.shanahan, Suresh Siddha, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, Darren Hart, andy, LKML

On Tue, Nov 20, 2018 at 02:04:42PM +0200, Jarkko Sakkinen wrote:

Good morning to everyone, Happy Thanksgiving to those who are
celebrating the holiday.

> On Mon, Nov 19, 2018 at 08:59:24AM -0800, Andy Lutomirski wrote:
> > The idea here is that, under normal circumstances, provisioning only
> > runs once, or at least only runs rarely.  So, rather than the SDK
> > running provisioning whenever it feels like doing so (which is the
> > current behavior, I imagine, although I haven't looked), there would
> > be a privileged program, perhaps a systemd unit that runs when needed,
> > that produces the key material needed for remote attestation, and
> > non-root users that need attestation would get the keying material
> > from the provisioning service.  And the provisioning service could
> > implement its own policy.  Ideally, the service wouldn't give the
> > sealed keys to users at all but would, instead, just provide the
> > entire attestation service over a UNIX socket, which would make
> > provisioning capabilities revocable.
> > 
> > Does this make sense?

> Yes, it does for me at least now that you brought some context.

Let me see if I can add a bit of additional context to the above to
frame further discussion regarding two major needs of the driver
before it lands.

What Andy is describing is how the current system already works.  The
driver is at the root of a fairly complex eco-system of code,
cryptography and protocols that implement SGX functionality.  This
software stack is known as the SGX Platform SoftWare (PSW) or SGX
runtime.

The Intel provided runtime is implemented in C++ and, depending on how
you count it, clocks in at around 50+ KLOC.  All of this ends up as a
single 1.8 megabyte binary named aesm_service that links against 35
shared libraries and is run by systemd.

This binary implements the functionality needed to load, initialize,
run and attest enclaves.  It also implements communications with the
Intel provisioning and attestation services which is needed to
provision a private EPID key to the platform and to verify the status
of an enclave attestation quote from a remote platform.

In order to achieve the SGX/IAGO security model, a lot of this
functionality is implemented by choreographing exchanges between six
Intel supplied and signed enclaves.  Intel supplies source code to
these enclaves and understanding how all of this works requires an
understanding of that codebase as well.  To top if off there is also a
50K hunk of signed Java bytecode that gets stuffed into the Management
Engine if you are interested in platform services.

All of the above is what we wrote an independent implementation of, in
straight C, that is capable of linking against the MUSL C library with
only libelf and OpenSSL as dependencies.  We developed all of this to
support a reasonably sophisticated multi-enclave SGX security
application that implements modeling the runtime behavior of
applications running on the Linux kernel.  That application uses an
alternate enclave attestation and communications architecture that we
independently developed.

I don't describe the above to hype or promote what we do.  Everyone
discussing these issues is a professional software engineer or
architect.  As such, you will know that by the time you get done doing
all of the above, to the point where you are willing to take it to
Washington, DC to do live technology demonstrations to government
agencies with seven minutes of setup time, you are going to have to be
pretty confident that you know how all of the pieces are supposed to
go together.

Based on this experience, if the proposed driver lands in its current
state, Linux mainline will have, at least from a privacy perspective,
an inferior implementation of SGX.  In addition, we are not confident
the driver will be useful to anything other then server class hardware
and will be incapable of supporting virtually all of the existing SGX
hardware in the field.

This is NOT a criticism of Jarkko's work or the overall technical
implementation and quality of the driver.  We actually use and test a
modified version of the proposed driver, along with the out of tree
driver in our platforms.

At a high level, addressing these issues is straight forward.  First,
the driver needs to support authorization equivalent to that which is
implemented in the current Intel Launch Enclave, ie. control over the
SGX_FLAGS_PROVISION_KEY attribute.  Secondly, the driver needs to drop
its prohibition against launch enclaves, ie. returning EINVAL when a
request is made to initialize enclaves which have the
SGX_FLAGS_EINITTOKEN_KEY attribute set.

There will be some devil in the details with respect to both of these
issues, but those discussions can follow later.  Addressing these two
issues will at least create an environment where the proposed in-tree
driver is equivalent in privacy and functionality to the out of tree
driver.

SGX is a remarkably complex piece of machinery.  Producing a useful
driver requires the consideration of a lot of issues which, in our
opinion, have not been fully represented in the discussions to date.

> /Jarkko

I hope the above is useful for framing future discussions.

Have a good remainder of the week.

Dr. Greg

As always,
Dr. G.W. Wettstein, Ph.D.   Enjellic Systems Development, LLC.
4206 N. 19th Ave.           Specializing in information infra-structure
Fargo, ND  58102            development.
PH: 701-281-1686
FAX: 701-281-3949           EMAIL: greg@enjellic.com
------------------------------------------------------------------------------
"I suppose that could could happen but he wouldn't know a Galois Field
 if it kicked him in the nuts."
                                -- Anonymous mathematician
                                   Resurrection.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-22 11:12           ` Dr. Greg
@ 2018-11-22 15:21             ` Andy Lutomirski
  2018-11-24 17:21               ` Jarkko Sakkinen
  2018-11-22 20:56             ` Andy Lutomirski
  1 sibling, 1 reply; 155+ messages in thread
From: Andy Lutomirski @ 2018-11-22 15:21 UTC (permalink / raw)
  To: Dr. Greg Wettstein
  Cc: Jarkko Sakkinen, X86 ML, Platform Driver, linux-sgx, Dave Hansen,
	Christopherson, Sean J, nhorman, npmccallum, Ayoun, Serge,
	shay.katz-zamir, haitao.huang, Andy Shevchenko, Thomas Gleixner,
	Svahn, Kai, mark.shanahan, Suresh Siddha, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, Darren Hart, Andy Shevchenko,
	LKML

On Thu, Nov 22, 2018 at 3:12 AM Dr. Greg <greg@enjellic.com> wrote:
>
> On Tue, Nov 20, 2018 at 02:04:42PM +0200, Jarkko Sakkinen wrote:
>
> Good morning to everyone, Happy Thanksgiving to those who are
> celebrating the holiday.
>
> > On Mon, Nov 19, 2018 at 08:59:24AM -0800, Andy Lutomirski wrote:
> > > The idea here is that, under normal circumstances, provisioning only
> > > runs once, or at least only runs rarely.  So, rather than the SDK
> > > running provisioning whenever it feels like doing so (which is the
> > > current behavior, I imagine, although I haven't looked), there would
> > > be a privileged program, perhaps a systemd unit that runs when needed,
> > > that produces the key material needed for remote attestation, and
> > > non-root users that need attestation would get the keying material
> > > from the provisioning service.  And the provisioning service could
> > > implement its own policy.  Ideally, the service wouldn't give the
> > > sealed keys to users at all but would, instead, just provide the
> > > entire attestation service over a UNIX socket, which would make
> > > provisioning capabilities revocable.
> > >
> > > Does this make sense?
>
> > Yes, it does for me at least now that you brought some context.
>
> Let me see if I can add a bit of additional context to the above to
> frame further discussion regarding two major needs of the driver
> before it lands.
>
> What Andy is describing is how the current system already works.  The
> driver is at the root of a fairly complex eco-system of code,
> cryptography and protocols that implement SGX functionality.  This
> software stack is known as the SGX Platform SoftWare (PSW) or SGX
> runtime.
>
> The Intel provided runtime is implemented in C++ and, depending on how
> you count it, clocks in at around 50+ KLOC.  All of this ends up as a
> single 1.8 megabyte binary named aesm_service that links against 35
> shared libraries and is run by systemd.
>
> This binary implements the functionality needed to load, initialize,
> run and attest enclaves.  It also implements communications with the
> Intel provisioning and attestation services which is needed to
> provision a private EPID key to the platform and to verify the status
> of an enclave attestation quote from a remote platform.
>
> In order to achieve the SGX/IAGO security model, a lot of this
> functionality is implemented by choreographing exchanges between six
> Intel supplied and signed enclaves.  Intel supplies source code to
> these enclaves and understanding how all of this works requires an
> understanding of that codebase as well.  To top if off there is also a
> 50K hunk of signed Java bytecode that gets stuffed into the Management
> Engine if you are interested in platform services.
>

It's very nice of Intel to supply source. Also, yikes, they wrote
their ME blob in Java?

> All of the above is what we wrote an independent implementation of, in
> straight C, that is capable of linking against the MUSL C library with
> only libelf and OpenSSL as dependencies.  We developed all of this to
> support a reasonably sophisticated multi-enclave SGX security
> application that implements modeling the runtime behavior of
> applications running on the Linux kernel.  That application uses an
> alternate enclave attestation and communications architecture that we
> independently developed.

How do you generate your root of trust for attestation if you don't
use Intel's service?  If I understand right, Intel's mechanism boils
down to Intel possessing something that is functionally equivalent to
a list of valid provisioning keys associated with genuine Intel chips.
(It could be literal provisioning keys, or keying material from which
the provisioning keys are derived, or even public keys for which the
private parts are derived from the provisioning keys.  But all of this
boils down to the CPU, via some enclaves, proving knowledge of the
provisioning key that is available when MRSIGNER is Intel.

I could imagine replacing this by running Intel's mechanism once to
generate a new root of trust for your own mechanism, or even by buying
a bunch of CPUs, determining their provisioning keys with MRSIGNER=Dr.
Greg, and enrolling those.  But I don't see any way to bootstrap an
attestation service on a CPU you've never physically possessed without
running *something* with MRSIGNER=Intel.

> Based on this experience, if the proposed driver lands in its current
> state, Linux mainline will have, at least from a privacy perspective,
> an inferior implementation of SGX.  In addition, we are not confident
> the driver will be useful to anything other then server class hardware
> and will be incapable of supporting virtually all of the existing SGX
> hardware in the field.

I'm a little bit puzzled by your privacy claims.  If an attacker
controls the kernel, then the secrets in your enclave may still be
secure, but you have very little privacy in terms of trying to prevent
the attacker from tying your communication to your physical machine.

> At a high level, addressing these issues is straight forward.  First,
> the driver needs to support authorization equivalent to that which is
> implemented in the current Intel Launch Enclave, ie. control over the
> SGX_FLAGS_PROVISION_KEY attribute.

I agree, hence my email :)

> Secondly, the driver needs to drop
> its prohibition against launch enclaves, ie. returning EINVAL when a
> request is made to initialize enclaves which have the
> SGX_FLAGS_EINITTOKEN_KEY attribute set.
>

Can you explain your use case for a launch enclave?  The current
driver won't allow you to supply an EINITTOKEN, so I'm not immediately
seeing what you would do with a launch token.  If you really do need
it, I suppose we could have 'unprivileged', 'provisioning', and
'launch' nodes, and maybe even 'launch_and_provision', but that's
starting to have some combinatorial issues.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-22 11:12           ` Dr. Greg
  2018-11-22 15:21             ` Andy Lutomirski
@ 2018-11-22 20:56             ` Andy Lutomirski
  2018-11-23 10:39               ` Dr. Greg
  1 sibling, 1 reply; 155+ messages in thread
From: Andy Lutomirski @ 2018-11-22 20:56 UTC (permalink / raw)
  To: Dr. Greg Wettstein
  Cc: Jarkko Sakkinen, X86 ML, Platform Driver, linux-sgx, Dave Hansen,
	Christopherson, Sean J, nhorman, npmccallum, Ayoun, Serge,
	shay.katz-zamir, haitao.huang, Andy Shevchenko, Thomas Gleixner,
	Svahn, Kai, mark.shanahan, Suresh Siddha, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, Darren Hart, Andy Shevchenko,
	LKML

On Thu, Nov 22, 2018 at 3:12 AM Dr. Greg <greg@enjellic.com> wrote:
> In addition, we are not confident
> the driver will be useful to anything other then server class hardware
> and will be incapable of supporting virtually all of the existing SGX
> hardware in the field.

I forgot to mention: I have a plain old retail Intel Celeron (I think
-- it's not in front of me right now) that has Flex LC.  I suspect
that, going forward, all new Intel CPUs will support Flex LC.  I
really wish that Intel would document all of the detailed capabilities
of all their CPUs somewhere.

There has been some talk of how the driver could support old CPUs.  It
would involve a rather different LE being signed by Intel, but it
should be more or less transparent to user code if it happens.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-22 20:56             ` Andy Lutomirski
@ 2018-11-23 10:39               ` Dr. Greg
  2018-11-24 16:45                 ` Jarkko Sakkinen
  0 siblings, 1 reply; 155+ messages in thread
From: Dr. Greg @ 2018-11-23 10:39 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Jarkko Sakkinen, X86 ML, Platform Driver, linux-sgx, Dave Hansen,
	Christopherson, Sean J, nhorman, npmccallum, Ayoun, Serge,
	shay.katz-zamir, haitao.huang, Andy Shevchenko, Thomas Gleixner,
	Svahn, Kai, mark.shanahan, Suresh Siddha, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, Darren Hart, Andy Shevchenko,
	LKML

On Thu, Nov 22, 2018 at 12:56:23PM -0800, Andy Lutomirski wrote:

Good morning to everyone.

> On Thu, Nov 22, 2018 at 3:12 AM Dr. Greg <greg@enjellic.com> wrote:
> > In addition, we are not confident
> > the driver will be useful to anything other then server class hardware
> > and will be incapable of supporting virtually all of the existing SGX
> > hardware in the field.

> I forgot to mention: I have a plain old retail Intel Celeron (I
> think -- it's not in front of me right now) that has Flex LC.  I
> suspect that, going forward, all new Intel CPUs will support Flex
> LC.  I really wish that Intel would document all of the detailed
> capabilities of all their CPUs somewhere.

Interesting, that contradicts the read we had gotten on FLC.

The only specific CPU's that we know of that are acknowledged to have
FLC are the XEON E series in support of the PCE/ECDSA attestation for
data-center use of SGX.

I'm assuming this is a really new system?  If so that matches our
experience with respect to the fact that SGX2/EDMM capable systems
slipped out quietly in early generation NUC SOC's.

Your sentinments are correct with respect to getting solid guidance on
hardware, it is a significant issue, particularly with respect to
SGX.

> There has been some talk of how the driver could support old CPUs.
> It would involve a rather different LE being signed by Intel, but it
> should be more or less transparent to user code if it happens.

I will reply to the LE and driver capability issues in my response to
your earlier e-mail so the thread does not diverge.

Jarkko, when this driver lands it will set the SGX ABI in stone for
Linux.  It would be very, very helpful to the development community if
there was some official guidance from Intel on whether or not FLC will
be a universal feature on all hardware and the date that is going to
happen or has happened.

If this turns out to be an OEM selectable issue via firmware
customizations, things will be even more problematic.

As things stand now, the proposed mainline SGX driver is going to be
useless for a lot of hardware that is out in the field.  Linux has
always had the reputation for supporting legacy hardware so this
directly contravenes that principal and needlessly so.

Dr. Greg

As always,
Dr. Greg Wettstein, Ph.D, Worker
IDfusion, LLC
4206 N. 19th Ave.           Implementing measured information privacy
Fargo, ND  58102            and integrity architectures.
PH: 701-281-1686
FAX: 701-281-3949           EMAIL: gw@idfusion.org
------------------------------------------------------------------------------
"Simplicity is prerequisite for reliability."
                                -- Edsger W. Dijkstra

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 06/23] x86/cpu/intel: Detect SGX support and update caps appropriately
  2018-11-21 18:17   ` Borislav Petkov
@ 2018-11-24 13:54     ` Jarkko Sakkinen
  0 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-24 13:54 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: x86, platform-driver-x86, linux-sgx, dave.hansen,
	sean.j.christopherson, nhorman, npmccallum, serge.ayoun,
	shay.katz-zamir, haitao.huang, andriy.shevchenko, tglx,
	kai.svahn, mark.shanahan, luto, Ingo Molnar, H. Peter Anvin,
	Konrad Rzeszutek Wilk, David Woodhouse, Kirill A. Shutemov,
	David Wang, Levin, Alexander (Sasha Levin),
	Jia Zhang, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Wed, Nov 21, 2018 at 07:17:28PM +0100, Borislav Petkov wrote:
> I see the build failure here has been pointed out already but lemme
> repeat it out for another reason:
> 
> It is very important that no patch we merge breaks bisectability -
> please build every patch before sending:

Yep, the patch ordering was incorrect. I agree and will check this
for the next version. Thanks for your remarks.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-20 11:15     ` Dr. Greg
@ 2018-11-24 16:15       ` Jarkko Sakkinen
  2018-11-24 19:24         ` Dr. Greg
  0 siblings, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-24 16:15 UTC (permalink / raw)
  To: Dr. Greg
  Cc: Andy Lutomirski, X86 ML, Platform Driver, linux-sgx, Dave Hansen,
	Christopherson, Sean J, nhorman, npmccallum, Ayoun, Serge,
	shay.katz-zamir, haitao.huang, Andy Shevchenko, Thomas Gleixner,
	Svahn, Kai, mark.shanahan, Suresh Siddha, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, Darren Hart, andy, LKML

On Tue, Nov 20, 2018 at 05:15:08AM -0600, Dr. Greg wrote:
> Malware would not necessarily need the Intel attestation service.
> Once access to the PROVISION bit is available, malware teams could
> simply build their own attestation service.

AFAIK not possible as they wouldn't have access to the root provisioning
key. Can be confirmed from the SDM's key derivation table (41-56).

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-23 10:39               ` Dr. Greg
@ 2018-11-24 16:45                 ` Jarkko Sakkinen
  2018-11-28  5:08                   ` Jarkko Sakkinen
  0 siblings, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-24 16:45 UTC (permalink / raw)
  To: Dr. Greg
  Cc: Andy Lutomirski, X86 ML, Platform Driver, linux-sgx, Dave Hansen,
	Christopherson, Sean J, nhorman, npmccallum, Ayoun, Serge,
	shay.katz-zamir, haitao.huang, Andy Shevchenko, Thomas Gleixner,
	Svahn, Kai, mark.shanahan, Suresh Siddha, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, Darren Hart, Andy Shevchenko,
	LKML

On Fri, Nov 23, 2018 at 04:39:23AM -0600, Dr. Greg wrote:
> Jarkko, when this driver lands it will set the SGX ABI in stone for
> Linux.  It would be very, very helpful to the development community if
> there was some official guidance from Intel on whether or not FLC will
> be a universal feature on all hardware and the date that is going to
> happen or has happened.

I seriously don't know but I can take this message to the mothership...

> If this turns out to be an OEM selectable issue via firmware
> customizations, things will be even more problematic.

Point taken.

> As things stand now, the proposed mainline SGX driver is going to be
> useless for a lot of hardware that is out in the field.  Linux has
> always had the reputation for supporting legacy hardware so this
> directly contravenes that principal and needlessly so.

I do get your point about supporting the legacy. I'm wondering if this
is still a deal breaker for Linux or not.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-22 15:21             ` Andy Lutomirski
@ 2018-11-24 17:21               ` Jarkko Sakkinen
  2018-11-24 20:13                 ` Dr. Greg
  2018-11-25 14:53                 ` Jarkko Sakkinen
  0 siblings, 2 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-24 17:21 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Dr. Greg Wettstein, X86 ML, Platform Driver, linux-sgx,
	Dave Hansen, Christopherson, Sean J, nhorman, npmccallum, Ayoun,
	Serge, shay.katz-zamir, haitao.huang, Andy Shevchenko,
	Thomas Gleixner, Svahn, Kai, mark.shanahan, Suresh Siddha,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin, Darren Hart,
	Andy Shevchenko, LKML

On Thu, Nov 22, 2018 at 07:21:08AM -0800, Andy Lutomirski wrote:
> > At a high level, addressing these issues is straight forward.  First,
> > the driver needs to support authorization equivalent to that which is
> > implemented in the current Intel Launch Enclave, ie. control over the
> > SGX_FLAGS_PROVISION_KEY attribute.
> 
> I agree, hence my email :)

Started to scratch my head that is it really an issue that any enclave
can provision in the end?

Direct quote from your first response:

"In particular, the ability to run enclaves with the provisioning bit set
is somewhat sensitive, since it effectively allows access to a stable
fingerprint of the system."

As can be seen from the key derivation table this does not exactly hold
so you should refine your original argument before we can consider any
type of change.

I just don't see what it is so wrong for any enclave to be able to tell
that it really is an enclave.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-24 16:15       ` Jarkko Sakkinen
@ 2018-11-24 19:24         ` Dr. Greg
  2018-11-26 19:39           ` Jarkko Sakkinen
  0 siblings, 1 reply; 155+ messages in thread
From: Dr. Greg @ 2018-11-24 19:24 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Andy Lutomirski, X86 ML, Platform Driver, linux-sgx, Dave Hansen,
	Christopherson, Sean J, nhorman, npmccallum, Ayoun, Serge,
	shay.katz-zamir, haitao.huang, Andy Shevchenko, Thomas Gleixner,
	Svahn, Kai, mark.shanahan, Suresh Siddha, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, Darren Hart, andy, LKML

On Sat, Nov 24, 2018 at 08:15:21AM -0800, Jarkko Sakkinen wrote:

> On Tue, Nov 20, 2018 at 05:15:08AM -0600, Dr. Greg wrote:
> > Malware would not necessarily need the Intel attestation service.
> > Once access to the PROVISION bit is available, malware teams could
> > simply build their own attestation service.

> AFAIK not possible as they wouldn't have access to the root
> provisioning key. Can be confirmed from the SDM's key derivation
> table (41-56).

What provisioning and attestation is all about is establishing an
identity binding for a platform in question.  The standard Intel
service binds the identity of a platform to an EPID private key.

With access to the SGX_FLAGS_PROVISION_BIT an enclave can generate a
perpetual identity for a platform based on the identity modulus
signature (MRSIGNER) of the key that signs the signature structure of
the enclave.  Without access to the root provisioning key a security
quorum or group has to be implemented via a subscription or enrollment
model but that is arguably not much of an obstacle.

That is pretty much the way standard botware works now.

Without provisions for cryptographically secure authorization and
policy enforcement in the driver, we will be creating infrastructure
for a new generation of botware/malware whose mothership will know
that a participating platform is running with full confidentiality and
integrity protections.

> /Jarkko

Dr. Greg

As always,
Dr. G.W. Wettstein, Ph.D.   Enjellic Systems Development, LLC.
4206 N. 19th Ave.           Specializing in information infra-structure
Fargo, ND  58102            development.
PH: 701-281-1686
FAX: 701-281-3949           EMAIL: greg@enjellic.com
------------------------------------------------------------------------------
"Remember that when you take down the fishhouse you can't put
 the minnows back into the lake, so throw them out on the ice.
 Make sure you stomp on any of the live ones so they don't suffer."
                                -- Fritz Wettstein
                                   At the lake

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-24 17:21               ` Jarkko Sakkinen
@ 2018-11-24 20:13                 ` Dr. Greg
  2018-11-26 21:15                   ` Jarkko Sakkinen
  2018-11-25 14:53                 ` Jarkko Sakkinen
  1 sibling, 1 reply; 155+ messages in thread
From: Dr. Greg @ 2018-11-24 20:13 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Andy Lutomirski, X86 ML, Platform Driver, linux-sgx, Dave Hansen,
	Christopherson, Sean J, nhorman, npmccallum, Ayoun, Serge,
	shay.katz-zamir, haitao.huang, Andy Shevchenko, Thomas Gleixner,
	Svahn, Kai, mark.shanahan, Suresh Siddha, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, Darren Hart, Andy Shevchenko,
	LKML

On Sat, Nov 24, 2018 at 09:21:14AM -0800, Jarkko Sakkinen wrote:
> On Thu, Nov 22, 2018 at 07:21:08AM -0800, Andy Lutomirski wrote:
> > > At a high level, addressing these issues is straight forward.  First,
> > > the driver needs to support authorization equivalent to that which is
> > > implemented in the current Intel Launch Enclave, ie. control over the
> > > SGX_FLAGS_PROVISION_KEY attribute.
> > 
> > I agree, hence my email :)

> Started to scratch my head that is it really an issue that any
> enclave can provision in the end?
>
> Direct quote from your first response:
>
> "In particular, the ability to run enclaves with the provisioning
> bit set is somewhat sensitive, since it effectively allows access to
> a stable fingerprint of the system."
>
> As can be seen from the key derivation table this does not exactly
> hold so you should refine your original argument before we can
> consider any type of change.
>
> I just don't see what it is so wrong for any enclave to be able to
> tell that it really is an enclave.

This isn't about an enclave being able to tell that it is really an
enclave.  As I noted in my previous reply, access to the provisioning
bit allows an enclave author to create a perpetual hardware identifier
for a platform based on a signing key of their choosing, along with a
few other incidentals, all of which are completely under the control
of the enclave author.

The Intel SGX architects, at least originally, felt strongly enough
about this issue to use the Launch Enclave to implement
cryptographically secure policy control over access to the
SGX_FLAGS_PROVISION_KEY attribute.  See the 'if' clause that begins on
line 219 of psw/ae/le/launch_enclave.cpp in the current HEAD of the
Linux SGX SDK which is currently bf22963411.

Let me describe an entirely contrived example but one which is
representative of the threat.

I'm a web-site that wants to consistently and reliably track platforms
that visit a site.  Without cryptographically secure policy
enforcement in the SGX eco-system I push an enclave to the platform
which only computes the MRSIGNER specific derived provisioning key and
returns it to the web-site.

From that point onward I will always be able to identify the platform,
as long as the enclave can be executed on the platform.  Unlike
cookies, there is nothing to delete since the aggressor enclave only
needs to exist long enough to be run and generate the derived
provisioning key, no trace of the fingerprinting remains thereafter.

If the proposed driver is to be a functional replacement for the
existing SGX eco-system it needs to offer privacy and platform
security guarantees at least comparable to what is available on a
non-FLC system.  That means at least some semblance of
cryptographically secure policy management on at least two fronts.

We can propose a general architecture that we believe satisfies these
needs without compromising the upstream integrity of the kernel with
respect to free and open systems.  A solution that could arguably
protect user's investment in current non-FLC hardware as well.

We would be happy to articulate the outline of that but I don't want
to waste anyone's time, including ours, if everyone's mind has been
made up as to what the driver should and should not do.

We are clearly capable of making the proposed driver do whatever we
want it to do.  Our concern is that Linux security architects that
choose to use this technology have the best tools available to them,
within the constraints of upstream sensibility, without whacking on
the kernel.

As it stands now the driver has both privacy and potential system
security issues which translate into useability and desirability
implications for SGX on Linux moving forward.

> /Jarkko

Have a good remainder of the weekend.

I need to get back to my MIG welder out in the shop.

Dr. Greg

As always,
Dr. G.W. Wettstein, Ph.D.   Enjellic Systems Development, LLC.
4206 N. 19th Ave.           Specializing in information infra-structure
Fargo, ND  58102            development.
PH: 701-281-1686
FAX: 701-281-3949           EMAIL: greg@enjellic.com
------------------------------------------------------------------------------
"Attendants at a service station in Eunice, Louisiana, handed more than
 $100 to a naked man who claimed to have a gun in his pocket."
                                -- Unknown


^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-24 17:21               ` Jarkko Sakkinen
  2018-11-24 20:13                 ` Dr. Greg
@ 2018-11-25 14:53                 ` Jarkko Sakkinen
  2018-11-25 16:22                   ` Andy Lutomirski
  1 sibling, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-25 14:53 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Dr. Greg Wettstein, X86 ML, Platform Driver, linux-sgx,
	Dave Hansen, Christopherson, Sean J, nhorman, npmccallum, Ayoun,
	Serge, shay.katz-zamir, haitao.huang, Andy Shevchenko,
	Thomas Gleixner, Svahn, Kai, mark.shanahan, Suresh Siddha,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin, Darren Hart,
	Andy Shevchenko, LKML

On Sat, Nov 24, 2018 at 09:21:14AM -0800, Jarkko Sakkinen wrote:
> On Thu, Nov 22, 2018 at 07:21:08AM -0800, Andy Lutomirski wrote:
> > > At a high level, addressing these issues is straight forward.  First,
> > > the driver needs to support authorization equivalent to that which is
> > > implemented in the current Intel Launch Enclave, ie. control over the
> > > SGX_FLAGS_PROVISION_KEY attribute.
> > 
> > I agree, hence my email :)
> 
> Started to scratch my head that is it really an issue that any enclave
> can provision in the end?
> 
> Direct quote from your first response:
> 
> "In particular, the ability to run enclaves with the provisioning bit set
> is somewhat sensitive, since it effectively allows access to a stable
> fingerprint of the system."
> 
> As can be seen from the key derivation table this does not exactly hold
> so you should refine your original argument before we can consider any
> type of change.
> 
> I just don't see what it is so wrong for any enclave to be able to tell
> that it really is an enclave.

I mean I can understand why Greg wants LE although I don't understand
what benefit does it bring to anyone to lock in for enclave to allow
to identify itself.

What you are proposing does not really bring any additional security if
we consider a threat model where the kernel is an adversary but it makes
the software stack more clanky to use.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-25 14:53                 ` Jarkko Sakkinen
@ 2018-11-25 16:22                   ` Andy Lutomirski
  2018-11-25 18:55                     ` Dr. Greg
  2018-11-26 21:51                     ` Jarkko Sakkinen
  0 siblings, 2 replies; 155+ messages in thread
From: Andy Lutomirski @ 2018-11-25 16:22 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Andy Lutomirski, Dr. Greg Wettstein, X86 ML, Platform Driver,
	linux-sgx, Dave Hansen, Christopherson, Sean J, nhorman,
	npmccallum, Ayoun, Serge, shay.katz-zamir, haitao.huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko, LKML


>> On Nov 25, 2018, at 6:53 AM, Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> wrote:
>> 
>> On Sat, Nov 24, 2018 at 09:21:14AM -0800, Jarkko Sakkinen wrote:
>> On Thu, Nov 22, 2018 at 07:21:08AM -0800, Andy Lutomirski wrote:
>>>> At a high level, addressing these issues is straight forward.  First,
>>>> the driver needs to support authorization equivalent to that which is
>>>> implemented in the current Intel Launch Enclave, ie. control over the
>>>> SGX_FLAGS_PROVISION_KEY attribute.
>>> 
>>> I agree, hence my email :)
>> 
>> Started to scratch my head that is it really an issue that any enclave
>> can provision in the end?
>> 
>> Direct quote from your first response:
>> 
>> "In particular, the ability to run enclaves with the provisioning bit set
>> is somewhat sensitive, since it effectively allows access to a stable
>> fingerprint of the system."
>> 
>> As can be seen from the key derivation table this does not exactly hold
>> so you should refine your original argument before we can consider any
>> type of change.
>> 
>> I just don't see what it is so wrong for any enclave to be able to tell
>> that it really is an enclave.
> 
> I mean I can understand why Greg wants LE although I don't understand
> what benefit does it bring to anyone to lock in for enclave to allow
> to identify itself.
> 
> What you are proposing does not really bring any additional security if
> we consider a threat model where the kernel is an adversary but it makes
> the software stack more clanky to use.

Agreed. What I’m proposing adds additional security if the kernel is *not* compromised.

There are other ways to accomplish it that might be better in some respects.  For example, there could be /dev/sgx and /dev/sgx_rights/provision.  The former exposes the whole sgx API, except that it doesn’t allow provisioning by default. The latter does nothing by itself. To run a provisioning enclave, you open both nodes, then do something like:

ioctl(sgx, SGX_IOC_ADD_RIGHT, sgx_provisioning);

This requires extra syscalls, but it doesn’t have the combinatorial explosion problem.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-25 16:22                   ` Andy Lutomirski
@ 2018-11-25 18:55                     ` Dr. Greg
  2018-11-25 23:51                       ` Jarkko Sakkinen
       [not found]                       ` <D45BC005-5064-4C75-B486-4E43C454E2F6@amacapital.net>
  2018-11-26 21:51                     ` Jarkko Sakkinen
  1 sibling, 2 replies; 155+ messages in thread
From: Dr. Greg @ 2018-11-25 18:55 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Jarkko Sakkinen, Andy Lutomirski, Dr. Greg Wettstein, X86 ML,
	Platform Driver, linux-sgx, Dave Hansen, Christopherson, Sean J,
	nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir, haitao.huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko, LKML

On Sun, Nov 25, 2018 at 08:22:35AM -0800, Andy Lutomirski wrote:

Good morning to everyone, I hope the weekend continues to proceed
well.

Proposal follows below for kernel based policy management of enclaves
if people want to skip forward.

> >> On Nov 25, 2018, at 6:53 AM, Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> wrote:
> >> 
> >> On Sat, Nov 24, 2018 at 09:21:14AM -0800, Jarkko Sakkinen wrote:
> >> On Thu, Nov 22, 2018 at 07:21:08AM -0800, Andy Lutomirski wrote:
> >>>> At a high level, addressing these issues is straight forward.  First,
> >>>> the driver needs to support authorization equivalent to that which is
> >>>> implemented in the current Intel Launch Enclave, ie. control over the
> >>>> SGX_FLAGS_PROVISION_KEY attribute.
> >>> 
> >>> I agree, hence my email :)
> >> 
> >> Started to scratch my head that is it really an issue that any enclave
> >> can provision in the end?
> >> 
> >> Direct quote from your first response:
> >> 
> >> "In particular, the ability to run enclaves with the provisioning bit set
> >> is somewhat sensitive, since it effectively allows access to a stable
> >> fingerprint of the system."
> >> 
> >> As can be seen from the key derivation table this does not exactly hold
> >> so you should refine your original argument before we can consider any
> >> type of change.
> >> 
> >> I just don't see what it is so wrong for any enclave to be able to tell
> >> that it really is an enclave.

> > I mean I can understand why Greg wants LE although I don't understand
> > what benefit does it bring to anyone to lock in for enclave to allow
> > to identify itself.
> > 
> > What you are proposing does not really bring any additional security if
> > we consider a threat model where the kernel is an adversary but it makes
> > the software stack more clanky to use.

> Agreed. What I'm proposing adds additional security if the kernel is
> *not* compromised.

Let me use this to stress a concept that I believe is important in
this discussion.

SGX is enabling technology that allows developers to create software
architectures that will deliver their stated security and privacy
guarantees irrespective of platform state.  It does this by linking
'islands' of execution (enclaves) together through a web of
cryptographic guarantees.

The notion of a launch enclave is critical to establishing these
guarantees.  As soon as the kernel becomes involved in implementing
SGX security policy the architecture becomes vulnerable to kernel
and/or privilege modification attacks.

We've talked at length about the provisioning bit, I won't go into
details unless people are interested, but the EPID provisioning
protocol implements an SGX mediated cryptographic contract that a
perpetual platform identifier will not be disclosed to anyone but
Intel.  The launch enclave is critical to that guarantee.

It is completely understandable why a locked down, (non-FLC) hardware
platform, is undesirable in this community.  That doesn't mean that a
launch enclave as a concept is unneeded or necessarily evil.

In an FLC environment the kernel assumes responsibility for SGX
privacy and security.  This means that we need to do at least as well
with a kernel based model as to what is currently available.

> There are other ways to accomplish it that might be better in some
> respects.  For example, there could be /dev/sgx and
> /dev/sgx_rights/provision.  The former exposes the whole sgx API,
> except that it doesn???t allow provisioning by default. The latter
> does nothing by itself. To run a provisioning enclave, you open both
> nodes, then do something like:
>
> ioctl(sgx, SGX_IOC_ADD_RIGHT, sgx_provisioning);
>
> This requires extra syscalls, but it doesn't have the combinatorial
> explosion problem.

Here is a proposal for the driver to add the needed policy control
that is 'SGXy' in nature.  The 'SGXy' way is to use MRSIGNER values as
the currency for security policy management.

The driver should establish the equivalent of three linked lists,
maintainable via /sysfs pseudo-files or equivalent plumbing.  The
lists are referenced by the kernel to enforce the following policies.

1.) The right to initialize an enclave without special attributes.

2.) The right to initialize an enclave with the PROVISION_KEY attribute set.

3.) The right to initialize an enclave with the LICENSE_KEY attribute set.

The lists are populated with MRSIGNER values of enclaves that are
allowed to initialize under the specified conditions.

The driver should either establish a 'seal' file or value,
ie. MRSIGNER value of all zero's, that once written will not allow
further modifications of the list(s).  This will allow
cryptographically guaranteed policies to be setup at early boot that
will limit the ability of subsequent DAC compromises to affect policy
management.

The lists are obviously vulnerable to a kernel compromise but the
vulnerability scope is significantly limited vs. 'can I get root or
some other userid'.  If we are really concerned about the scope of
that vulnerability there could be an option on TPM based systems to
verify a hash value over the lists once sealed on each enclave
initialization.  We have already conceded that EINIT isn't going to be
any type of speed daemon.

On an FLC system the driver verifies that the submitted enclave has an
MRSIGNER value on one of the lists consistent with the attributes of
the enclave before loading the value into the identity modulus
signature registers.

In this model, I would argue that the driver does not need to
arbitrarily exclude launch enclaves as it does now, since the kernel
has the ability to specify acceptable launch enclaves.  The driver API
can alaso continue to accept an EINITTOKEN which maintains
compatibility with the current ABI.  Punishment can be inflicted on
non-FLC hardware owners by issueing EINVAL if an EINITTOKEN is
specified on platforms with fixed launch keys.

This also has the effect of allowing multiple launch enclaves at the
platform owner's discretion.  I know there was some sentiment, and
Jarkko had code, that used a launch enclave at a fixed location such
as /lib/firmware.  That has the disadvantage of requiring that the
kernel know about all the different ways that a launch enclave might
be used or setup.  It also establishes a cryptographic rather then a
filesystem based guarantee on the launch enclave being used.

If the lists are empty the kernel simply proceeds as it does now and
loads any enclave submitted to it.

I believe this architecture has a number of merits.  It largely
preserves compatibility with current PSW's and provides a mechanism
for cryptographically enforced policy that is consistent with the SGX
architecture.

I need to get Christmas lights put up on the house for the squirrels
to eat so I will leave this proposal open for debate.

Have a good remainder of the weekend or whats left of it.

Dr. Greg

As always,
Dr. G.W. Wettstein, Ph.D.   Enjellic Systems Development, LLC.
4206 N. 19th Ave.           Specializing in information infra-structure
Fargo, ND  58102            development.
PH: 701-281-1686
FAX: 701-281-3949           EMAIL: greg@enjellic.com
------------------------------------------------------------------------------
"Some of them are.  A surprising number aren't.  A personal favorite of
 mine was the log from a cracker who couldn't figure out how to untar
 and install the trojan package he'd ftped onto the machine.  He tried a
 few times, and then eventually gave up and logged out."
                                -- Nat Lanza

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-25 18:55                     ` Dr. Greg
@ 2018-11-25 23:51                       ` Jarkko Sakkinen
       [not found]                       ` <D45BC005-5064-4C75-B486-4E43C454E2F6@amacapital.net>
  1 sibling, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-25 23:51 UTC (permalink / raw)
  To: Dr. Greg, Andy Lutomirski, Andy Lutomirski
  Cc: X86 ML, Platform Driver, linux-sgx, Dave Hansen, Christopherson,
	Sean J, nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir,
	haitao.huang, Andy Shevchenko, Thomas Gleixner, Svahn, Kai,
	mark.shanahan, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko, LKML

On Sun, Nov 25, 2018 at 12:55:24PM -0600, Dr. Greg wrote:
> Good morning to everyone, I hope the weekend continues to proceed
> well.

Thank you, wish the same. Surviving from jetlag after flying from
Finland to Portland yesterday..

Greg, Andy, I'll check your remarks with thought after I'm done with v18
i.e. have less things to multitask with. Is that OK for you? Probably
v18 won't be the last the version anyway.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
       [not found]                       ` <D45BC005-5064-4C75-B486-4E43C454E2F6@amacapital.net>
@ 2018-11-26  0:37                         ` Andy Lutomirski
  2018-11-26 11:00                           ` Dr. Greg
  0 siblings, 1 reply; 155+ messages in thread
From: Andy Lutomirski @ 2018-11-26  0:37 UTC (permalink / raw)
  To: Dr. Greg
  Cc: Jarkko Sakkinen, Andy Lutomirski, X86 ML, Platform Driver,
	linux-sgx, Dave Hansen, Christopherson, Sean J, nhorman,
	npmccallum, Ayoun, Serge, shay.katz-zamir, haitao.huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko, LKML

Bah, I hit send on a partially written draft. I’ll try again soon.

--Andy

> On Nov 25, 2018, at 1:59 PM, Andy Lutomirski <luto@amacapital.net> wrote:
> 
> 
> 
>> On Nov 25, 2018, at 10:55 AM, Dr. Greg <greg@enjellic.com> wrote:
>> 
> 
>> 
>> 
>> The notion of a launch enclave is critical to establishing these
>> guarantees.  As soon as the kernel becomes involved in implementing
>> SGX security policy the architecture becomes vulnerable to kernel
>> and/or privilege modification attacks.
>> 
>> We've talked at length about the provisioning bit, I won't go into
>> details unless people are interested, but the EPID provisioning
>> protocol implements an SGX mediated cryptographic contract that a
>> perpetual platform identifier will not be disclosed to anyone but
>> Intel.  
> 
> As a reviewer, and as an occasional academic cryptographer, I need to put my foot down here.  This is inaccurate.
> 
> There is an SGX-mediated contract that says:
> 
> 1. For any given public key p, a perpetual platform identifier ID_p exists and will only be disclosed to the holder of the corresponding private key p_priv or to someone to whom the private key holder permits (intentionally or otherwise) to use that identifier.
> 
> 2. The ability described in #1 is available to anyone whom the kernel and launch enclave (if the MSRs are locked ) permits (intentionally or otherwise) to use it.
> 
> No, I have no clue why Intel did it this way.  I consider it to be a mistake.
> 
>> The launch enclave is critical to that guarantee.
>> 
>> It is completely understandable why a locked down, (non-FLC) hardware
>> platform, is undesirable in this community.  That doesn't mean that a
>> launch enclave as a concept is unneeded or necessarily evil.
>> 
>> In an FLC environment the kernel assumes responsibility for SGX
>> privacy and security.  This means that we need to do at least as well
>> with a kernel based model as to what is currently available.
>> 
>>> There are other ways to accomplish it that might be better in some
>>> respects.  For example, there could be /dev/sgx and
>>> /dev/sgx_rights/provision.  The former exposes the whole sgx API,
>>> except that it doesn???t allow provisioning by default. The latter
>>> does nothing by itself. To run a provisioning enclave, you open both
>>> nodes, then do something like:
>>> 
>>> ioctl(sgx, SGX_IOC_ADD_RIGHT, sgx_provisioning);
>>> 
>>> This requires extra syscalls, but it doesn't have the combinatorial
>>> explosion problem.
>> 
>> Here is a proposal for the driver to add the needed policy control
>> that is 'SGXy' in nature.  The 'SGXy' way is to use MRSIGNER values as
>> the currency for security policy management.
>> 
>> The driver should establish the equivalent of three linked lists,
>> maintainable via /sysfs pseudo-files or equivalent plumbing.  The
>> lists are referenced by the kernel to enforce the following policies.
>> 
>> 1.) The right to initialize an enclave without special attributes.
>> 
>> 2.) The right to initialize an enclave with the PROVISION_KEY attribute set.
>> 
>> 3.) The right to initialize an enclave with the LICENSE_KEY attribute set.
>> 
>> The lists are populated with MRSIGNER values of enclaves that are
>> allowed to initialize under the specified conditions.
> 
> NAK because this is insufficient.  You’re thinking of a model in which SGX-like protection is all that’s needed.  This is an inadequate model of the real world.  The attack I’m most concerned about wrt provisioning is an attack in which an unauthorized user is permitted 
> 
> The use case I see for attestation *privacy*
> 
>> 
>> The driver should either establish a 'seal' file or value,
>> ie. MRSIGNER value of all zero's, that once written will not allow
>> further modifications of the list(s).  This will allow
>> cryptographically guaranteed policies to be setup at early boot that
>> will limit the ability of subsequent DAC compromises to affect policy
>> management.
>> 
>> The lists are obviously vulnerable to a kernel compromise but the
>> vulnerability scope is significantly limited vs. 'can I get root or
>> some other userid'.  If we are really concerned about the scope of
>> that vulnerability there could be an option on TPM based systems to
>> verify a hash value over the lists once sealed on each enclave
>> initialization.  We have already conceded that EINIT isn't going to be
>> any type of speed daemon.
>> 
>> On an FLC system the driver verifies that the submitted enclave has an
>> MRSIGNER value on one of the lists consistent with the attributes of
>> the enclave before loading the value into the identity modulus
>> signature registers.
>> 
>> In this model, I would argue that the driver does not need to
>> arbitrarily exclude launch enclaves as it does now, since the kernel
>> has the ability to specify acceptable launch enclaves.  The driver API
>> can alaso continue to accept an EINITTOKEN which maintains
>> compatibility with the current ABI.  Punishment can be inflicted on
>> non-FLC hardware owners by issueing EINVAL if an EINITTOKEN is
>> specified on platforms with fixed launch keys.
>> 
>> This also has the effect of allowing multiple launch enclaves at the
>> platform owner's discretion.  I know there was some sentiment, and
>> Jarkko had code, that used a launch enclave at a fixed location such
>> as /lib/firmware.  That has the disadvantage of requiring that the
>> kernel know about all the different ways that a launch enclave might
>> be used or setup.  It also establishes a cryptographic rather then a
>> filesystem based guarantee on the launch enclave being used.
>> 
>> If the lists are empty the kernel simply proceeds as it does now and
>> loads any enclave submitted to it.
>> 
>> I believe this architecture has a number of merits.  It largely
>> preserves compatibility with current PSW's and provides a mechanism
>> for cryptographically enforced policy that is consistent with the SGX
>> architecture.
>> 
>> I need to get Christmas lights put up on the house for the squirrels
>> to eat so I will leave this proposal open for debate.
>> 
>> Have a good remainder of the weekend or whats left of it.
>> 
>> Dr. Greg
>> 
>> As always,
>> Dr. G.W. Wettstein, Ph.D.   Enjellic Systems Development, LLC.
>> 4206 N. 19th Ave.           Specializing in information infra-structure
>> Fargo, ND  58102            development.
>> PH: 701-281-1686
>> FAX: 701-281-3949           EMAIL: greg@enjellic.com
>> ------------------------------------------------------------------------------
>> "Some of them are.  A surprising number aren't.  A personal favorite of
>> mine was the log from a cracker who couldn't figure out how to untar
>> and install the trojan package he'd ftped onto the machine.  He tried a
>> few times, and then eventually gave up and logged out."
>>                               -- Nat Lanza

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-26  0:37                         ` Andy Lutomirski
@ 2018-11-26 11:00                           ` Dr. Greg
  2018-11-26 18:22                             ` Andy Lutomirski
  2018-11-26 22:16                             ` Jarkko Sakkinen
  0 siblings, 2 replies; 155+ messages in thread
From: Dr. Greg @ 2018-11-26 11:00 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Jarkko Sakkinen, Andy Lutomirski, X86 ML, Platform Driver,
	linux-sgx, Dave Hansen, Christopherson, Sean J, nhorman,
	npmccallum, Ayoun, Serge, shay.katz-zamir, haitao.huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko, LKML

On Sun, Nov 25, 2018 at 04:37:00PM -0800, Andy Lutomirski wrote:

> Bah, I hit send on a partially written draft. I???ll try again soon.
> 
> --Andy

Your first issue seems to be complete so I will respond to that in
order to make sure we are not talking past one another.

> > On Nov 25, 2018, at 1:59 PM, Andy Lutomirski <luto@amacapital.net> wrote:
> >> On Nov 25, 2018, at 10:55 AM, Dr. Greg <greg@enjellic.com> wrote:
> >> 
> >> The notion of a launch enclave is critical to establishing these
> >> guarantees.  As soon as the kernel becomes involved in implementing
> >> SGX security policy the architecture becomes vulnerable to kernel
> >> and/or privilege modification attacks.
> >> 
> >> We've talked at length about the provisioning bit, I won't go into
> >> details unless people are interested, but the EPID provisioning
> >> protocol implements an SGX mediated cryptographic contract that a
> >> perpetual platform identifier will not be disclosed to anyone but
> >> Intel.  

> As a reviewer, and as an occasional academic cryptographer, I need
> to put my foot down here.  This is inaccurate.

I certainly wouldn't try to engage in a debate at the level of
academic cryptography, so I want to clarify that I was speaking
specifically with respect to the ability to use the Intel supplied
Platform Certification Enclave (PCE) to obtain a perpetual platform
identifier.

There could certainly be an academic level weakness in SGX, or in the
provisioning protocol, but at the end of the day the important issue
seems to be whether or not a PCE enclave can be exploited by anyone
with execution access to the enclave to generate a perpetual
identifier for a platform.

> There is an SGX-mediated contract that says:
>
> 1. For any given public key p, a perpetual platform identifier ID_p
> exists and will only be disclosed to the holder of the corresponding
> private key p_priv or to someone to whom the private key holder
> permits (intentionally or otherwise) to use that identifier.
>
> 2. The ability described in #1 is available to anyone whom the
> kernel and launch enclave (if the MSRs are locked ) permits
> (intentionally or otherwise) to use it.

Let me see if I can respond directly to point two as it seems the most
important.

In the EPID provisioning model, the PCE and the ProVisioning Enclave
(PVE) both have posession of the PROVISION attribute and thus access
to the derivation of an MRSIGNER specific provisioning key.

The Intel supplied launch enclave (LE) specifically denies
initialization of enclaves which have the PROVISION attribute set,
with the exception of enclaves whose MRSIGNER values match those of
the keys that Intel uses to sign the PCE and PVE enclaves.  See line
219 of psw/ae/le/launch_enclave.cpp in the Intel SDK.

In the message one phase of the provisioning protocol Intel supplies
the platform with a 3K RSA public key (PEK).  The identity of that key
is confirmed by an ECC256 based signature over the key.  Intel embeds
the public gx and gy curve points for the signature key in their SDK,
see ae/data/constants/linux/peksk_pub.hh.

The PVE verifies the signature of the PEK and generates a SHA256
verification hash over a message containing the key and uses that as
the data field in an attestation report that is generated against the
target information for the PCE.  The PVE rejects generation of the
report if the PCE target information does not have the PROVISION
attribute set.  See line 124 of psw/ae/pve/provision_msg1.cpp.

This report, along with the PEK, is submitted to the PCE enclave in
order to generate the Platform Provisioning IDentity (PPID), which is
the privacy critical identifier.  The PCE verifies the report
generated by the PVE and rejects the request to generate the PPID if
the report was generated by an enclave that was not initialized with
the PROVISION bit set, see line 109 of psw/ae/pce/pce.cpp.

The PCE enclave then recomputes the message hash using the PEK that it
is provided and verifies that the value matches the value in the data
field of the attestation report from the PVE enclave.  If the values
do not match the PPID generation request is denied.  The PCE enclave
then encrypts the PPID with the PEK key and the encrypted PPID is
returned to Intel to use as the platform identifier.

The PPID is the CMAC over a 16 byte null message which uses a derived
provisioning key based on CPUSVN and ISVSVN values set to zero.  See
the get_ppid() function in psw/ae/pce/pce_helper.cpp.

I believe this effectively denies the ability of anyone other then
Intel, who holds the private portion of the ECC256 signature key used
to authenticate the PEK, from using the PCE enclave to generate a
platform identifier.

As I conceded above, there could be an academic deficiency in all
this, I'm not qualified to comment.  I believe there is a reasonably
solid functional guarantee that on a locked platform the process
cannot be easily subverted by a privacy aggressor.

We contend that the model we propose below can also deliver this
guarantee as long as ring 0 privileges are not compromised by an
aggressor, which is the best that an FLC platform can do.

Once again, the important design factor in all of this is the premise
that the launch enclave will not allow enclaves other then the PCE and
PVE to access the PROVISION bit.  Hence my comments about SGX being
about establishing islands of trust and the negotiation of security
contexts between those islands of trust.

> No, I have no clue why Intel did it this way.  I consider it to be a
> mistake.

Are you referring to there being a mistake in the trust relationships
that the provisioning protocol implements or the overall concept of a
provisioning key?

We've got over two man years into re-implementing all of this.  The
Intel code is a bit challenging to follow and not well documented, it
is now.... :-), but we have developed a great deal of respect for how
good the individuals behind the design of this were.

> >> The launch enclave is critical to that guarantee.
> >> 
> >> It is completely understandable why a locked down, (non-FLC) hardware
> >> platform, is undesirable in this community.  That doesn't mean that a
> >> launch enclave as a concept is unneeded or necessarily evil.
> >> 
> >> In an FLC environment the kernel assumes responsibility for SGX
> >> privacy and security.  This means that we need to do at least as well
> >> with a kernel based model as to what is currently available.
> >> 
> >>> There are other ways to accomplish it that might be better in some
> >>> respects.  For example, there could be /dev/sgx and
> >>> /dev/sgx_rights/provision.  The former exposes the whole sgx API,
> >>> except that it doesn???t allow provisioning by default. The latter
> >>> does nothing by itself. To run a provisioning enclave, you open both
> >>> nodes, then do something like:
> >>> 
> >>> ioctl(sgx, SGX_IOC_ADD_RIGHT, sgx_provisioning);
> >>> 
> >>> This requires extra syscalls, but it doesn't have the combinatorial
> >>> explosion problem.
> >> 
> >> Here is a proposal for the driver to add the needed policy control
> >> that is 'SGXy' in nature.  The 'SGXy' way is to use MRSIGNER values as
> >> the currency for security policy management.
> >> 
> >> The driver should establish the equivalent of three linked lists,
> >> maintainable via /sysfs pseudo-files or equivalent plumbing.  The
> >> lists are referenced by the kernel to enforce the following policies.
> >> 
> >> 1.) The right to initialize an enclave without special attributes.
> >> 
> >> 2.) The right to initialize an enclave with the PROVISION_KEY attribute set.
> >> 
> >> 3.) The right to initialize an enclave with the LICENSE_KEY attribute set.
> >> 
> >> The lists are populated with MRSIGNER values of enclaves that are
> >> allowed to initialize under the specified conditions.

> NAK because this is insufficient.  You're thinking of a model in
> which SGX-like protection is all that's needed.  This is an
> inadequate model of the real world.  The attack I'm most concerned
> about wrt provisioning is an attack in which an unauthorized user is
> permitted.

We will be interested in your comments as to why the proposal is
insufficient in the real world of FLC.

I believe the proposed architecture can be defended as being effective
in the real world, as it allows the root user to use cryptographic
protections of access to the PROVISION bit and to enclave execution in
general.  On FLC that is the strongest guarantee that can be
delivered.

When we speak of 'unauthorized' users I believe we are speaking in the
parlance of discretionary access controls which has a much wider TCB
scope then the cryptographic model we are proposing.  The model we
propose allows the platform owner (root) to effectively implement the
same level of security over the PROVISION bit that current locked
platforms have, in a free and open fashion of course.

We can certainly attempt to explain our position further.

> The use case I see for attestation *privacy*

Things seemed to end here so I assume that is where your e-mail went
awry.

I hope the clarifications provided above will assist further
discussion.

Have a good day.

Dr. Greg

As always,
Dr. G.W. Wettstein, Ph.D.   Enjellic Systems Development, LLC.
4206 N. 19th Ave.           Specializing in information infra-structure
Fargo, ND  58102            development.
PH: 701-281-1686
FAX: 701-281-3949           EMAIL: greg@enjellic.com
------------------------------------------------------------------------------
"When I am working on a problem I never think about beauty.  I only
 think about how to solve the problem.  But when I have finished, if
 the solution is not beautiful, I know it is wrong."
                                -- Buckminster Fuller

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-26 11:00                           ` Dr. Greg
@ 2018-11-26 18:22                             ` Andy Lutomirski
  2018-11-26 22:16                             ` Jarkko Sakkinen
  1 sibling, 0 replies; 155+ messages in thread
From: Andy Lutomirski @ 2018-11-26 18:22 UTC (permalink / raw)
  To: Dr. Greg Wettstein
  Cc: Jarkko Sakkinen, Andrew Lutomirski, X86 ML, Platform Driver,
	linux-sgx, Dave Hansen, Christopherson, Sean J, nhorman,
	npmccallum, Ayoun, Serge, shay.katz-zamir, haitao.huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko, LKML

On Mon, Nov 26, 2018 at 3:00 AM Dr. Greg <greg@enjellic.com> wrote:
>
> On Sun, Nov 25, 2018 at 04:37:00PM -0800, Andy Lutomirski wrote:
>
> > Bah, I hit send on a partially written draft. I???ll try again soon.
> >
> > --Andy
>
> Your first issue seems to be complete so I will respond to that in
> order to make sure we are not talking past one another.

It wasn't, but your answer is enlightening!  I've read the SGX
*manual*, but I hadn't dug through the actual Intel-supplied enclaves.
So, when I said that the LE isn't an important part of the overall
trust model, I meant that it isn't *in hardware*.  It's certainly
possible to write SGX software that weakens the security of the
overall system, and Intel seems to have done so:

>
> The Intel supplied launch enclave (LE) specifically denies
> initialization of enclaves which have the PROVISION attribute set,
> with the exception of enclaves whose MRSIGNER values match those of
> the keys that Intel uses to sign the PCE and PVE enclaves.  See line
> 219 of psw/ae/le/launch_enclave.cpp in the Intel SDK.

This seems entirely reasonable.  (But see below...)

> This report, along with the PEK, is submitted to the PCE enclave in
> order to generate the Platform Provisioning IDentity (PPID), which is
> the privacy critical identifier.  The PCE verifies the report
> generated by the PVE and rejects the request to generate the PPID if
> the report was generated by an enclave that was not initialized with
> the PROVISION bit set, see line 109 of psw/ae/pce/pce.cpp.

...and this seems entirely unreasonable.  Your description does indeed
appear consistent with the code: the PCE will hand out the PPID to any
requesting enclave that has the PROVISION bit set, so you are correct
that:

> Once again, the important design factor in all of this is the premise
> that the launch enclave will not allow enclaves other then the PCE and
> PVE to access the PROVISION bit.

But here's where the whole thing goes off the rails.  I would argue
that the Intel-supplied (and Intel-signed, apparently!) PCE is just
straight-up buggy.  What Intel is *trying* to do is to hand out the
PPID to an appropriately signed enclave.  What they actually did is to
hand out the PPID to any enclave that has the PROVISION bit set.  This
is poor design because it overload the PROVISION bit.  That bit is
supposed to mean "may use EGETKEY to obtain provisioning and
provisioning seal keys", which is not actually what Intel wants here.
It's also poor design without FLC because it pointlessly relies on the
LE to enforce a restriction on the use of provisioning enclaves, when
the code could instead have checked MRSIGNER..  And it's just straight
up wrong with FLC because there is no guarantee whatsoever that the LE
being used is Intel's.  And, for that matter, there is no guarantee
that the requesting enclave doesn't have the DEBUG bit set.

(It's also poor design because the PCE doesn't appear to verify that
the report passed in is actually intended to be associated with a call
to get_ppid().  There appear to be reports associated with provision
"msg1" and "msg3".  If it's possible to get a valid report for msg3 to
be accepted as a msg1 report of vice versa, then it might be game
over.)

Sorry, but this is not Linux's problem.  The right fix is, in my
opinion, entirely clear: the PCE should check MRSIGNER and possibly
even MRENCLAVE in the report it receives.  Intel needs to fix their
PCE, sign a fixed version, and find some way to revoke, to the extent
possible, the old one.  And the SGX enclave authors need to understand
something that is apparently subtle: THE LAUNCH POLICY IS NOT PART OF
THE TCB AND SHOULD NOT BE RELIED UPON.  Enclaves can and should be
written to remain secure even in the complete absence of any form of
launch control.

I went and filed a bug on github.  Let's see what happens:

https://github.com/intel/linux-sgx/issues/345

Also, the whole SGX report mechanism seems to be misused in the SDK.
An SGX report is a cryptographic primitive that essentially acts like
a signed blob.  Building a secure protocol on top of signed messages
or on top of reports takes more than just making up ad hoc blob
formats and signing them.  There needs to be domain separation between
different messages, and this seems to be entirely missing.  Do you
know if Intel has had a serious audit of their platform enclave code
done?

>
> > No, I have no clue why Intel did it this way.  I consider it to be a
> > mistake.
>
> Are you referring to there being a mistake in the trust relationships
> that the provisioning protocol implements or the overall concept of a
> provisioning key?

I'm referring to the hardware's policy as to when keys that don't
depend on OWNEREPOCH can be obtained.  As far as I know, the only real
need for such keys is to verify that the running platform is a real
Intel platform, which means that access to the provisioning key is
only useful to Intel-approved services.  Why didn't Intel enforce this
in hardware or microcode?  I see no reason that EGETKEY should hand
out those key types of the enclave is not signed by Intel.  For that
matter, I also don't see why the provisioning seal key needs to exist
-- the regular seal key could be used instead and, if OWNEREPOCH
changes, the platform could just re-certify itself.

> > >> The driver should establish the equivalent of three linked lists,
> > >> maintainable via /sysfs pseudo-files or equivalent plumbing.  The
> > >> lists are referenced by the kernel to enforce the following policies.
> > >>
> > >> 1.) The right to initialize an enclave without special attributes.
> > >>
> > >> 2.) The right to initialize an enclave with the PROVISION_KEY attribute set.
> > >>
> > >> 3.) The right to initialize an enclave with the LICENSE_KEY attribute set.
> > >>
> > >> The lists are populated with MRSIGNER values of enclaves that are
> > >> allowed to initialize under the specified conditions.
>
> > NAK because this is insufficient.  You're thinking of a model in
> > which SGX-like protection is all that's needed.  This is an
> > inadequate model of the real world.  The attack I'm most concerned
> > about wrt provisioning is an attack in which an unauthorized user is
> > permitted.
>
> We will be interested in your comments as to why the proposal is
> insufficient in the real world of FLC.

That's what you get for reading my unfinished email :)

Your proposal fails to protect against SGX malware.  Here's an SGX
malware use case: the attacker writes a malicious enclave and gets a
victim machine to run it as a non-root user.  They bundle it with a
valid Intel-signed copy of the relevant platform enclaves and use them
to bootstrap the attestation process.  The malicious enclave attests
its identity to a command-and-control server and obtains malicious
code to run.  The good guys can't reverse engineer the malware
enclave, because they can't pass the attestation check and therefore
can't obtain the encrypted code.

This isn't prevented by your proposed solution: the provisioning
enclaves are all signed by Intel.  What's needed is a check that
prevents unauthorized *users* from running them.

--Andy

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-24 19:24         ` Dr. Greg
@ 2018-11-26 19:39           ` Jarkko Sakkinen
  0 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-26 19:39 UTC (permalink / raw)
  To: Dr. Greg
  Cc: Andy Lutomirski, X86 ML, Platform Driver, linux-sgx, Dave Hansen,
	Christopherson, Sean J, nhorman, npmccallum, Ayoun, Serge,
	shay.katz-zamir, haitao.huang, Andy Shevchenko, Thomas Gleixner,
	Svahn, Kai, mark.shanahan, Suresh Siddha, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, Darren Hart, andy, LKML

On Sat, Nov 24, 2018 at 01:24:54PM -0600, Dr. Greg wrote:
> On Sat, Nov 24, 2018 at 08:15:21AM -0800, Jarkko Sakkinen wrote:
> 
> > On Tue, Nov 20, 2018 at 05:15:08AM -0600, Dr. Greg wrote:
> > > Malware would not necessarily need the Intel attestation service.
> > > Once access to the PROVISION bit is available, malware teams could
> > > simply build their own attestation service.
> 
> > AFAIK not possible as they wouldn't have access to the root
> > provisioning key. Can be confirmed from the SDM's key derivation
> > table (41-56).
> 
> What provisioning and attestation is all about is establishing an
> identity binding for a platform in question.  The standard Intel
> service binds the identity of a platform to an EPID private key.
> 
> With access to the SGX_FLAGS_PROVISION_BIT an enclave can generate a
> perpetual identity for a platform based on the identity modulus
> signature (MRSIGNER) of the key that signs the signature structure of
> the enclave.  Without access to the root provisioning key a security
> quorum or group has to be implemented via a subscription or enrollment
> model but that is arguably not much of an obstacle.
> 
> That is pretty much the way standard botware works now.
> 
> Without provisions for cryptographically secure authorization and
> policy enforcement in the driver, we will be creating infrastructure
> for a new generation of botware/malware whose mothership will know
> that a participating platform is running with full confidentiality and
> integrity protections.

OK, I think I got what you mean.

With free access to the provision the bot net controller could be sure
that a node is running inside an enclave. Is this what you are worried
about? Please correct if not or even if there is a slight drift on what
you are trying to state.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-24 20:13                 ` Dr. Greg
@ 2018-11-26 21:15                   ` Jarkko Sakkinen
  0 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-26 21:15 UTC (permalink / raw)
  To: Dr. Greg
  Cc: Andy Lutomirski, X86 ML, Platform Driver, linux-sgx, Dave Hansen,
	Christopherson, Sean J, nhorman, npmccallum, Ayoun, Serge,
	shay.katz-zamir, haitao.huang, Andy Shevchenko, Thomas Gleixner,
	Svahn, Kai, mark.shanahan, Suresh Siddha, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, Darren Hart, Andy Shevchenko,
	LKML

On Sat, Nov 24, 2018 at 02:13:18PM -0600, Dr. Greg wrote:
> This isn't about an enclave being able to tell that it is really an
> enclave.  As I noted in my previous reply, access to the provisioning
> bit allows an enclave author to create a perpetual hardware identifier
> for a platform based on a signing key of their choosing, along with a
> few other incidentals, all of which are completely under the control
> of the enclave author.

I think I'm now in the same page with the issue now. Thanks for the
patience explaining this.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-25 16:22                   ` Andy Lutomirski
  2018-11-25 18:55                     ` Dr. Greg
@ 2018-11-26 21:51                     ` Jarkko Sakkinen
  2018-11-26 23:04                       ` Jarkko Sakkinen
  1 sibling, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-26 21:51 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Andy Lutomirski, Dr. Greg Wettstein, X86 ML, Platform Driver,
	linux-sgx, Dave Hansen, Christopherson, Sean J, nhorman,
	npmccallum, Ayoun, Serge, shay.katz-zamir, haitao.huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko, LKML

On Sun, Nov 25, 2018 at 08:22:35AM -0800, Andy Lutomirski wrote:
> Agreed. What I’m proposing adds additional security if the kernel is
> *not* compromised.

And even if the kernel is compromised evil use will detected quicker
i.e. compromissed kernel is "better" than a kernel that allows to
use provisioning freely.

> There are other ways to accomplish it that might be better in some
> respects.  For example, there could be /dev/sgx and
> /dev/sgx_rights/provision.  The former exposes the whole sgx API,
> except that it doesn’t allow provisioning by default. The latter does
> nothing by itself. To run a provisioning enclave, you open both nodes,
> then do something like:
> 
> ioctl(sgx, SGX_IOC_ADD_RIGHT, sgx_provisioning);
> 
> This requires extra syscalls, but it doesn’t have the combinatorial
> explosion problem.

I like this design because it is extendable. I'm now also in the same
page why we need to protect provisioning in the first place. I would
slight restructure this as

/dev/sgx/control
/dev/sgx/attributes/provision

Looks cleaner and the root /dev directory is less polluted.

BTW, off-topic from this but should we remove ENCLAVE from IOC names as
they all concern enclaves anyway? Seems kind of redundant. I.e.

SGX_IOC_ENCLAVE_CREATE -> SGX_IOC_CREATE
SGX_IOC_ENCLAVE_ADD_PAGE -> SGX_IOC_ADD_PAGE
SGX_IOC_ENCLAVE_INIT -> SGX_IOC_INIT

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-26 11:00                           ` Dr. Greg
  2018-11-26 18:22                             ` Andy Lutomirski
@ 2018-11-26 22:16                             ` Jarkko Sakkinen
  1 sibling, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-26 22:16 UTC (permalink / raw)
  To: Dr. Greg
  Cc: Andy Lutomirski, Andy Lutomirski, X86 ML, Platform Driver,
	linux-sgx, Dave Hansen, Christopherson, Sean J, nhorman,
	npmccallum, Ayoun, Serge, shay.katz-zamir, haitao.huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko, LKML

On Mon, Nov 26, 2018 at 05:00:39AM -0600, Dr. Greg wrote:
> We will be interested in your comments as to why the proposal is
> insufficient in the real world of FLC.
> 
> I believe the proposed architecture can be defended as being effective
> in the real world, as it allows the root user to use cryptographic
> protections of access to the PROVISION bit and to enclave execution in
> general.  On FLC that is the strongest guarantee that can be
> delivered.
> 
> When we speak of 'unauthorized' users I believe we are speaking in the
> parlance of discretionary access controls which has a much wider TCB
> scope then the cryptographic model we are proposing.  The model we
> propose allows the platform owner (root) to effectively implement the
> same level of security over the PROVISION bit that current locked
> platforms have, in a free and open fashion of course.
> 
> We can certainly attempt to explain our position further.

I think kernel controlled provision would in all cases lower the
mitigations of thread scenarios (at least what you've presented so far)
assuming that a compromissed kernel could be detected fairly quickly,
wouldn't it?

Even without SGX, having a compromissed kernel, you can anyhow stealth
your malware in many ways.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-26 21:51                     ` Jarkko Sakkinen
@ 2018-11-26 23:04                       ` Jarkko Sakkinen
  2018-11-27  8:55                         ` Dr. Greg
  0 siblings, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-26 23:04 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Andy Lutomirski, Dr. Greg Wettstein, X86 ML, Platform Driver,
	linux-sgx, Dave Hansen, Christopherson, Sean J, nhorman,
	npmccallum, Ayoun, Serge, shay.katz-zamir, haitao.huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko, LKML

On Mon, Nov 26, 2018 at 01:51:45PM -0800, Jarkko Sakkinen wrote:
> > ioctl(sgx, SGX_IOC_ADD_RIGHT, sgx_provisioning);
> > 
> > This requires extra syscalls, but it doesn’t have the combinatorial
> > explosion problem.
> 
> I like this design because it is extendable. I'm now also in the same
> page why we need to protect provisioning in the first place. I would
> slight restructure this as
> 
> /dev/sgx/control
> /dev/sgx/attributes/provision

I guess it would be OK to upstream only control node first as long as
provision attribute is denied in order to keep the already huge patch
set a tiny bit smaller?

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-26 23:04                       ` Jarkko Sakkinen
@ 2018-11-27  8:55                         ` Dr. Greg
  2018-11-27 16:41                           ` Jarkko Sakkinen
                                             ` (2 more replies)
  0 siblings, 3 replies; 155+ messages in thread
From: Dr. Greg @ 2018-11-27  8:55 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Andy Lutomirski, Andy Lutomirski, Dr. Greg Wettstein, X86 ML,
	Platform Driver, linux-sgx, Dave Hansen, Christopherson, Sean J,
	nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir, haitao.huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko, LKML

On Mon, Nov 26, 2018 at 03:04:36PM -0800, Jarkko Sakkinen wrote:

Good morning to everyone.

> On Mon, Nov 26, 2018 at 01:51:45PM -0800, Jarkko Sakkinen wrote:
> > > ioctl(sgx, SGX_IOC_ADD_RIGHT, sgx_provisioning);
> > > 
> > > This requires extra syscalls, but it doesn???t have the combinatorial
> > > explosion problem.
> > 
> > I like this design because it is extendable. I'm now also in the same
> > page why we need to protect provisioning in the first place. I would
> > slight restructure this as
> > 
> > /dev/sgx/control
> > /dev/sgx/attributes/provision

> I guess it would be OK to upstream only control node first as long
> as provision attribute is denied in order to keep the already huge
> patch set a tiny bit smaller?

At this point in time I believe there is a consensus that the driver
needs a policy management framework of some type for an optimum
implementation.  The PROVISION attribute has privacy implications and
unrestricted access to release mode (full security) is problematic.

Since the thread has become a bit divergent I wanted to note that we
have offered a proposal for a general policy management framework
based on MRSIGNER values.  This framework is consistent with the SGX
security model, ie. cryptographic rather then DAC based policy
controls.  This framework also allows a much more flexible policy
implementation that doesn't result in combinatoric issues.

Our framework also allows the preservation of the current ABI which
allows an EINITTOKEN to be passed in from userspace.  The framework
also supports the ability to specify that only a kernel based launch
enclave (LE) should be available if the platform owner or distribution
should desire to implement such a model.

The policy management framework is straight forward.  Three linked
lists or their equivalent which are populated through /sysfs
pseudo-files or equivalent plumbing.  Each list is populated with
MRSIGNER values for signing keys that are allowed to initialize
enclaves under three separate conditions.

1.) General enclaves without special attribute bits.

2.) Enclaves with the SGX_FLAGS_PROVISION_KEY attribute set. - i.e.,
'Provisioning Enclaves'.

3.) Enclaves with the SGX_FLAGS_LICENSE_KEY attribute set - i.e., 'Launch
Enclaves'.

An all-null MRSIGNER value serves as a 'sealing' value that locks a
list from any further modifications.

This architecture allows platform policies to be specified and then
sealed at early boot by the root user.  At that point cryptographic
policy controls are in place rather then DAC based controls, the
latter of which have perpetual security liabilities in addition to the
useability constraints inherent in a DAC or device node model.

We have developed an independent implementation of the PSW and
arguably have as much experience with issues surrounding how to
interact with the device driver as anyone.  We have spent a lot of
time thinking about these issues and the above framework provides the
most flexible architecture available.

> /Jarkko

We would be happy to discuss specific aspects of the implementation.

Have a good day.

Dr. Greg

As always,
Dr. G.W. Wettstein, Ph.D.   Enjellic Systems Development, LLC.
4206 N. 19th Ave.           Specializing in information infra-structure
Fargo, ND  58102            development.
PH: 701-281-1686
FAX: 701-281-3949           EMAIL: greg@enjellic.com
------------------------------------------------------------------------------
"Remember that when you take down the fishhouse you can't put
 the minnows back into the lake, so throw them out on the ice.
 Make sure you stomp on any of the live ones so they don't suffer."
                                -- Fritz Wettstein
                                   At the lake

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-27  8:55                         ` Dr. Greg
@ 2018-11-27 16:41                           ` Jarkko Sakkinen
  2018-11-27 17:55                             ` Andy Lutomirski
  2018-11-27 16:46                           ` Jarkko Sakkinen
  2018-11-28 21:52                           ` Andy Lutomirski
  2 siblings, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-27 16:41 UTC (permalink / raw)
  To: Dr. Greg
  Cc: Andy Lutomirski, Andy Lutomirski, X86 ML, Platform Driver,
	linux-sgx, Dave Hansen, Christopherson, Sean J, nhorman,
	npmccallum, Ayoun, Serge, shay.katz-zamir, haitao.huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko, LKML

On Tue, Nov 27, 2018 at 02:55:33AM -0600, Dr. Greg wrote:
> Since the thread has become a bit divergent I wanted to note that we
> have offered a proposal for a general policy management framework
> based on MRSIGNER values.  This framework is consistent with the SGX
> security model, ie. cryptographic rather then DAC based policy
> controls.  This framework also allows a much more flexible policy
> implementation that doesn't result in combinatoric issues.
> 
> Our framework also allows the preservation of the current ABI which
> allows an EINITTOKEN to be passed in from userspace.  The framework
> also supports the ability to specify that only a kernel based launch
> enclave (LE) should be available if the platform owner or distribution
> should desire to implement such a model.
> 
> The policy management framework is straight forward.  Three linked
> lists or their equivalent which are populated through /sysfs
> pseudo-files or equivalent plumbing.  Each list is populated with
> MRSIGNER values for signing keys that are allowed to initialize
> enclaves under three separate conditions.
> 
> 1.) General enclaves without special attribute bits.
> 
> 2.) Enclaves with the SGX_FLAGS_PROVISION_KEY attribute set. - i.e.,
> 'Provisioning Enclaves'.
> 
> 3.) Enclaves with the SGX_FLAGS_LICENSE_KEY attribute set - i.e., 'Launch
> Enclaves'.
> 
> An all-null MRSIGNER value serves as a 'sealing' value that locks a
> list from any further modifications.
> 
> This architecture allows platform policies to be specified and then
> sealed at early boot by the root user.  At that point cryptographic
> policy controls are in place rather then DAC based controls, the
> latter of which have perpetual security liabilities in addition to the
> useability constraints inherent in a DAC or device node model.
> 
> We have developed an independent implementation of the PSW and
> arguably have as much experience with issues surrounding how to
> interact with the device driver as anyone.  We have spent a lot of
> time thinking about these issues and the above framework provides the
> most flexible architecture available.

Sounds like a lot bloat and policy added to the kernel whereas with
Andy's proposal you can implement logic to a daemon and provide only
mechanism to do it.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-27  8:55                         ` Dr. Greg
  2018-11-27 16:41                           ` Jarkko Sakkinen
@ 2018-11-27 16:46                           ` Jarkko Sakkinen
  2018-11-28 21:52                           ` Andy Lutomirski
  2 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-27 16:46 UTC (permalink / raw)
  To: Dr. Greg
  Cc: Andy Lutomirski, Andy Lutomirski, X86 ML, Platform Driver,
	linux-sgx, Dave Hansen, Christopherson, Sean J, nhorman,
	npmccallum, Ayoun, Serge, shay.katz-zamir, haitao.huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko, LKML

On Tue, Nov 27, 2018 at 02:55:33AM -0600, Dr. Greg wrote:
> 3.) Enclaves with the SGX_FLAGS_LICENSE_KEY attribute set - i.e., 'Launch
> Enclaves'.

Kernel does not have to manage this. If the MSRs are read-only, they
should match your LE. If the MSRs writable, you don't need an LE.

This whole scheme sounds like adding own SELinux for SGX and it is
only words. No code available.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-27 16:41                           ` Jarkko Sakkinen
@ 2018-11-27 17:55                             ` Andy Lutomirski
  2018-11-28 10:49                               ` Dr. Greg
  0 siblings, 1 reply; 155+ messages in thread
From: Andy Lutomirski @ 2018-11-27 17:55 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Dr. Greg, Andy Lutomirski, X86 ML, Platform Driver, linux-sgx,
	Dave Hansen, Christopherson, Sean J, nhorman, npmccallum, Ayoun,
	Serge, shay.katz-zamir, haitao.huang, Andy Shevchenko,
	Thomas Gleixner, Svahn, Kai, mark.shanahan, Suresh Siddha,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin, Darren Hart,
	Andy Shevchenko, LKML



> On Nov 27, 2018, at 8:41 AM, Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> wrote:
> 
>> On Tue, Nov 27, 2018 at 02:55:33AM -0600, Dr. Greg wrote:
>> Since the thread has become a bit divergent I wanted to note that we
>> have offered a proposal for a general policy management framework
>> based on MRSIGNER values.  This framework is consistent with the SGX
>> security model, ie. cryptographic rather then DAC based policy
>> controls.  This framework also allows a much more flexible policy
>> implementation that doesn't result in combinatoric issues.
>> 
>> Our framework also allows the preservation of the current ABI which
>> allows an EINITTOKEN to be passed in from userspace.  The framework
>> also supports the ability to specify that only a kernel based launch
>> enclave (LE) should be available if the platform owner or distribution
>> should desire to implement such a model.
>> 
>> The policy management framework is straight forward.  Three linked
>> lists or their equivalent which are populated through /sysfs
>> pseudo-files or equivalent plumbing.  Each list is populated with
>> MRSIGNER values for signing keys that are allowed to initialize
>> enclaves under three separate conditions.
>> 
>> 1.) General enclaves without special attribute bits.
>> 
>> 2.) Enclaves with the SGX_FLAGS_PROVISION_KEY attribute set. - i.e.,
>> 'Provisioning Enclaves'.
>> 
>> 3.) Enclaves with the SGX_FLAGS_LICENSE_KEY attribute set - i.e., 'Launch
>> Enclaves'.
>> 
>> An all-null MRSIGNER value serves as a 'sealing' value that locks a
>> list from any further modifications.
>> 
>> This architecture allows platform policies to be specified and then
>> sealed at early boot by the root user.  At that point cryptographic
>> policy controls are in place rather then DAC based controls, the
>> latter of which have perpetual security liabilities in addition to the
>> useability constraints inherent in a DAC or device node model.
>> 
>> We have developed an independent implementation of the PSW and
>> arguably have as much experience with issues surrounding how to
>> interact with the device driver as anyone.  We have spent a lot of
>> time thinking about these issues and the above framework provides the
>> most flexible architecture available.
> 
> Sounds like a lot bloat and policy added to the kernel whereas with
> Andy's proposal you can implement logic to a daemon and provide only
> mechanism to do it.
> 
> 

Well, almost. We’d need SGX_IOC_FREEZE_MR{ENCLAVE,SIGNER} or similar.  Or maybe the daemon could handle the entire loading process.  But this can wait until after the main driver is upstream.

This does lead to a question: enclaves are kind-of-sort-of mapped into a given address space. What happens if you issue the various ioctls in the context of a different mm?  For that matter, can two processes mmap the same enclave?

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-24 16:45                 ` Jarkko Sakkinen
@ 2018-11-28  5:08                   ` Jarkko Sakkinen
  0 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-28  5:08 UTC (permalink / raw)
  To: Dr. Greg
  Cc: Andy Lutomirski, X86 ML, Platform Driver, linux-sgx, Dave Hansen,
	Christopherson, Sean J, nhorman, npmccallum, Ayoun, Serge,
	shay.katz-zamir, haitao.huang, Andy Shevchenko, Thomas Gleixner,
	Svahn, Kai, mark.shanahan, Suresh Siddha, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, Darren Hart, Andy Shevchenko,
	LKML

On Sat, Nov 24, 2018 at 08:45:34AM -0800, Jarkko Sakkinen wrote:
> On Fri, Nov 23, 2018 at 04:39:23AM -0600, Dr. Greg wrote:
> > Jarkko, when this driver lands it will set the SGX ABI in stone for
> > Linux.  It would be very, very helpful to the development community if
> > there was some official guidance from Intel on whether or not FLC will
> > be a universal feature on all hardware and the date that is going to
> > happen or has happened.
> 
> I seriously don't know but I can take this message to the mothership...

LC enabling is essentially a platform vendors choice, not Intels choice,
like many other CPU features that Linux is dependent on. Of course, if
Linux ends supporting only LC that will without doubt have a big impact
on vendors so in that way it is indirectly also communitys choice.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-27 17:55                             ` Andy Lutomirski
@ 2018-11-28 10:49                               ` Dr. Greg
  2018-11-28 19:22                                 ` Jarkko Sakkinen
  0 siblings, 1 reply; 155+ messages in thread
From: Dr. Greg @ 2018-11-28 10:49 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Jarkko Sakkinen, Andy Lutomirski, X86 ML, Platform Driver,
	linux-sgx, Dave Hansen, Christopherson, Sean J, nhorman,
	npmccallum, Ayoun, Serge, shay.katz-zamir, haitao.huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko, LKML

On Tue, Nov 27, 2018 at 09:55:45AM -0800, Andy Lutomirski wrote:

> > On Nov 27, 2018, at 8:41 AM, Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> wrote:
> > 
> >> On Tue, Nov 27, 2018 at 02:55:33AM -0600, Dr. Greg wrote:
> >> Since the thread has become a bit divergent I wanted to note that we
> >> have offered a proposal for a general policy management framework
> >> based on MRSIGNER values.  This framework is consistent with the SGX
> >> security model, ie. cryptographic rather then DAC based policy
> >> controls.  This framework also allows a much more flexible policy
> >> implementation that doesn't result in combinatoric issues.
> >> 
> >> Our framework also allows the preservation of the current ABI which
> >> allows an EINITTOKEN to be passed in from userspace.  The framework
> >> also supports the ability to specify that only a kernel based launch
> >> enclave (LE) should be available if the platform owner or distribution
> >> should desire to implement such a model.
> >> 
> >> The policy management framework is straight forward.  Three linked
> >> lists or their equivalent which are populated through /sysfs
> >> pseudo-files or equivalent plumbing.  Each list is populated with
> >> MRSIGNER values for signing keys that are allowed to initialize
> >> enclaves under three separate conditions.
> >> 
> >> 1.) General enclaves without special attribute bits.
> >> 
> >> 2.) Enclaves with the SGX_FLAGS_PROVISION_KEY attribute set. - i.e.,
> >> 'Provisioning Enclaves'.
> >> 
> >> 3.) Enclaves with the SGX_FLAGS_LICENSE_KEY attribute set - i.e., 'Launch
> >> Enclaves'.
> >> 
> >> An all-null MRSIGNER value serves as a 'sealing' value that locks a
> >> list from any further modifications.
> >> 
> >> This architecture allows platform policies to be specified and then
> >> sealed at early boot by the root user.  At that point cryptographic
> >> policy controls are in place rather then DAC based controls, the
> >> latter of which have perpetual security liabilities in addition to the
> >> useability constraints inherent in a DAC or device node model.
> >> 
> >> We have developed an independent implementation of the PSW and
> >> arguably have as much experience with issues surrounding how to
> >> interact with the device driver as anyone.  We have spent a lot of
> >> time thinking about these issues and the above framework provides the
> >> most flexible architecture available.
> > 
> > Sounds like a lot bloat and policy added to the kernel whereas with
> > Andy's proposal you can implement logic to a daemon and provide only
> > mechanism to do it.

> Well, almost. We'd need SGX_IOC_FREEZE_MR{ENCLAVE,SIGNER} or
> similar.  Or maybe the daemon could handle the entire loading process.
> But this can wait until after the main driver is upstream.
>
> This does lead to a question: enclaves are kind-of-sort-of mapped
> into a given address space. What happens if you issue the various
> ioctls in the context of a different mm?  For that matter, can two
> processes mmap the same enclave?

Fascinating.

We've been carrying a patch, that drops in on top of the proposed
kernel driver, that implements the needed policy management framework
for DAC fragile (FLC) platforms.  After a meeting yesterday with the
client that is funding the work, a decision was made to release the
enhancements when the SGX driver goes mainline.  That will at least
give developers the option of creating solutions on Linux that
implement the security guarantees that SGX was designed to deliver.

Most importantly, since it implements a driver consistent with the
design of SGX, it has the added benefit of allowing system
administrators the ability to enable the driver to work on non-FLC
(locked) platforms.  Since Jarkko confirmed that FLC is the option of
platform vendors, this would seem to be important as SGX on Linux will
only work in a random fashion dependent on the whims of hardware OEM's
in probably a SKU dependent fashion.  Which is why the client has
interest in the work.

Best wishes for a productive remainder of the week.

Dr. Greg

As always,
Dr. G.W. Wettstein, Ph.D.   Enjellic Systems Development, LLC.
4206 N. 19th Ave.           Specializing in information infra-structure
Fargo, ND  58102            development.
PH: 701-281-1686
FAX: 701-281-3949           EMAIL: greg@enjellic.com
------------------------------------------------------------------------------
"Five year projections, are you kidding me.  We don't know what we are
 supposed to be doing at the 4 o'clock meeting this afternoon."
                                -- Terry Wieland
                                   Resurrection

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-28 10:49                               ` Dr. Greg
@ 2018-11-28 19:22                                 ` Jarkko Sakkinen
  2018-12-10 10:49                                   ` Dr. Greg
  0 siblings, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-11-28 19:22 UTC (permalink / raw)
  To: Dr. Greg
  Cc: Andy Lutomirski, Andy Lutomirski, X86 ML, Platform Driver,
	linux-sgx, Dave Hansen, Christopherson, Sean J, nhorman,
	npmccallum, Ayoun, Serge, shay.katz-zamir, haitao.huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko, LKML

On Wed, Nov 28, 2018 at 04:49:41AM -0600, Dr. Greg wrote:
> We've been carrying a patch, that drops in on top of the proposed
> kernel driver, that implements the needed policy management framework
> for DAC fragile (FLC) platforms.  After a meeting yesterday with the
> client that is funding the work, a decision was made to release the
> enhancements when the SGX driver goes mainline.  That will at least
> give developers the option of creating solutions on Linux that
> implement the security guarantees that SGX was designed to deliver.

We do not need yet another policy management framework to the *kernel*.

The token based approach that Andy is proposing is proven and well
established method to create a mechanism. You can then create a daemon
to user space that decides who it wants to send tokes.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-27  8:55                         ` Dr. Greg
  2018-11-27 16:41                           ` Jarkko Sakkinen
  2018-11-27 16:46                           ` Jarkko Sakkinen
@ 2018-11-28 21:52                           ` Andy Lutomirski
  2 siblings, 0 replies; 155+ messages in thread
From: Andy Lutomirski @ 2018-11-28 21:52 UTC (permalink / raw)
  To: Dr. Greg Wettstein
  Cc: Jarkko Sakkinen, Andrew Lutomirski, X86 ML, Platform Driver,
	linux-sgx, Dave Hansen, Christopherson, Sean J, nhorman,
	npmccallum, Ayoun, Serge, shay.katz-zamir, haitao.huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko, LKML

On Tue, Nov 27, 2018 at 12:55 AM Dr. Greg <greg@enjellic.com> wrote:
> Since the thread has become a bit divergent I wanted to note that we
> have offered a proposal for a general policy management framework
> based on MRSIGNER values.  This framework is consistent with the SGX
> security model, ie. cryptographic rather then DAC based policy
> controls.  This framework also allows a much more flexible policy
> implementation that doesn't result in combinatoric issues.

Can you give a concrete explanation of a problem that your proposal
would solve?  As far as I can tell, it gets rid of a case in which an
unprivileged attacker who can run enclaves but hasn't compromised the
kernel can learn the PPID and other SGX-related permanent platform
identifiers, but it does nothing to prevent the same attacker from
learning non-SGX-related permanent identifiers, nor does it prevent
the attacker from using the Intel quoting enclave (unless configured
in a surprising way) and thus attesting to a remote system.

So what problem does it solve?

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 22/23] x86/sgx: SGX documentation
  2018-11-16  1:01 ` [PATCH v17 22/23] x86/sgx: SGX documentation Jarkko Sakkinen
@ 2018-12-03  3:28   ` Randy Dunlap
  2018-12-03  9:32     ` Jarkko Sakkinen
  0 siblings, 1 reply; 155+ messages in thread
From: Randy Dunlap @ 2018-12-03  3:28 UTC (permalink / raw)
  To: Jarkko Sakkinen, x86, platform-driver-x86, linux-sgx
  Cc: dave.hansen, sean.j.christopherson, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Jonathan Corbet,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	open list:DOCUMENTATION, open list

Hi,
I have more editing comments below.


On 11/15/18 5:01 PM, Jarkko Sakkinen wrote:
> Documentation of the features of the Software Guard eXtensions used
> by the Linux kernel and basic design choices for the core and driver
> and functionality.
> 
> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> Co-developed-by: Sean Christopherson <sean.j.christopherson@intel.com>
> Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
> ---
>  Documentation/index.rst         |   1 +
>  Documentation/x86/index.rst     |   8 ++
>  Documentation/x86/intel_sgx.rst | 233 ++++++++++++++++++++++++++++++++
>  3 files changed, 242 insertions(+)
>  create mode 100644 Documentation/x86/index.rst
>  create mode 100644 Documentation/x86/intel_sgx.rst

> diff --git a/Documentation/x86/intel_sgx.rst b/Documentation/x86/intel_sgx.rst
> new file mode 100644
> index 000000000000..f51b43f9e125
> --- /dev/null
> +++ b/Documentation/x86/intel_sgx.rst
> @@ -0,0 +1,233 @@
> +===================
> +Intel(R) SGX driver
> +===================
> +
> +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 inverted sandbox. It protects the

                                   provides an inverted sandbox.

> +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

                       ring 3

> +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 in

                                                                        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.
> +
> +Enclave can only execute code inside the ELRANGE. Instructions that may cause

   An enclave can only

> +VMEXIT, IO instructions and instructions that require a privilege change are
> +prohibited inside the enclave. Interrupts and exceptions always cause enclave

                                                            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 to which enclave they belong to.

Drop one of those "to" words (either one).

> +
> +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

                                                        with an

> +   *launch key*, which is re-generated for each boot cycle.

(prefer)                     regenerated

> +
> +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[17]** is used by the BIOS configure whether

                                        by the BIOS to 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 out to the ENCLS(ECREATE) together with a physical address of a page

This would make more sense to me:

   is passed to the ENCLS(ECREATE) instruction together with ...

> +in EPC that will hold the SECS.
> +
> +The pages are added with ENCLS(EADD) and measured with ENCLS(EEXTEND) i.e.

                                                     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 ENCLS(EWB) 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

                                128-byte

> +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.
> +ENCLS(EBLOCK) instruction moves a page to the *blocked* state, which means

 The ENCLS(EBLOCK) instruction

> +that no new TLB entries can be created to it by the hardware threads.
> +
> +After this a shootdown sequence is started with ENCLS(ETRACK), 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
> +couner value because that means that there might be hardware thread inside

   counter                                                      threads


> +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 unlocked MSRs i.e.

                                                            MSRs, i.e.

> +FEATURE_CONTROL_SGX_LE_WR must be set. The launch is performed by setting the
> +MSRs to the hash of the public key modulus of the enclave signer, which is one
> +of the fields in the SIGSTRUCT.
> +
> +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
> +
> +Noteably, (2) implies that either the kernel has botched the EPC mappings or the

   Notably,

> +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 w/ PF_SGX set.  The SGX architecture

                                     with

> +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

       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
> +  <https://eprint.iacr.org/2016/204.pdf>
> +* System Programming Manual: 39.1.4 Intel® SGX Launch Control Configuration


ciao.
-- 
~Randy

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 22/23] x86/sgx: SGX documentation
  2018-12-03  3:28   ` Randy Dunlap
@ 2018-12-03  9:32     ` Jarkko Sakkinen
  0 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-03  9:32 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: x86, platform-driver-x86, linux-sgx, dave.hansen,
	sean.j.christopherson, nhorman, npmccallum, serge.ayoun,
	shay.katz-zamir, haitao.huang, andriy.shevchenko, tglx,
	kai.svahn, mark.shanahan, luto, Jonathan Corbet, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, open list:DOCUMENTATION,
	open list

On Sun, Dec 02, 2018 at 07:28:55PM -0800, Randy Dunlap wrote:
> Hi,
> I have more editing comments below.
> 
> 
> On 11/15/18 5:01 PM, Jarkko Sakkinen wrote:
> > Documentation of the features of the Software Guard eXtensions used
> > by the Linux kernel and basic design choices for the core and driver
> > and functionality.
> > 
> > Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> > Co-developed-by: Sean Christopherson <sean.j.christopherson@intel.com>
> > Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
> > ---
> >  Documentation/index.rst         |   1 +
> >  Documentation/x86/index.rst     |   8 ++
> >  Documentation/x86/intel_sgx.rst | 233 ++++++++++++++++++++++++++++++++
> >  3 files changed, 242 insertions(+)
> >  create mode 100644 Documentation/x86/index.rst
> >  create mode 100644 Documentation/x86/intel_sgx.rst
> 
> > diff --git a/Documentation/x86/intel_sgx.rst b/Documentation/x86/intel_sgx.rst
> > new file mode 100644
> > index 000000000000..f51b43f9e125
> > --- /dev/null
> > +++ b/Documentation/x86/intel_sgx.rst
> > @@ -0,0 +1,233 @@
> > +===================
> > +Intel(R) SGX driver
> > +===================
> > +
> > +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 inverted sandbox. It protects the
> 
>                                    provides an inverted sandbox.
> 
> > +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
> 
>                        ring 3
> 
> > +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 in
> 
>                                                                         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.
> > +
> > +Enclave can only execute code inside the ELRANGE. Instructions that may cause
> 
>    An enclave can only
> 
> > +VMEXIT, IO instructions and instructions that require a privilege change are
> > +prohibited inside the enclave. Interrupts and exceptions always cause enclave
> 
>                                                             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 to which enclave they belong to.
> 
> Drop one of those "to" words (either one).
> 
> > +
> > +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
> 
>                                                         with an
> 
> > +   *launch key*, which is re-generated for each boot cycle.
> 
> (prefer)                     regenerated
> 
> > +
> > +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[17]** is used by the BIOS configure whether
> 
>                                         by the BIOS to 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 out to the ENCLS(ECREATE) together with a physical address of a page
> 
> This would make more sense to me:
> 
>    is passed to the ENCLS(ECREATE) instruction together with ...
> 
> > +in EPC that will hold the SECS.
> > +
> > +The pages are added with ENCLS(EADD) and measured with ENCLS(EEXTEND) i.e.
> 
>                                                      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 ENCLS(EWB) 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
> 
>                                 128-byte

Is having a space instead of dash always grammatically wrong or is this
just to have a coherent style? Just asking for plain curiosity...

> 
> > +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.
> > +ENCLS(EBLOCK) instruction moves a page to the *blocked* state, which means
> 
>  The ENCLS(EBLOCK) instruction
> 
> > +that no new TLB entries can be created to it by the hardware threads.
> > +
> > +After this a shootdown sequence is started with ENCLS(ETRACK), 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
> > +couner value because that means that there might be hardware thread inside
> 
>    counter                                                      threads
> 
> 
> > +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 unlocked MSRs i.e.
> 
>                                                             MSRs, i.e.
> 
> > +FEATURE_CONTROL_SGX_LE_WR must be set. The launch is performed by setting the
> > +MSRs to the hash of the public key modulus of the enclave signer, which is one
> > +of the fields in the SIGSTRUCT.
> > +
> > +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
> > +
> > +Noteably, (2) implies that either the kernel has botched the EPC mappings or the
> 
>    Notably,
> 
> > +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 w/ PF_SGX set.  The SGX architecture
> 
>                                      with
> 
> > +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
> 
>        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
> > +  <https://eprint.iacr.org/2016/204.pdf>
> > +* System Programming Manual: 39.1.4 Intel® SGX Launch Control Configuration
> 
> 
> ciao.
> -- 
> ~Randy

Great, thanks Randy, highly appreciated!

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-19 16:59       ` Andy Lutomirski
  2018-11-20 12:04         ` Jarkko Sakkinen
@ 2018-12-09 17:01         ` Pavel Machek
  1 sibling, 0 replies; 155+ messages in thread
From: Pavel Machek @ 2018-12-09 17:01 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Jarkko Sakkinen, X86 ML, Platform Driver, linux-sgx, Dave Hansen,
	Christopherson, Sean J, nhorman, npmccallum, Ayoun, Serge,
	shay.katz-zamir, haitao.huang, Andy Shevchenko, Thomas Gleixner,
	Svahn, Kai, mark.shanahan, Suresh Siddha, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, Darren Hart, andy, LKML

Hi!

> > There would be three types of users:
> >
> > 1. Ones that have access to neither of the devices.
> > 2. Ones that have access to unprivileged. Who are these?
> 
> Either 0666 (world) or an sgx group.

Sgx group, please. Or even better, what is generic term for sgx? We
probably want to use that, as sgx is likely trademarked and certainly
Intelism.
								Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-19 15:29   ` Andy Lutomirski
  2018-11-19 16:19     ` Jarkko Sakkinen
  2018-11-20 11:15     ` Dr. Greg
@ 2018-12-09 17:01     ` Pavel Machek
  2018-12-10 14:46       ` Dr. Greg
  2 siblings, 1 reply; 155+ messages in thread
From: Pavel Machek @ 2018-12-09 17:01 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Jarkko Sakkinen, X86 ML, Platform Driver, linux-sgx, Dave Hansen,
	Christopherson, Sean J, nhorman, npmccallum, Ayoun, Serge,
	shay.katz-zamir, haitao.huang, Andy Shevchenko, Thomas Gleixner,
	Svahn, Kai, mark.shanahan, Suresh Siddha, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, Darren Hart, andy, LKML

Hi!

> On Thu, Nov 15, 2018 at 5:08 PM Jarkko Sakkinen
> <jarkko.sakkinen@linux.intel.com> wrote:
> >
> > 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.
> >
> > SGX driver provides a ioctl API for loading and initializing enclaves.
> > Address range for enclaves is reserved with mmap() and they are
> > destroyed with munmap(). Enclave construction, measurement and
> > initialization is done with the provided the ioctl API.
> >
> 
> I brought this up a while back, and I think I should re-ask it now
> that this driver is getting close to ready:
> 
> As it stands, there's just one SGX character device, and I imagine
> that it'll be available to unprivileged applications.  I'm concerned
> that this isn't quite what we want.  I certainly think that everyone,
> or at least almost everyone, ought to be able to run normal
> enclaves.

I don't think nobody or postfix or guest should be running enclaves on
my systems. First, I'd like to  be able to debug my systems.

Second, sgx quite complex and tricky. It may turn out to be secure in
the end, but I'd not be surprised if we got few CVEs before we get
there.

Last, I'd hate to find out in few years that I can't switch to amd
cpu because firefox now requires sgx.

Just make it root-only or 660 by default. Users can get permission in
similar way they get rights to audio..

								Pavel
								
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-28 19:22                                 ` Jarkko Sakkinen
@ 2018-12-10 10:49                                   ` Dr. Greg
  2018-12-12 18:00                                     ` Jarkko Sakkinen
  0 siblings, 1 reply; 155+ messages in thread
From: Dr. Greg @ 2018-12-10 10:49 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Andy Lutomirski, Andy Lutomirski, X86 ML, Platform Driver,
	linux-sgx, Dave Hansen, Christopherson, Sean J, nhorman,
	npmccallum, Ayoun, Serge, shay.katz-zamir, haitao.huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko, LKML

On Wed, Nov 28, 2018 at 11:22:28AM -0800, Jarkko Sakkinen wrote:

Good morning, I hope everyone had a pleasant weekend.

> On Wed, Nov 28, 2018 at 04:49:41AM -0600, Dr. Greg wrote:
> > We've been carrying a patch, that drops in on top of the proposed
> > kernel driver, that implements the needed policy management framework
> > for DAC fragile (FLC) platforms.  After a meeting yesterday with the
> > client that is funding the work, a decision was made to release the
> > enhancements when the SGX driver goes mainline.  That will at least
> > give developers the option of creating solutions on Linux that
> > implement the security guarantees that SGX was designed to deliver.

> We do not need yet another policy management framework to the *kernel*.
>
> The token based approach that Andy is proposing is proven and well
> established method to create a mechanism. You can then create a
> daemon to user space that decides who it wants to send tokes.

I guess there will be plenty of time to argue about all of that.

In the meantime, I wanted to confirm that your jarkko-sgx/master
branch contains the proposed driver that is headed upstream.  Before
adding the SFLC patches we thought it best to run the driver through
some testing in order to verify that any problems we generated where
attributable to our work and not the base driver.

At the current time jarkko-sgx/master appears to be having difficulty
initializing the unit test enclave for our trusted runtime API
librarary.  Enclave creation and loading appear to work fine, things
go south after the EINIT ioctl is called on the loaded image.

We specifically isolated the regressions to occur secondary to the
EINIT ioctl being called.  We modified our sgx-load test utility to
pause with the image loaded, but not initialized.  We generated a fair
amount of system activity while the process was holding the enclave
image open and there were no issues.  The process was then allowed to
unmap the virtual memory image without calling EINIT and the system
was fine after that as well.

Symptoms vary, but in all cases appear to be linked to corruption of
the virtual memory infrastructure.  In all cases, the kernel ends up
at a point where any attempt to start a new process hangs and becomes
uninterruptible.  The full kernel failure does not appear to be
synchronous with when EINIT is called, which would support the notion
that something is going wrong with the VM management that is being
workqueue deferred.

This is with your MPX patch applied that corrects issues with the
wrong memory management context being acted upon by that system.  In
any event, the kernel configuration being used for testing does not
have MPX support even enabled.  Given that the changelog for the patch
is indicating the new driver is attempting something unique with
workqueue deferred VM management, it would seem possible that the
driver is tickling bad and possibly untested behavior elsewhere in the
kernel as well.

The enclave in question is not terribly sophisticated by the standards
of our other enclaves, but it is a non-trivial test of SGX
functionality.  It weighs in at about 156K and is generated and signed
in debug mode with version 1.4 compliant metadata.  Obviously it
initializes and runs fine with the out-of-tree driver.

We managed to capture two separate sets of error logs/backtraces that
are included below.  As I'm sure you know, without module support,
working on all of this is a bit painful as it requires the classic
edit-compile-link-boot-whimper procedure.... :-)

Given that the self-test committed to the kernel sources is a trivial
one page enclave and the proposed driver ABI is incompatible with the
released Intel Linux PSW/SDK, this may be the most challenging test
the driver has been put through.  Unless your PSW/SDK team is testing
the new driver behind the scenes.

Obviously let us know if jarkko-master/sgx is not where the action is
at or if you would like us to move forward with alternative testing.

Regression traces follow:

Event 1: -------------------------------------------------------------------
Dec  9 07:35:15 nuc2 kernel: general protection fault: 0000 [#1] SMP PTI
Dec  9 07:35:15 nuc2 kernel: CPU: 1 PID: 1594 Comm: less Not tainted 4.20.0-rc2-sgx-nuc2+ #11
Dec  9 07:35:15 nuc2 kernel: Hardware name: Intel Corporation NUC7CJYH/NUC7JYB, BIOS JYGLKCPX.86A.0046.2018.1103.1316 11/03/2018
Dec  9 07:35:15 nuc2 kernel: RIP: 0010:unmap_vmas+0x3c/0x83
Dec  9 07:35:15 nuc2 kernel: Code: 49 89 cc 53 48 89 f3 4c 8b 6e 40 49 83 bd a0 03 00 00 00 74 32 b9 01 00 00 00 4c 89 e2 4c 89 f6 4c 89 ef e8 db be 01 00 eb 1d <4c> 39 23 73 1d 48 89 de 45 31 c0 4c 89 e1 4c 89 f2 4c 89 ff e8 cb
Dec  9 07:35:15 nuc2 kernel: RSP: 0018:ffff9fd7404c7d90 EFLAGS: 00010282
Dec  9 07:35:15 nuc2 kernel: RAX: 000000000007755e RBX: ffff0f66fad412e0 RCX: 0000000000000000
Dec  9 07:35:15 nuc2 kernel: RDX: ffff8b66f9e42ee0 RSI: ffff8b66f9e42c00 RDI: ffff9fd7404c7dc8
Dec  9 07:35:15 nuc2 kernel: RBP: ffff9fd7404c7db8 R08: 0000000000000014 R09: 000000000007755e
Dec  9 07:35:15 nuc2 kernel: R10: ffff9fd7404c7cc0 R11: 0000000000000000 R12: ffffffffffffffff
Dec  9 07:35:15 nuc2 kernel: R13: ffff8b66f9e42c00 R14: 0000000000000000 R15: ffff9fd7404c7dc8
Dec  9 07:35:15 nuc2 kernel: FS:  0000000000000000(0000) GS:ffff8b66fbe80000(0000) knlGS:0000000000000000
Dec  9 07:35:15 nuc2 kernel: CS:  0010 DS: 002b ES: 002b CR0: 0000000080050033
Dec  9 07:35:15 nuc2 kernel: CR2: 00000000f7e5cce8 CR3: 000000012ec0a000 CR4: 0000000000340ee0
Dec  9 07:35:15 nuc2 kernel: Call Trace:
Dec  9 07:35:15 nuc2 kernel:  exit_mmap+0xab/0x146
Dec  9 07:35:15 nuc2 kernel:  ? __handle_mm_fault+0x6f8/0xb0e
Dec  9 07:35:15 nuc2 kernel:  mmput+0x20/0xa9
Dec  9 07:35:15 nuc2 kernel:  do_exit+0x39d/0x8ad
Dec  9 07:35:15 nuc2 kernel:  ? handle_mm_fault+0x172/0x1c4
Dec  9 07:35:15 nuc2 kernel:  do_group_exit+0x3f/0x96
Dec  9 07:35:15 nuc2 kernel:  __ia32_sys_exit_group+0x12/0x12
Dec  9 07:35:15 nuc2 kernel:  do_fast_syscall_32+0xfd/0x1c1
Dec  9 07:35:15 nuc2 kernel:  entry_SYSENTER_compat+0x7c/0x8e
Dec  9 07:35:15 nuc2 kernel: RIP: 0023:0xf7f638d9
Dec  9 07:35:15 nuc2 kernel: Code: Bad RIP value.
Dec  9 07:35:15 nuc2 kernel: RSP: 002b:00000000ff93594c EFLAGS: 00000206 ORIG_RAX: 00000000000000fc
Dec  9 07:35:15 nuc2 kernel: RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 0000000000000000
Dec  9 07:35:15 nuc2 kernel: RDX: 0000000000000000 RSI: 0000000000000000 RDI: 00000000f7f05288
Dec  9 07:35:15 nuc2 kernel: RBP: 00000000ff935978 R08: 0000000000000000 R09: 0000000000000000
Dec  9 07:35:15 nuc2 kernel: R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000
Dec  9 07:35:15 nuc2 kernel: R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
Dec  9 07:35:15 nuc2 kernel: Modules linked in:
Dec  9 07:35:15 nuc2 kernel: ---[ end trace 590ee48fe9cfd7a6 ]---
Dec  9 07:35:15 nuc2 kernel: RIP: 0010:unmap_vmas+0x3c/0x83
Dec  9 07:35:15 nuc2 kernel: Code: 49 89 cc 53 48 89 f3 4c 8b 6e 40 49 83 bd a0 03 00 00 00 74 32 b9 01 00 00 00 4c 89 e2 4c 89 f6 4c 89 ef e8 db be 01 00 eb 1d <4c> 39 23 73 1d 48 89 de 45 31 c0 4c 89 e1 4c 89 f2 4c 89 ff e8 cb
Dec  9 07:35:15 nuc2 kernel: RSP: 0018:ffff9fd7404c7d90 EFLAGS: 00010282
Dec  9 07:35:15 nuc2 kernel: RAX: 000000000007755e RBX: ffff0f66fad412e0 RCX: 0000000000000000
Dec  9 07:35:15 nuc2 kernel: RDX: ffff8b66f9e42ee0 RSI: ffff8b66f9e42c00 RDI: ffff9fd7404c7dc8
Dec  9 07:35:15 nuc2 kernel: RBP: ffff9fd7404c7db8 R08: 0000000000000014 R09: 000000000007755e
Dec  9 07:35:15 nuc2 kernel: R10: ffff9fd7404c7cc0 R11: 0000000000000000 R12: ffffffffffffffff
Dec  9 07:35:15 nuc2 kernel: R13: ffff8b66f9e42c00 R14: 0000000000000000 R15: ffff9fd7404c7dc8
Dec  9 07:35:15 nuc2 kernel: FS:  0000000000000000(0000) GS:ffff8b66fbe80000(0000) knlGS:0000000000000000
Dec  9 07:35:15 nuc2 kernel: CS:  0010 DS: 002b ES: 002b CR0: 0000000080050033
Dec  9 07:35:15 nuc2 kernel: CR2: 00000000f7f638af CR3: 000000012ec0a000 CR4: 0000000000340ee0
Dec  9 07:35:15 nuc2 kernel: Fixing recursive fault but reboot is needed!
---------------------------------------------------------------------------

Test 2: --------------------------------------------------------------------
Dec  9 07:55:51 nuc2 kernel: BUG: Bad rss-counter state mm:0000000004eb5fd2 idx:0 val:226
Dec  9 07:55:51 nuc2 kernel: BUG: Bad rss-counter state mm:0000000004eb5fd2 idx:1 val:46
Dec  9 07:55:51 nuc2 kernel: BUG: non-zero pgtables_bytes on freeing mm: 12288
Dec  9 07:56:12 nuc2 kernel: sgx-load[1759]: segfault at 80 ip 0000000000402015 sp 00007ffe727f6a30 error 4 in sgx-load[400000+b000]
Dec  9 07:56:12 nuc2 kernel: Code: ff 41 b8 8c 02 00 00 b9 90 78 40 00 ba 55 77 40 00 be cc 74 40 00 48 89 ef 31 c0 e8 35 ef ff ff e9 1e ff ff ff 48 83 4b 50 01 <49> 8b 8c 24 80 00 00 00 48 89 8b a0 00 00 00 49 8b 8c 24 88 00 00
Dec  9 07:56:17 nuc2 kernel: BUG: Bad rss-counter state mm:00000000666f29a9 idx:0 val:1
Dec  9 07:56:17 nuc2 kernel: BUG: Bad rss-counter state mm:00000000666f29a9 idx:1 val:9
Dec  9 07:56:17 nuc2 kernel: BUG: non-zero pgtables_bytes on freeing mm: 4096
Dec  9 07:56:25 nuc2 kernel: BUG: Bad rss-counter state mm:00000000f23b96cf idx:1 val:4
Dec  9 07:57:17 nuc2 kernel: rcu: INFO: rcu_sched self-detected stall on CPU
Dec  9 07:57:17 nuc2 kernel: rcu: ^I0-....: (14999 ticks this GP) idle=55e/1/0x4000000000000002 softirq=3304/3304 fqs=7499 
Dec  9 07:57:17 nuc2 kernel: rcu: ^I (t=15000 jiffies g=5665 q=50)
Dec  9 07:57:17 nuc2 kernel: NMI backtrace for cpu 0
Dec  9 07:57:17 nuc2 kernel: CPU: 0 PID: 1761 Comm: less Not tainted 4.20.0-rc2-sgx-nuc2+ #11
Dec  9 07:57:17 nuc2 kernel: Hardware name: Intel Corporation NUC7CJYH/NUC7JYB, BIOS JYGLKCPX.86A.0046.2018.1103.1316 11/03/2018
Dec  9 07:57:17 nuc2 kernel: Call Trace:
Dec  9 07:57:17 nuc2 kernel:  <IRQ>
Dec  9 07:57:17 nuc2 kernel:  dump_stack+0x4d/0x63
Dec  9 07:57:17 nuc2 kernel:  nmi_cpu_backtrace+0x7a/0x8b
Dec  9 07:57:17 nuc2 kernel:  ? lapic_can_unplug_cpu+0x98/0x98
----------------------------------------------------------------------------

> /Jarkko

Best wishes for a productive week.

Dr. Greg

As always,
Dr. G.W. Wettstein, Ph.D.   Enjellic Systems Development, LLC.
4206 N. 19th Ave.           Specializing in information infra-structure
Fargo, ND  58102            development.
PH: 701-281-1686
FAX: 701-281-3949           EMAIL: greg@enjellic.com
------------------------------------------------------------------------------
"(3)  With sufficient thrust, pigs fly just fine.  However, this is not
      necessarily a good idea.  It is hard to be sure where they are
      going to land, and it could be dangerous sitting under them as they
      fly overhead."
                                -- RFC 1925
                                   Fundamental Truths of Networking

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-09 17:01     ` Pavel Machek
@ 2018-12-10 14:46       ` Dr. Greg
  0 siblings, 0 replies; 155+ messages in thread
From: Dr. Greg @ 2018-12-10 14:46 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Andy Lutomirski, Jarkko Sakkinen, X86 ML, Platform Driver,
	linux-sgx, Dave Hansen, Christopherson, Sean J, nhorman,
	npmccallum, Ayoun, Serge, shay.katz-zamir, haitao.huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, andy, LKML

On Sun, Dec 09, 2018 at 06:01:32PM +0100, Pavel Machek wrote:

> Hi!

Good morning to everyone.

> > On Thu, Nov 15, 2018 at 5:08 PM Jarkko Sakkinen
> > <jarkko.sakkinen@linux.intel.com> wrote:
> > >
> > > 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.
> > >
> > > SGX driver provides a ioctl API for loading and initializing enclaves.
> > > Address range for enclaves is reserved with mmap() and they are
> > > destroyed with munmap(). Enclave construction, measurement and
> > > initialization is done with the provided the ioctl API.
> > 
> > I brought this up a while back, and I think I should re-ask it now
> > that this driver is getting close to ready:
> > 
> > As it stands, there's just one SGX character device, and I imagine
> > that it'll be available to unprivileged applications.  I'm concerned
> > that this isn't quite what we want.  I certainly think that everyone,
> > or at least almost everyone, ought to be able to run normal
> > enclaves.

> I don't think nobody or postfix or guest should be running enclaves
> on my systems. First, I'd like to be able to debug my systems.
>
> Second, sgx quite complex and tricky. It may turn out to be secure
> in the end, but I'd not be surprised if we got few CVEs before we
> get there.
>
> Last, I'd hate to find out in few years that I can't switch to amd
> cpu because firefox now requires sgx.
>
> Just make it root-only or 660 by default. Users can get permission
> in similar way they get rights to audio..

I'm not sure that using root or group restricted access to a character
device is going to stop an ISV from embracing a technology, but that
is an alternate debate.

Relying on discretionary, or mandatory for that matter, access
controls is not consistent with the security architecture of SGX.  The
technology was designed to provide robustness in the face of
aggressors who may have compromised the operating system or hardware
platform.

The lingua franca of SGX security and access controls are MRSIGNER
values.  The SFLC patches that we will be making available, once we
are convinced the upstream driver is working, implement MRSIGNER based
security controls with an absolutely minimal TCB footprint in the
kernel.  This strategy allows the platform owner to use SGX compliant
and cryptographically enforced access controls.

Just as an aside, secondary to our perception that this technology and
what it can do is not widely understood, we are developing a 2-part
LWN article series on SGX and its implications for Linux.

> 								Pavel

Best wishes for a good day and a productive week.

Dr. Greg

As always,
Dr. G.W. Wettstein, Ph.D.   Enjellic Systems Development, LLC.
4206 N. 19th Ave.           Specializing in information infra-structure
Fargo, ND  58102            development.
PH: 701-281-1686
FAX: 701-281-3949           EMAIL: greg@enjellic.com
------------------------------------------------------------------------------
"... remember that innovation is saying 'no' to 1000 things."
                                -- Moxie Marlinspike

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-10 10:49                                   ` Dr. Greg
@ 2018-12-12 18:00                                     ` Jarkko Sakkinen
  2018-12-14 23:59                                       ` Dr. Greg
  0 siblings, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-12 18:00 UTC (permalink / raw)
  To: Dr. Greg
  Cc: Andy Lutomirski, Andy Lutomirski, X86 ML, Platform Driver,
	linux-sgx, Dave Hansen, Christopherson, Sean J, nhorman,
	npmccallum, Ayoun, Serge, shay.katz-zamir, haitao.huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko, LKML

On Mon, Dec 10, 2018 at 04:49:08AM -0600, Dr. Greg wrote:
> In the meantime, I wanted to confirm that your jarkko-sgx/master
> branch contains the proposed driver that is headed upstream.  Before
> adding the SFLC patches we thought it best to run the driver through
> some testing in order to verify that any problems we generated where
> attributable to our work and not the base driver.

The master branch is by definition unstable at the moment i.e. it can
sometimes (not often) contain unfinished changes. Use next for testing.
I update next when I consider the master contents "stable enough".

Thanks.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-12 18:00                                     ` Jarkko Sakkinen
@ 2018-12-14 23:59                                       ` Dr. Greg
  2018-12-15  0:06                                         ` Sean Christopherson
  0 siblings, 1 reply; 155+ messages in thread
From: Dr. Greg @ 2018-12-14 23:59 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Andy Lutomirski, Andy Lutomirski, X86 ML, Platform Driver,
	linux-sgx, Dave Hansen, Christopherson, Sean J, nhorman,
	npmccallum, Ayoun, Serge, shay.katz-zamir, haitao.huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko, LKML, jethro

On Wed, Dec 12, 2018 at 08:00:36PM +0200, Jarkko Sakkinen wrote:

Good evening, I hope the week has gone well for everyone.

> On Mon, Dec 10, 2018 at 04:49:08AM -0600, Dr. Greg wrote:
> > In the meantime, I wanted to confirm that your jarkko-sgx/master
> > branch contains the proposed driver that is headed upstream.
> > Before adding the SFLC patches we thought it best to run the
> > driver through some testing in order to verify that any problems
> > we generated where attributable to our work and not the base
> > driver.
>
> The master branch is by definition unstable at the moment i.e. it
> can sometimes (not often) contain unfinished changes. Use next for
> testing.  I update next when I consider the master contents "stable
> enough".

I noticed in the last day or so that you appeared to sync
jarkko-sgx/master with jarkko-sgx/next, so I checked out a local
branch against jarkko-sgx/next and ran it against our unit tests.
Based on what we are seeing the driver is still experiencing issues
with initialization of a non-trivial enclave.

On the first test boot of the new kernel, the EINIT ioctl consistently
returned EBUSY over multiple invocations of the unit test.  This did
not appear to generate any negative issues with the kernel at large.

We rebooted the box to run the test against a fresh kernel load.  This
time around we experienced issues similar to what we had previously
described.  The EINIT ioctl generates a segmentation fault which seems
to largely incapacitate the kernel.

Here are the logs and first backtrace from the test:

---------------------------------------------------------------------------
Dec 14 13:25:06 nuc2 kernel: PGD 4f001067 P4D 4f001067 PUD 0 
Dec 14 13:25:06 nuc2 kernel: BUG: unable to handle kernel paging request at ffff97bf3ae916fe
Dec 14 13:25:06 nuc2 kernel: Oops: 0002 [#1] SMP PTI
Dec 14 13:25:06 nuc2 kernel: CPU: 1 PID: 34 Comm: kworker/1:1 Not tainted 4.20.0-rc2-sgx-nuc2+ #12
Dec 14 13:25:06 nuc2 kernel: Hardware name: Intel Corporation NUC7CJYH/NUC7JYB, BIOS JYGLKCPX.86A.0046.2018.1103.1316 11/03/2018
Dec 14 13:25:06 nuc2 kernel: Workqueue: events cache_reap
Dec 14 13:25:06 nuc2 kernel: RIP: 0010:free_block+0xe3/0x182
Dec 14 13:25:06 nuc2 kernel: Code: 20 45 29 d4 41 d3 ec 0f b6 4f 1d 45 01 e2 41 d3 ea 41 8b 49 30 ff c9 49 83 79 20 00 41 89 49 30 75 04 4d 89 59 20 4d 8b 59 20 <45> 88 14 0b 49 8d 49 08 41 83 79 30 00 75 1a 4c 8b 50 28 49 89 4a
Dec 14 13:25:06 nuc2 kernel: RSP: 0018:ffffb90800123db0 EFLAGS: 00210046
Dec 14 13:25:06 nuc2 kernel: RAX: ffff97be3b419080 RBX: 000000000000000f RCX: 00000000ffffff7e
Dec 14 13:25:06 nuc2 kernel: RDX: 0000000000000018 RSI: ffffd907ffc82b70 RDI: ffff97be3b44c200
Dec 14 13:25:06 nuc2 kernel: RBP: ffffb90800123dd8 R08: ffffb90800123e10 R09: fffff9b345eba440
Dec 14 13:25:06 nuc2 kernel: R10: 000000000051f663 R11: ffff97be3ae91780 R12: 0000000011ede5c3
Dec 14 13:25:06 nuc2 kernel: R13: ffffffff80000000 R14: ffff97be3b419088 R15: ffff97be3b4190a8
Dec 14 13:25:06 nuc2 kernel: FS:  0000000000000000(0000) GS:ffff97be3be80000(0000) knlGS:0000000000000000
Dec 14 13:25:06 nuc2 kernel: CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
Dec 14 13:25:06 nuc2 kernel: CR2: ffff97bf3ae916fe CR3: 000000004ec0a000 CR4: 0000000000340ee0
Dec 14 13:25:06 nuc2 kernel: Call Trace:
Dec 14 13:25:06 nuc2 kernel:  drain_array_locked+0x50/0x75
Dec 14 13:25:06 nuc2 kernel:  drain_array.constprop.67+0x57/0x72
Dec 14 13:25:06 nuc2 kernel:  cache_reap+0x58/0x101
Dec 14 13:25:06 nuc2 kernel:  process_one_work+0x183/0x271
Dec 14 13:25:06 nuc2 kernel:  worker_thread+0x1e5/0x2b4
Dec 14 13:25:06 nuc2 kernel:  ? cancel_delayed_work_sync+0x10/0x10
Dec 14 13:25:06 nuc2 kernel:  kthread+0x116/0x11e
Dec 14 13:25:06 nuc2 kernel:  ? kthread_park+0x7e/0x7e
Dec 14 13:25:06 nuc2 kernel:  ret_from_fork+0x1f/0x40
Dec 14 13:25:06 nuc2 kernel: Modules linked in:
Dec 14 13:25:06 nuc2 kernel: CR2: ffff97bf3ae916fe
Dec 14 13:25:06 nuc2 kernel: ---[ end trace 7f5dc24edc7285b3 ]---
Dec 14 13:25:06 nuc2 kernel: RIP: 0010:free_block+0xe3/0x182
Dec 14 13:25:06 nuc2 kernel: Code: 20 45 29 d4 41 d3 ec 0f b6 4f 1d 45 01 e2 41 d3 ea 41 8b 49 30 ff c9 49 83 79 20 00 41 89 49 30 75 04 4d 89 59 20 4d 8b 59 20 <45> 88 14 0b 49 8d 49 08 41 83 79 30 00 75 1a 4c 8b 50 28 49 89 4a
Dec 14 13:25:06 nuc2 kernel: RSP: 0018:ffffb90800123db0 EFLAGS: 00210046
Dec 14 13:25:06 nuc2 kernel: RAX: ffff97be3b419080 RBX: 000000000000000f RCX: 00000000ffffff7e
Dec 14 13:25:06 nuc2 kernel: RDX: 0000000000000018 RSI: ffffd907ffc82b70 RDI: ffff97be3b44c200
Dec 14 13:25:06 nuc2 kernel: RBP: ffffb90800123dd8 R08: ffffb90800123e10 R09: fffff9b345eba440
Dec 14 13:25:06 nuc2 kernel: R10: 000000000051f663 R11: ffff97be3ae91780 R12: 0000000011ede5c3
Dec 14 13:25:06 nuc2 kernel: R13: ffffffff80000000 R14: ffff97be3b419088 R15: ffff97be3b4190a8
Dec 14 13:25:06 nuc2 kernel: FS:  0000000000000000(0000) GS:ffff97be3be80000(0000) knlGS:0000000000000000
Dec 14 13:25:06 nuc2 kernel: CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
Dec 14 13:25:06 nuc2 kernel: CR2: ffff97bf3ae916fe CR3: 000000004ec0a000 CR4: 0000000000340ee0
Dec 14 13:25:21 nuc2 kernel: sgx-load[1596]: segfault at 80 ip 0000000000402015 sp 00007ffdb267e2f0 error 4 in sgx-load[400000+b000]
Dec 14 13:25:21 nuc2 kernel: Code: ff 41 b8 8c 02 00 00 b9 90 78 40 00 ba 5d 77 40 00 be cc 74 40 00 48 89 ef 31 c0 e8 35 ef ff ff e9 1e ff ff ff 48 83 4b 50 01 <49> 8b 8c 24 80 00 00 00 48 89 8b a0 00 00 00 49 8b 8c 24 88 00 00
---------------------------------------------------------------------------

This is a post 'make distclean' compile from a fresh branch of
jarkko-sgx/next with no modifications.

For testing purposes we created a branch of our PSW and dropped the
EINITTOKEN pointer from the sgx_enclave_init structure in order to
make our runtime compatible with the new variant of
SGX_IOC_ENCLAVE_INIT.  As I noted in my previous e-mail, our runtime
doesn't appear to be having any issues with the creation and load of
the enclave.

We are assuming there is an intent for the new driver to be reasonably
compatible with the current Intel PSW/SDK.  Even if this isn't the
case it would seem to be problematic if it is possible for a badly
formed IOCTL call to tip the kernel over.

Jethro are you guys testing the driver against any non-trivial
enclaves?

> Thanks.
> 
> /Jarkko

Let us know if you would like us to experiment with anything in
particular.

Have a good weekend.

Dr. Greg

As always,
Dr. G.W. Wettstein, Ph.D.   Enjellic Systems Development, LLC.
4206 N. 19th Ave.           Specializing in information infra-structure
Fargo, ND  58102            development.
PH: 701-281-1686
FAX: 701-281-3949           EMAIL: greg@enjellic.com
------------------------------------------------------------------------------
"You and Uncle Pete drank the whole thing?  That was a $250.00 bottle
 of whisky.

 Yeah, it was good."
                                -- Rick Engen
                                   Resurrection.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-14 23:59                                       ` Dr. Greg
@ 2018-12-15  0:06                                         ` Sean Christopherson
  2018-12-15 23:22                                           ` Dr. Greg
  2018-12-17 13:28                                           ` Jarkko Sakkinen
  0 siblings, 2 replies; 155+ messages in thread
From: Sean Christopherson @ 2018-12-15  0:06 UTC (permalink / raw)
  To: Dr. Greg
  Cc: Jarkko Sakkinen, Andy Lutomirski, Andy Lutomirski, X86 ML,
	Platform Driver, linux-sgx, Dave Hansen, nhorman, npmccallum,
	Ayoun, Serge, shay.katz-zamir, haitao.huang, Andy Shevchenko,
	Thomas Gleixner, Svahn, Kai, mark.shanahan, Suresh Siddha,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin, Darren Hart,
	Andy Shevchenko, LKML, jethro

On Fri, Dec 14, 2018 at 05:59:17PM -0600, Dr. Greg wrote:
> On Wed, Dec 12, 2018 at 08:00:36PM +0200, Jarkko Sakkinen wrote:
> 
> Good evening, I hope the week has gone well for everyone.
> 
> > On Mon, Dec 10, 2018 at 04:49:08AM -0600, Dr. Greg wrote:
> > > In the meantime, I wanted to confirm that your jarkko-sgx/master
> > > branch contains the proposed driver that is headed upstream.
> > > Before adding the SFLC patches we thought it best to run the
> > > driver through some testing in order to verify that any problems
> > > we generated where attributable to our work and not the base
> > > driver.
> >
> > The master branch is by definition unstable at the moment i.e. it
> > can sometimes (not often) contain unfinished changes. Use next for
> > testing.  I update next when I consider the master contents "stable
> > enough".
> 
> I noticed in the last day or so that you appeared to sync
> jarkko-sgx/master with jarkko-sgx/next, so I checked out a local
> branch against jarkko-sgx/next and ran it against our unit tests.
> Based on what we are seeing the driver is still experiencing issues
> with initialization of a non-trivial enclave.

master branch is broken, looks like the VMA code Jarkko is reworking is
buggy.  I should be able to help debug this next week.

[  504.149548] ------------[ cut here ]------------
[  504.149550] kernel BUG at /home/sean/go/src/kernel.org/linux/mm/mmap.c:669!
[  504.150288] invalid opcode: 0000 [#1] SMP
[  504.150614] CPU: 2 PID: 237 Comm: kworker/u20:2 Not tainted 4.20.0-rc2+ #267
[  504.151165] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
[  504.151818] Workqueue: sgx-encl-wq sgx_encl_release_worker
[  504.152267] RIP: 0010:__vma_adjust+0x64a/0x820
[  504.152626] Code: ff 48 89 50 18 e9 6f fc ff ff 4c 8b ab 88 00 00 00 45 31 e4 e9 61 fb ff ff 31 c0 48 83 c4 60 5b 5d 41 5c 41 5d 41 5e 41 5f c3 <0f> 0b 49 89 de 49 83 c6 20 0f 84 06 fe ff ff 49 8d 7e e0 e8 fe ee
[  504.154109] RSP: 0000:ffffc900004ebd60 EFLAGS: 00010206
[  504.154535] RAX: 00007fd92ef7e000 RBX: ffff888467af16c0 RCX: ffff888467af16e0
[  504.155104] RDX: ffff888458fd09e0 RSI: 00007fd954021000 RDI: ffff88846bf9e798
[  504.155673] RBP: ffff888467af1480 R08: ffff88845bea2000 R09: 0000000000000000
[  504.156242] R10: 0000000080000000 R11: fefefefefefefeff R12: 0000000000000000
[  504.156810] R13: ffff88846bf9e790 R14: ffff888467af1b70 R15: ffff888467af1b60
[  504.157378] FS:  0000000000000000(0000) GS:ffff88846f700000(0000) knlGS:0000000000000000
[  504.158021] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  504.158483] CR2: 00007f2c56e99000 CR3: 0000000005009001 CR4: 0000000000360ee0
[  504.159054] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[  504.159623] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[  504.160193] Call Trace:
[  504.160406]  __split_vma+0x16f/0x180
[  504.160706]  ? __switch_to_asm+0x40/0x70
[  504.161024]  __do_munmap+0xfb/0x450
[  504.161308]  sgx_encl_release_worker+0x44/0x70
[  504.161675]  process_one_work+0x200/0x3f0
[  504.162004]  worker_thread+0x2d/0x3d0
[  504.162301]  ? process_one_work+0x3f0/0x3f0
[  504.162645]  kthread+0x113/0x130
[  504.162912]  ? kthread_park+0x90/0x90
[  504.163209]  ret_from_fork+0x35/0x40
[  504.163503] Modules linked in: bridge stp llc
[  504.163866] ---[ end trace 83076139fc25e3e0 ]---

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-15  0:06                                         ` Sean Christopherson
@ 2018-12-15 23:22                                           ` Dr. Greg
  2018-12-17 14:27                                             ` Sean Christopherson
  2018-12-17 13:28                                           ` Jarkko Sakkinen
  1 sibling, 1 reply; 155+ messages in thread
From: Dr. Greg @ 2018-12-15 23:22 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Jarkko Sakkinen, Andy Lutomirski, Andy Lutomirski, X86 ML,
	Platform Driver, linux-sgx, Dave Hansen, nhorman, npmccallum,
	Ayoun, Serge, shay.katz-zamir, haitao.huang, Andy Shevchenko,
	Thomas Gleixner, Svahn, Kai, mark.shanahan, Suresh Siddha,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin, Darren Hart,
	Andy Shevchenko, LKML, jethro

On Fri, Dec 14, 2018 at 04:06:27PM -0800, Sean Christopherson wrote:

Good afternoon, I hope the weekend is going well for everyone.

> On Fri, Dec 14, 2018 at 05:59:17PM -0600, Dr. Greg wrote:
> > On Wed, Dec 12, 2018 at 08:00:36PM +0200, Jarkko Sakkinen wrote:
> > 
> > Good evening, I hope the week has gone well for everyone.
> > 
> > > On Mon, Dec 10, 2018 at 04:49:08AM -0600, Dr. Greg wrote:
> > > > In the meantime, I wanted to confirm that your jarkko-sgx/master
> > > > branch contains the proposed driver that is headed upstream.
> > > > Before adding the SFLC patches we thought it best to run the
> > > > driver through some testing in order to verify that any problems
> > > > we generated where attributable to our work and not the base
> > > > driver.
> > >
> > > The master branch is by definition unstable at the moment i.e. it
> > > can sometimes (not often) contain unfinished changes. Use next for
> > > testing.  I update next when I consider the master contents "stable
> > > enough".
> > 
> > I noticed in the last day or so that you appeared to sync
> > jarkko-sgx/master with jarkko-sgx/next, so I checked out a local
> > branch against jarkko-sgx/next and ran it against our unit tests.
> > Based on what we are seeing the driver is still experiencing issues
> > with initialization of a non-trivial enclave.

> master branch is broken, looks like the VMA code Jarkko is reworking is
> buggy.  I should be able to help debug this next week.
> 
> [  504.149548] ------------[ cut here ]------------
> [  504.149550] kernel BUG at /home/sean/go/src/kernel.org/linux/mm/mmap.c:669!

Rodger, dodger.

Let us know when you think you have something working pushed up into
one of the branches and we will put it on the bench here in the lab
and see what our runtime is able to do with it.

BTW, your new vDSO work appears to be shaping up well.  Just out of
curiosity though, how are you testing and validating the new vDSO
based exception handler if it isn't possible to initialize and run an
enclave with the new driver?

We will look forward to hearing from you.

Have a good remainder of the weekend.

Dr. Greg

As always,
Dr. G.W. Wettstein, Ph.D.   Enjellic Systems Development, LLC.
4206 N. 19th Ave.           Specializing in information infra-structure
Fargo, ND  58102            development.
PH: 701-281-1686
FAX: 701-281-3949           EMAIL: greg@enjellic.com
------------------------------------------------------------------------------
"Don't worry about people stealing your ideas.  If your ideas are any
 good, you'll have to ram them down people's throats."
                                -- Howard Aiken

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-15  0:06                                         ` Sean Christopherson
  2018-12-15 23:22                                           ` Dr. Greg
@ 2018-12-17 13:28                                           ` Jarkko Sakkinen
  2018-12-17 13:39                                             ` Jarkko Sakkinen
  1 sibling, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-17 13:28 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Dr. Greg, Andy Lutomirski, Andy Lutomirski, X86 ML,
	Platform Driver, linux-sgx, Dave Hansen, nhorman, npmccallum,
	Ayoun, Serge, shay.katz-zamir, haitao.huang, Andy Shevchenko,
	Thomas Gleixner, Svahn, Kai, mark.shanahan, Suresh Siddha,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin, Darren Hart,
	Andy Shevchenko, LKML, jethro

On Fri, Dec 14, 2018 at 04:06:27PM -0800, Sean Christopherson wrote:
> [  504.149548] ------------[ cut here ]------------
> [  504.149550] kernel BUG at /home/sean/go/src/kernel.org/linux/mm/mmap.c:669!
> [  504.150288] invalid opcode: 0000 [#1] SMP
> [  504.150614] CPU: 2 PID: 237 Comm: kworker/u20:2 Not tainted 4.20.0-rc2+ #267
> [  504.151165] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
> [  504.151818] Workqueue: sgx-encl-wq sgx_encl_release_worker
> [  504.152267] RIP: 0010:__vma_adjust+0x64a/0x820
> [  504.152626] Code: ff 48 89 50 18 e9 6f fc ff ff 4c 8b ab 88 00 00 00 45 31 e4 e9 61 fb ff ff 31 c0 48 83 c4 60 5b 5d 41 5c 41 5d 41 5e 41 5f c3 <0f> 0b 49 89 de 49 83 c6 20 0f 84 06 fe ff ff 49 8d 7e e0 e8 fe ee
> [  504.154109] RSP: 0000:ffffc900004ebd60 EFLAGS: 00010206
> [  504.154535] RAX: 00007fd92ef7e000 RBX: ffff888467af16c0 RCX: ffff888467af16e0
> [  504.155104] RDX: ffff888458fd09e0 RSI: 00007fd954021000 RDI: ffff88846bf9e798
> [  504.155673] RBP: ffff888467af1480 R08: ffff88845bea2000 R09: 0000000000000000
> [  504.156242] R10: 0000000080000000 R11: fefefefefefefeff R12: 0000000000000000
> [  504.156810] R13: ffff88846bf9e790 R14: ffff888467af1b70 R15: ffff888467af1b60
> [  504.157378] FS:  0000000000000000(0000) GS:ffff88846f700000(0000) knlGS:0000000000000000
> [  504.158021] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [  504.158483] CR2: 00007f2c56e99000 CR3: 0000000005009001 CR4: 0000000000360ee0
> [  504.159054] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> [  504.159623] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
> [  504.160193] Call Trace:
> [  504.160406]  __split_vma+0x16f/0x180
> [  504.160706]  ? __switch_to_asm+0x40/0x70
> [  504.161024]  __do_munmap+0xfb/0x450
> [  504.161308]  sgx_encl_release_worker+0x44/0x70
> [  504.161675]  process_one_work+0x200/0x3f0
> [  504.162004]  worker_thread+0x2d/0x3d0
> [  504.162301]  ? process_one_work+0x3f0/0x3f0
> [  504.162645]  kthread+0x113/0x130
> [  504.162912]  ? kthread_park+0x90/0x90
> [  504.163209]  ret_from_fork+0x35/0x40
> [  504.163503] Modules linked in: bridge stp llc
> [  504.163866] ---[ end trace 83076139fc25e3e0 ]---

There was a race with release and swapping code that I thought I fixed,
and this is looks like a race there. Have to recheck what I did not
consider. Anyway, though to share this if you have time to look at it.
That is the part where something is now unsync most probably.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 13:28                                           ` Jarkko Sakkinen
@ 2018-12-17 13:39                                             ` Jarkko Sakkinen
  2018-12-17 14:08                                               ` Jarkko Sakkinen
  0 siblings, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-17 13:39 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Dr. Greg, Andy Lutomirski, Andy Lutomirski, X86 ML,
	Platform Driver, linux-sgx, Dave Hansen, nhorman, npmccallum,
	Ayoun, Serge, shay.katz-zamir, haitao.huang, Andy Shevchenko,
	Thomas Gleixner, Svahn, Kai, mark.shanahan, Suresh Siddha,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin, Darren Hart,
	Andy Shevchenko, LKML, jethro

On Mon, Dec 17, 2018 at 03:28:59PM +0200, Jarkko Sakkinen wrote:
> On Fri, Dec 14, 2018 at 04:06:27PM -0800, Sean Christopherson wrote:
> > [  504.149548] ------------[ cut here ]------------
> > [  504.149550] kernel BUG at /home/sean/go/src/kernel.org/linux/mm/mmap.c:669!
> > [  504.150288] invalid opcode: 0000 [#1] SMP
> > [  504.150614] CPU: 2 PID: 237 Comm: kworker/u20:2 Not tainted 4.20.0-rc2+ #267
> > [  504.151165] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
> > [  504.151818] Workqueue: sgx-encl-wq sgx_encl_release_worker
> > [  504.152267] RIP: 0010:__vma_adjust+0x64a/0x820
> > [  504.152626] Code: ff 48 89 50 18 e9 6f fc ff ff 4c 8b ab 88 00 00 00 45 31 e4 e9 61 fb ff ff 31 c0 48 83 c4 60 5b 5d 41 5c 41 5d 41 5e 41 5f c3 <0f> 0b 49 89 de 49 83 c6 20 0f 84 06 fe ff ff 49 8d 7e e0 e8 fe ee
> > [  504.154109] RSP: 0000:ffffc900004ebd60 EFLAGS: 00010206
> > [  504.154535] RAX: 00007fd92ef7e000 RBX: ffff888467af16c0 RCX: ffff888467af16e0
> > [  504.155104] RDX: ffff888458fd09e0 RSI: 00007fd954021000 RDI: ffff88846bf9e798
> > [  504.155673] RBP: ffff888467af1480 R08: ffff88845bea2000 R09: 0000000000000000
> > [  504.156242] R10: 0000000080000000 R11: fefefefefefefeff R12: 0000000000000000
> > [  504.156810] R13: ffff88846bf9e790 R14: ffff888467af1b70 R15: ffff888467af1b60
> > [  504.157378] FS:  0000000000000000(0000) GS:ffff88846f700000(0000) knlGS:0000000000000000
> > [  504.158021] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> > [  504.158483] CR2: 00007f2c56e99000 CR3: 0000000005009001 CR4: 0000000000360ee0
> > [  504.159054] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> > [  504.159623] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
> > [  504.160193] Call Trace:
> > [  504.160406]  __split_vma+0x16f/0x180
> > [  504.160706]  ? __switch_to_asm+0x40/0x70
> > [  504.161024]  __do_munmap+0xfb/0x450
> > [  504.161308]  sgx_encl_release_worker+0x44/0x70
> > [  504.161675]  process_one_work+0x200/0x3f0
> > [  504.162004]  worker_thread+0x2d/0x3d0
> > [  504.162301]  ? process_one_work+0x3f0/0x3f0
> > [  504.162645]  kthread+0x113/0x130
> > [  504.162912]  ? kthread_park+0x90/0x90
> > [  504.163209]  ret_from_fork+0x35/0x40
> > [  504.163503] Modules linked in: bridge stp llc
> > [  504.163866] ---[ end trace 83076139fc25e3e0 ]---
> 
> There was a race with release and swapping code that I thought I fixed,
> and this is looks like a race there. Have to recheck what I did not
> consider. Anyway, though to share this if you have time to look at it.
> That is the part where something is now unsync most probably.

I think I found it. I was careless to make sgx_encl_release() to use
sgx_invalidate(), which does not delete pages in the case when enclave
is already marked as dead. This was after I had fixed the race that I
had there in the first place. That is why I was puzzled why it suddenly
reappeared.

Would be nice to use sgx_invalidate() also in release for consistency in
semantics sake so maybe just delete this:

	if (encl->flags & SGX_ENCL_DEAD)
		return;

?

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 13:39                                             ` Jarkko Sakkinen
@ 2018-12-17 14:08                                               ` Jarkko Sakkinen
  2018-12-17 14:13                                                 ` Jarkko Sakkinen
  2018-12-17 17:31                                                 ` Sean Christopherson
  0 siblings, 2 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-17 14:08 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Dr. Greg, Andy Lutomirski, Andy Lutomirski, X86 ML,
	Platform Driver, linux-sgx, Dave Hansen, nhorman, npmccallum,
	Ayoun, Serge, shay.katz-zamir, haitao.huang, Andy Shevchenko,
	Thomas Gleixner, Svahn, Kai, mark.shanahan, Suresh Siddha,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin, Darren Hart,
	Andy Shevchenko, LKML, jethro

On Mon, Dec 17, 2018 at 03:39:28PM +0200, Jarkko Sakkinen wrote:
> On Mon, Dec 17, 2018 at 03:28:59PM +0200, Jarkko Sakkinen wrote:
> > On Fri, Dec 14, 2018 at 04:06:27PM -0800, Sean Christopherson wrote:
> > > [  504.149548] ------------[ cut here ]------------
> > > [  504.149550] kernel BUG at /home/sean/go/src/kernel.org/linux/mm/mmap.c:669!
> > > [  504.150288] invalid opcode: 0000 [#1] SMP
> > > [  504.150614] CPU: 2 PID: 237 Comm: kworker/u20:2 Not tainted 4.20.0-rc2+ #267
> > > [  504.151165] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
> > > [  504.151818] Workqueue: sgx-encl-wq sgx_encl_release_worker
> > > [  504.152267] RIP: 0010:__vma_adjust+0x64a/0x820
> > > [  504.152626] Code: ff 48 89 50 18 e9 6f fc ff ff 4c 8b ab 88 00 00 00 45 31 e4 e9 61 fb ff ff 31 c0 48 83 c4 60 5b 5d 41 5c 41 5d 41 5e 41 5f c3 <0f> 0b 49 89 de 49 83 c6 20 0f 84 06 fe ff ff 49 8d 7e e0 e8 fe ee
> > > [  504.154109] RSP: 0000:ffffc900004ebd60 EFLAGS: 00010206
> > > [  504.154535] RAX: 00007fd92ef7e000 RBX: ffff888467af16c0 RCX: ffff888467af16e0
> > > [  504.155104] RDX: ffff888458fd09e0 RSI: 00007fd954021000 RDI: ffff88846bf9e798
> > > [  504.155673] RBP: ffff888467af1480 R08: ffff88845bea2000 R09: 0000000000000000
> > > [  504.156242] R10: 0000000080000000 R11: fefefefefefefeff R12: 0000000000000000
> > > [  504.156810] R13: ffff88846bf9e790 R14: ffff888467af1b70 R15: ffff888467af1b60
> > > [  504.157378] FS:  0000000000000000(0000) GS:ffff88846f700000(0000) knlGS:0000000000000000
> > > [  504.158021] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> > > [  504.158483] CR2: 00007f2c56e99000 CR3: 0000000005009001 CR4: 0000000000360ee0
> > > [  504.159054] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> > > [  504.159623] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
> > > [  504.160193] Call Trace:
> > > [  504.160406]  __split_vma+0x16f/0x180
> > > [  504.160706]  ? __switch_to_asm+0x40/0x70
> > > [  504.161024]  __do_munmap+0xfb/0x450
> > > [  504.161308]  sgx_encl_release_worker+0x44/0x70
> > > [  504.161675]  process_one_work+0x200/0x3f0
> > > [  504.162004]  worker_thread+0x2d/0x3d0
> > > [  504.162301]  ? process_one_work+0x3f0/0x3f0
> > > [  504.162645]  kthread+0x113/0x130
> > > [  504.162912]  ? kthread_park+0x90/0x90
> > > [  504.163209]  ret_from_fork+0x35/0x40
> > > [  504.163503] Modules linked in: bridge stp llc
> > > [  504.163866] ---[ end trace 83076139fc25e3e0 ]---
> > 
> > There was a race with release and swapping code that I thought I fixed,
> > and this is looks like a race there. Have to recheck what I did not
> > consider. Anyway, though to share this if you have time to look at it.
> > That is the part where something is now unsync most probably.
> 
> I think I found it. I was careless to make sgx_encl_release() to use
> sgx_invalidate(), which does not delete pages in the case when enclave
> is already marked as dead. This was after I had fixed the race that I
> had there in the first place. That is why I was puzzled why it suddenly
> reappeared.
> 
> Would be nice to use sgx_invalidate() also in release for consistency in
> semantics sake so maybe just delete this:
> 
> 	if (encl->flags & SGX_ENCL_DEAD)
> 		return;

Updated master, not at this point next.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 14:08                                               ` Jarkko Sakkinen
@ 2018-12-17 14:13                                                 ` Jarkko Sakkinen
  2018-12-17 16:34                                                   ` Dr. Greg
  2018-12-17 17:31                                                 ` Sean Christopherson
  1 sibling, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-17 14:13 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Dr. Greg, Andy Lutomirski, Andy Lutomirski, X86 ML,
	Platform Driver, linux-sgx, Dave Hansen, nhorman, npmccallum,
	Ayoun, Serge, shay.katz-zamir, haitao.huang, Andy Shevchenko,
	Thomas Gleixner, Svahn, Kai, mark.shanahan, Suresh Siddha,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin, Darren Hart,
	Andy Shevchenko, LKML, jethro

On Mon, Dec 17, 2018 at 04:08:11PM +0200, Jarkko Sakkinen wrote:
> On Mon, Dec 17, 2018 at 03:39:28PM +0200, Jarkko Sakkinen wrote:
> > On Mon, Dec 17, 2018 at 03:28:59PM +0200, Jarkko Sakkinen wrote:
> > > On Fri, Dec 14, 2018 at 04:06:27PM -0800, Sean Christopherson wrote:
> > > > [  504.149548] ------------[ cut here ]------------
> > > > [  504.149550] kernel BUG at /home/sean/go/src/kernel.org/linux/mm/mmap.c:669!
> > > > [  504.150288] invalid opcode: 0000 [#1] SMP
> > > > [  504.150614] CPU: 2 PID: 237 Comm: kworker/u20:2 Not tainted 4.20.0-rc2+ #267
> > > > [  504.151165] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
> > > > [  504.151818] Workqueue: sgx-encl-wq sgx_encl_release_worker
> > > > [  504.152267] RIP: 0010:__vma_adjust+0x64a/0x820
> > > > [  504.152626] Code: ff 48 89 50 18 e9 6f fc ff ff 4c 8b ab 88 00 00 00 45 31 e4 e9 61 fb ff ff 31 c0 48 83 c4 60 5b 5d 41 5c 41 5d 41 5e 41 5f c3 <0f> 0b 49 89 de 49 83 c6 20 0f 84 06 fe ff ff 49 8d 7e e0 e8 fe ee
> > > > [  504.154109] RSP: 0000:ffffc900004ebd60 EFLAGS: 00010206
> > > > [  504.154535] RAX: 00007fd92ef7e000 RBX: ffff888467af16c0 RCX: ffff888467af16e0
> > > > [  504.155104] RDX: ffff888458fd09e0 RSI: 00007fd954021000 RDI: ffff88846bf9e798
> > > > [  504.155673] RBP: ffff888467af1480 R08: ffff88845bea2000 R09: 0000000000000000
> > > > [  504.156242] R10: 0000000080000000 R11: fefefefefefefeff R12: 0000000000000000
> > > > [  504.156810] R13: ffff88846bf9e790 R14: ffff888467af1b70 R15: ffff888467af1b60
> > > > [  504.157378] FS:  0000000000000000(0000) GS:ffff88846f700000(0000) knlGS:0000000000000000
> > > > [  504.158021] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> > > > [  504.158483] CR2: 00007f2c56e99000 CR3: 0000000005009001 CR4: 0000000000360ee0
> > > > [  504.159054] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> > > > [  504.159623] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
> > > > [  504.160193] Call Trace:
> > > > [  504.160406]  __split_vma+0x16f/0x180
> > > > [  504.160706]  ? __switch_to_asm+0x40/0x70
> > > > [  504.161024]  __do_munmap+0xfb/0x450
> > > > [  504.161308]  sgx_encl_release_worker+0x44/0x70
> > > > [  504.161675]  process_one_work+0x200/0x3f0
> > > > [  504.162004]  worker_thread+0x2d/0x3d0
> > > > [  504.162301]  ? process_one_work+0x3f0/0x3f0
> > > > [  504.162645]  kthread+0x113/0x130
> > > > [  504.162912]  ? kthread_park+0x90/0x90
> > > > [  504.163209]  ret_from_fork+0x35/0x40
> > > > [  504.163503] Modules linked in: bridge stp llc
> > > > [  504.163866] ---[ end trace 83076139fc25e3e0 ]---
> > > 
> > > There was a race with release and swapping code that I thought I fixed,
> > > and this is looks like a race there. Have to recheck what I did not
> > > consider. Anyway, though to share this if you have time to look at it.
> > > That is the part where something is now unsync most probably.
> > 
> > I think I found it. I was careless to make sgx_encl_release() to use
> > sgx_invalidate(), which does not delete pages in the case when enclave
> > is already marked as dead. This was after I had fixed the race that I
> > had there in the first place. That is why I was puzzled why it suddenly
> > reappeared.
> > 
> > Would be nice to use sgx_invalidate() also in release for consistency in
> > semantics sake so maybe just delete this:
> > 
> > 	if (encl->flags & SGX_ENCL_DEAD)
> > 		return;
> 
> Updated master, not at this point next.

If I checked this right was that mmu_notifier_unregister() cause DEAD
to set, and thus when sgx_invalidate() is executed, it returns without
doing anything...

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-15 23:22                                           ` Dr. Greg
@ 2018-12-17 14:27                                             ` Sean Christopherson
  0 siblings, 0 replies; 155+ messages in thread
From: Sean Christopherson @ 2018-12-17 14:27 UTC (permalink / raw)
  To: Dr. Greg
  Cc: Jarkko Sakkinen, Andy Lutomirski, Andy Lutomirski, X86 ML,
	Platform Driver, linux-sgx, Dave Hansen, nhorman, npmccallum,
	Ayoun, Serge, shay.katz-zamir, haitao.huang, Andy Shevchenko,
	Thomas Gleixner, Svahn, Kai, mark.shanahan, Suresh Siddha,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin, Darren Hart,
	Andy Shevchenko, LKML, jethro

On Sat, Dec 15, 2018 at 05:22:31PM -0600, Dr. Greg wrote:
> On Fri, Dec 14, 2018 at 04:06:27PM -0800, Sean Christopherson wrote:
> 
> Good afternoon, I hope the weekend is going well for everyone.
> 
> > On Fri, Dec 14, 2018 at 05:59:17PM -0600, Dr. Greg wrote:
> > > On Wed, Dec 12, 2018 at 08:00:36PM +0200, Jarkko Sakkinen wrote:
> > > 
> > > Good evening, I hope the week has gone well for everyone.
> > > 
> > > > On Mon, Dec 10, 2018 at 04:49:08AM -0600, Dr. Greg wrote:
> > > > > In the meantime, I wanted to confirm that your jarkko-sgx/master
> > > > > branch contains the proposed driver that is headed upstream.
> > > > > Before adding the SFLC patches we thought it best to run the
> > > > > driver through some testing in order to verify that any problems
> > > > > we generated where attributable to our work and not the base
> > > > > driver.
> > > >
> > > > The master branch is by definition unstable at the moment i.e. it
> > > > can sometimes (not often) contain unfinished changes. Use next for
> > > > testing.  I update next when I consider the master contents "stable
> > > > enough".
> > > 
> > > I noticed in the last day or so that you appeared to sync
> > > jarkko-sgx/master with jarkko-sgx/next, so I checked out a local
> > > branch against jarkko-sgx/next and ran it against our unit tests.
> > > Based on what we are seeing the driver is still experiencing issues
> > > with initialization of a non-trivial enclave.
> 
> > master branch is broken, looks like the VMA code Jarkko is reworking is
> > buggy.  I should be able to help debug this next week.
> > 
> > [  504.149548] ------------[ cut here ]------------
> > [  504.149550] kernel BUG at /home/sean/go/src/kernel.org/linux/mm/mmap.c:669!
> 
> Rodger, dodger.
> 
> Let us know when you think you have something working pushed up into
> one of the branches and we will put it on the bench here in the lab
> and see what our runtime is able to do with it.
> 
> BTW, your new vDSO work appears to be shaping up well.  Just out of
> curiosity though, how are you testing and validating the new vDSO
> based exception handler if it isn't possible to initialize and run an
> enclave with the new driver?

Cherry-pick the patches to a stable version of the driver, the vDSO code
doesn't use any of the SGX APIs.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 14:13                                                 ` Jarkko Sakkinen
@ 2018-12-17 16:34                                                   ` Dr. Greg
  0 siblings, 0 replies; 155+ messages in thread
From: Dr. Greg @ 2018-12-17 16:34 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Sean Christopherson, Andy Lutomirski, Andy Lutomirski, X86 ML,
	Platform Driver, linux-sgx, Dave Hansen, nhorman, npmccallum,
	Ayoun, Serge, shay.katz-zamir, haitao.huang, Andy Shevchenko,
	Thomas Gleixner, Svahn, Kai, mark.shanahan, Suresh Siddha,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin, Darren Hart,
	Andy Shevchenko, LKML, jethro

On Mon, Dec 17, 2018 at 04:13:15PM +0200, Jarkko Sakkinen wrote:

Good morning to everyone.

> On Mon, Dec 17, 2018 at 04:08:11PM +0200, Jarkko Sakkinen wrote:
> > On Mon, Dec 17, 2018 at 03:39:28PM +0200, Jarkko Sakkinen wrote:
> > > On Mon, Dec 17, 2018 at 03:28:59PM +0200, Jarkko Sakkinen wrote:
> > > > On Fri, Dec 14, 2018 at 04:06:27PM -0800, Sean Christopherson wrote:
> > > > > [  504.149548] ------------[ cut here ]------------
> > > > > [  504.149550] kernel BUG at /home/sean/go/src/kernel.org/linux/mm/mmap.c:669!
> > > > > [  504.150288] invalid opcode: 0000 [#1] SMP
> > > > > [  504.150614] CPU: 2 PID: 237 Comm: kworker/u20:2 Not tainted 4.20.0-rc2+ #267
> > > > > [  504.151165] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
> > > > > [  504.151818] Workqueue: sgx-encl-wq sgx_encl_release_worker
> > > > > [  504.152267] RIP: 0010:__vma_adjust+0x64a/0x820
> > > > > [  504.152626] Code: ff 48 89 50 18 e9 6f fc ff ff 4c 8b ab 88 00 00 00 45 31 e4 e9 61 fb ff ff 31 c0 48 83 c4 60 5b 5d 41 5c 41 5d 41 5e 41 5f c3 <0f> 0b 49 89 de 49 83 c6 20 0f 84 06 fe ff ff 49 8d 7e e0 e8 fe ee
> > > > > [  504.154109] RSP: 0000:ffffc900004ebd60 EFLAGS: 00010206
> > > > > [  504.154535] RAX: 00007fd92ef7e000 RBX: ffff888467af16c0 RCX: ffff888467af16e0
> > > > > [  504.155104] RDX: ffff888458fd09e0 RSI: 00007fd954021000 RDI: ffff88846bf9e798
> > > > > [  504.155673] RBP: ffff888467af1480 R08: ffff88845bea2000 R09: 0000000000000000
> > > > > [  504.156242] R10: 0000000080000000 R11: fefefefefefefeff R12: 0000000000000000
> > > > > [  504.156810] R13: ffff88846bf9e790 R14: ffff888467af1b70 R15: ffff888467af1b60
> > > > > [  504.157378] FS:  0000000000000000(0000) GS:ffff88846f700000(0000) knlGS:0000000000000000
> > > > > [  504.158021] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> > > > > [  504.158483] CR2: 00007f2c56e99000 CR3: 0000000005009001 CR4: 0000000000360ee0
> > > > > [  504.159054] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> > > > > [  504.159623] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
> > > > > [  504.160193] Call Trace:
> > > > > [  504.160406]  __split_vma+0x16f/0x180
> > > > > [  504.160706]  ? __switch_to_asm+0x40/0x70
> > > > > [  504.161024]  __do_munmap+0xfb/0x450
> > > > > [  504.161308]  sgx_encl_release_worker+0x44/0x70
> > > > > [  504.161675]  process_one_work+0x200/0x3f0
> > > > > [  504.162004]  worker_thread+0x2d/0x3d0
> > > > > [  504.162301]  ? process_one_work+0x3f0/0x3f0
> > > > > [  504.162645]  kthread+0x113/0x130
> > > > > [  504.162912]  ? kthread_park+0x90/0x90
> > > > > [  504.163209]  ret_from_fork+0x35/0x40
> > > > > [  504.163503] Modules linked in: bridge stp llc
> > > > > [  504.163866] ---[ end trace 83076139fc25e3e0 ]---

> > > > There was a race with release and swapping code that I thought
> > > > I fixed, and this is looks like a race there. Have to recheck
> > > > what I did not consider. Anyway, though to share this if you
> > > > have time to look at it.  That is the part where something is
> > > > now unsync most probably.

> > > I think I found it. I was careless to make sgx_encl_release() to
> > > use sgx_invalidate(), which does not delete pages in the case
> > > when enclave is already marked as dead. This was after I had
> > > fixed the race that I had there in the first place. That is why
> > > I was puzzled why it suddenly reappeared.

> > > Would be nice to use sgx_invalidate() also in release for consistency in
> > > semantics sake so maybe just delete this:
> > > 
> > > 	if (encl->flags & SGX_ENCL_DEAD)
> > > 		return;
> > 
> > Updated master, not at this point next.

> If I checked this right was that mmu_notifier_unregister() cause
> DEAD to set, and thus when sgx_invalidate() is executed, it returns
> without doing anything...

On a pristine jarkko-sgx/next local branch we commented out the 'if
(encl->flags & SGX_ENCL_DEAD) return' clause in the following
file/function:

arch/x86/kernel/cpu/sgx/driver/encl.c:sgx_invalidate()

And tested the kernel.

This fix seems to prevent the memory manager from getting
catastrophically corrupted but the EINIT ioctl still fails.

On the first invocation after a fresh boot the EINIT ioctl returns -1.

On subsequent invocations of the loader it returns EBUSY.  Every 8-10
invocations we get the -1 (EPERM -?) from the EINIT call and then it
returns to issueing EBUSY.

Here is a representative call trace from the loader utility:

---------------------------------------------------------------------------
address: 7ff5cbe00000, create address: 7ff5cbe00000
Non-token initialization requested.
EINIT retn: -1 / No error information
[SGXenclave.c,init_enclave,652]: Error location.
[sgx-load.c,main,180]: Error location.

address: 7f4255200000, create address: 7f4255200000
Non-token initialization requested.
EINIT retn: 16 / Resource busy
[SGXenclave.c,init_enclave,652]: Error location.
[sgx-load.c,main,180]: Error location.
---------------------------------------------------------------------------

It looks like I spoke too soon about the patch completely hardening
the machine.  We just got a segmentation fault on EINIT and the
process is hung in 'D' state with the following WCHAN value:

__flush_work.isra.43

Any further attempts to run the loader causes those processes to hang
as well.

Here is everything we have been able to get out of the machine with respect to a stack trace after the initial fault:

---------------------------------------------------------------------------
Dec 17 10:03:00 nuc2 kernel: general protection fault: 0000 [#1] SMP PTI
Dec 17 10:03:00 nuc2 kernel: CPU: 1 PID: 1249 Comm: kworker/u8:3 Not tainted 4.20.0-rc2-sgx-nuc2+ #13
Dec 17 10:03:00 nuc2 kernel: Hardware name: Intel Corporation NUC7CJYH/NUC7JYB, BIOS JYGLKCPX.86A.0046.2018.1103.1316 11/03/2018
Dec 17 10:03:00 nuc2 kernel: Workqueue: sgx-encl-wq sgx_encl_release_worker
Dec 17 10:03:00 nuc2 kernel: RIP: 0010:__mmu_notifier_invalidate_range_start+0x38/0xc5
Dec 17 10:03:00 nuc2 kernel: Code: 54 49 89 fc 48 c7 c7 d0 6f c3 ad 53 31 db 48 83 ec 18 48 89 75 c8 48 89 55 c0 e8 67 97 f7 ff 89 45 d4 49 8b 84 24 a0 03 00 00 <4c> 8b 30 41 0f b6 c5 89 45 d0 4d 85 f6 74 5e 49 8b 46 10 48 8b 40
Dec 17 10:03:00 nuc2 kernel: RSP: 0018:ffffa51d4238bc98 EFLAGS: 00010246
Dec 17 10:03:00 nuc2 kernel: RAX: dead000000000100 RBX: 0000000000000000 RCX: 0000000000000000
Dec 17 10:03:00 nuc2 kernel: RDX: 000000000001b640 RSI: 00007f51607ee000 RDI: ffffffffadc36fd0
Dec 17 10:03:00 nuc2 kernel: RBP: ffffa51d4238bcd8 R08: 00007f5160a00000 R09: 0000000000000000
Dec 17 10:03:00 nuc2 kernel: R10: ffffa51d4238bce8 R11: fefefefefefefeff R12: ffffa17a3aa68c00
Dec 17 10:03:00 nuc2 kernel: R13: ffffa17a3aa68c01 R14: 00007f51607ee000 R15: ffffa51d4238bd28
Dec 17 10:03:00 nuc2 kernel: FS:  0000000000000000(0000) GS:ffffa17a3be80000(0000) knlGS:0000000000000000
Dec 17 10:03:00 nuc2 kernel: CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
Dec 17 10:03:00 nuc2 kernel: CR2: 000000000878ed68 CR3: 000000017adc4000 CR4: 0000000000340ee0
Dec 17 10:03:00 nuc2 kernel: Call Trace:
Dec 17 10:03:00 nuc2 kernel:  unmap_vmas+0x3a/0x83
Dec 17 10:03:00 nuc2 kernel:  unmap_region+0xab/0xfc
Dec 17 10:03:00 nuc2 kernel:  ? __vma_rb_erase+0x189/0x1c4
Dec 17 10:03:00 nuc2 kernel:  __do_munmap+0x246/0x2d5
Dec 17 10:03:00 nuc2 kernel:  do_munmap+0xc/0xe
Dec 17 10:03:00 nuc2 kernel:  sgx_encl_release_worker+0x44/0x6e
Dec 17 10:03:00 nuc2 kernel:  process_one_work+0x183/0x271
Dec 17 10:03:00 nuc2 kernel:  worker_thread+0x1e5/0x2b4
Dec 17 10:03:00 nuc2 kernel:  ? cancel_delayed_work_sync+0x10/0x10
Dec 17 10:03:00 nuc2 kernel:  kthread+0x116/0x11e
Dec 17 10:03:00 nuc2 kernel:  ? kthread_park+0x7e/0x7e
Dec 17 10:03:00 nuc2 kernel:  ret_from_fork+0x1f/0x40
Dec 17 10:03:00 nuc2 kernel: Modules linked in:
Dec 17 10:03:00 nuc2 kernel: ---[ end trace 07fc74730017fedb ]---
Dec 17 10:03:00 nuc2 kernel: RIP: 0010:__mmu_notifier_invalidate_range_start+0x38/0xc5
Dec 17 10:03:00 nuc2 kernel: Code: 54 49 89 fc 48 c7 c7 d0 6f c3 ad 53 31 db 48 83 ec 18 48 89 75 c8 48 89 55 c0 e8 67 97 f7 ff 89 45 d4 49 8b 84 24 a0 03 00 00 <4c> 8b 30 41 0f b6 c5 89 45 d0 4d 85 f6 74 5e 49 8b 46 10 48 8b 40
Dec 17 10:03:00 nuc2 kernel: RSP: 0018:ffffa51d4238bc98 EFLAGS: 00010246
Dec 17 10:03:00 nuc2 kernel: RAX: dead000000000100 RBX: 0000000000000000 RCX: 0000000000000000
Dec 17 10:03:00 nuc2 kernel: RDX: 000000000001b640 RSI: 00007f51607ee000 RDI: ffffffffadc36fd0
Dec 17 10:03:00 nuc2 kernel: RBP: ffffa51d4238bcd8 R08: 00007f5160a00000 R09: 0000000000000000
Dec 17 10:03:00 nuc2 kernel: R10: ffffa51d4238bce8 R11: fefefefefefefeff R12: ffffa17a3aa68c00
Dec 17 10:03:00 nuc2 kernel: R13: ffffa17a3aa68c01 R14: 00007f51607ee000 R15: ffffa51d4238bd28
Dec 17 10:03:00 nuc2 kernel: FS:  0000000000000000(0000) GS:ffffa17a3be80000(0000) knlGS:0000000000000000
Dec 17 10:03:00 nuc2 kernel: CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
Dec 17 10:03:00 nuc2 kernel: CR2: 000000000878ed68 CR3: 000000017adc4000 CR4: 0000000000340ee0
---------------------------------------------------------------------------

So far the box still appears to be largely intact except for every
invocation of the enclave loader hanging.

> /Jarkko

Let us know how we can help.

Have a good afternoon.

Dr. Greg

As always,
Dr. Greg Wettstein, Ph.D, Worker
IDfusion, LLC
4206 N. 19th Ave.           Implementing measured information privacy
Fargo, ND  58102            and integrity architectures.
PH: 701-281-1686
FAX: 701-281-3949           EMAIL: gw@idfusion.org
------------------------------------------------------------------------------
"... remember that innovation is saying 'no' to 1000 things."
                                -- Moxie Marlinspike

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 14:08                                               ` Jarkko Sakkinen
  2018-12-17 14:13                                                 ` Jarkko Sakkinen
@ 2018-12-17 17:31                                                 ` Sean Christopherson
  2018-12-17 17:49                                                   ` Jarkko Sakkinen
  1 sibling, 1 reply; 155+ messages in thread
From: Sean Christopherson @ 2018-12-17 17:31 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Dr. Greg, Andy Lutomirski, Andy Lutomirski, X86 ML,
	Platform Driver, linux-sgx, Dave Hansen, nhorman, npmccallum,
	Ayoun, Serge, shay.katz-zamir, haitao.huang, Andy Shevchenko,
	Thomas Gleixner, Svahn, Kai, mark.shanahan, Suresh Siddha,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin, Darren Hart,
	Andy Shevchenko, LKML, jethro

[-- Attachment #1: Type: text/plain, Size: 4534 bytes --]

On Mon, Dec 17, 2018 at 04:08:11PM +0200, Jarkko Sakkinen wrote:
> On Mon, Dec 17, 2018 at 03:39:28PM +0200, Jarkko Sakkinen wrote:
> > On Mon, Dec 17, 2018 at 03:28:59PM +0200, Jarkko Sakkinen wrote:
> > > On Fri, Dec 14, 2018 at 04:06:27PM -0800, Sean Christopherson wrote:
> > > > [  504.149548] ------------[ cut here ]------------
> > > > [  504.149550] kernel BUG at /home/sean/go/src/kernel.org/linux/mm/mmap.c:669!
> > > > [  504.150288] invalid opcode: 0000 [#1] SMP
> > > > [  504.150614] CPU: 2 PID: 237 Comm: kworker/u20:2 Not tainted 4.20.0-rc2+ #267
> > > > [  504.151165] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
> > > > [  504.151818] Workqueue: sgx-encl-wq sgx_encl_release_worker
> > > > [  504.152267] RIP: 0010:__vma_adjust+0x64a/0x820
> > > > [  504.152626] Code: ff 48 89 50 18 e9 6f fc ff ff 4c 8b ab 88 00 00 00 45 31 e4 e9 61 fb ff ff 31 c0 48 83 c4 60 5b 5d 41 5c 41 5d 41 5e 41 5f c3 <0f> 0b 49 89 de 49 83 c6 20 0f 84 06 fe ff ff 49 8d 7e e0 e8 fe ee
> > > > [  504.154109] RSP: 0000:ffffc900004ebd60 EFLAGS: 00010206
> > > > [  504.154535] RAX: 00007fd92ef7e000 RBX: ffff888467af16c0 RCX: ffff888467af16e0
> > > > [  504.155104] RDX: ffff888458fd09e0 RSI: 00007fd954021000 RDI: ffff88846bf9e798
> > > > [  504.155673] RBP: ffff888467af1480 R08: ffff88845bea2000 R09: 0000000000000000
> > > > [  504.156242] R10: 0000000080000000 R11: fefefefefefefeff R12: 0000000000000000
> > > > [  504.156810] R13: ffff88846bf9e790 R14: ffff888467af1b70 R15: ffff888467af1b60
> > > > [  504.157378] FS:  0000000000000000(0000) GS:ffff88846f700000(0000) knlGS:0000000000000000
> > > > [  504.158021] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> > > > [  504.158483] CR2: 00007f2c56e99000 CR3: 0000000005009001 CR4: 0000000000360ee0
> > > > [  504.159054] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> > > > [  504.159623] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
> > > > [  504.160193] Call Trace:
> > > > [  504.160406]  __split_vma+0x16f/0x180
> > > > [  504.160706]  ? __switch_to_asm+0x40/0x70
> > > > [  504.161024]  __do_munmap+0xfb/0x450
> > > > [  504.161308]  sgx_encl_release_worker+0x44/0x70
> > > > [  504.161675]  process_one_work+0x200/0x3f0
> > > > [  504.162004]  worker_thread+0x2d/0x3d0
> > > > [  504.162301]  ? process_one_work+0x3f0/0x3f0
> > > > [  504.162645]  kthread+0x113/0x130
> > > > [  504.162912]  ? kthread_park+0x90/0x90
> > > > [  504.163209]  ret_from_fork+0x35/0x40
> > > > [  504.163503] Modules linked in: bridge stp llc
> > > > [  504.163866] ---[ end trace 83076139fc25e3e0 ]---
> > > 
> > > There was a race with release and swapping code that I thought I fixed,
> > > and this is looks like a race there. Have to recheck what I did not
> > > consider. Anyway, though to share this if you have time to look at it.
> > > That is the part where something is now unsync most probably.
> > 
> > I think I found it. I was careless to make sgx_encl_release() to use
> > sgx_invalidate(), which does not delete pages in the case when enclave
> > is already marked as dead. This was after I had fixed the race that I
> > had there in the first place. That is why I was puzzled why it suddenly
> > reappeared.
> > 
> > Would be nice to use sgx_invalidate() also in release for consistency in
> > semantics sake so maybe just delete this:
> > 
> > 	if (encl->flags & SGX_ENCL_DEAD)
> > 		return;

This doesn't work as-is.  sgx_encl_release() needs to use sgx_free_page()
and not __sgx_free_page() so that we get a WARN() if the page can't be
freed.  sgx_invalidate() needs to use __sgx_free_page() as freeing a page
can fail due to running concurrently with reclaim.  I'll play around with
the code a bit, there's probably a fairly clean way to share code between
the two flows.

> 
> Updated master, not at this point next.

Still broken (as Greg's parallel email points out).

sgx_encl_release_worker() calls do_unmap() without checking the validity
of the page tables[1].  As is, the code doesn't even guarantee mm_struct
itself is valid.

The easiest fix I can think of is to add a SGX_ENCL_MM_RELEASED flag
that is set along with SGX_ENCL_DEAD in sgx_mmu_notifier_release(), and
only call do_unmap() if SGX_ENCL_MM_RELEASED is false.  Note that this
means we cant unregister the mmu_notifier until after do_unmap(), but
that's true no matter what since we're relying on the mmu_notifier to
hold a reference to mm_struct.  Patch attached.

[1] https://www.spinics.net/lists/dri-devel/msg186827.html

[-- Attachment #2: 0001-x86-sgx-Do-not-attempt-to-unmap-enclave-VMAs-if-mm_s.patch --]
[-- Type: text/x-diff, Size: 3045 bytes --]

From 7cfdf34ec5b70392216b24853d6b8cc5e3192a92 Mon Sep 17 00:00:00 2001
From: Sean Christopherson <sean.j.christopherson@intel.com>
Date: Mon, 17 Dec 2018 09:21:14 -0800
Subject: [PATCH] x86/sgx: Do not attempt to unmap enclave VMAs if mm_struct is
 defunct

Add a flag, SGX_ENCL_MM_RELEASED, to explicitly track the lifecycle of
the enclave's associated mm_struct.  Simply ensuring the mm_struct
itself is valid is not sufficient as the VMAs and page tables can be
removed after sgx_mmu_notifier_release() is invoked[1].

Note that this means mmu_notifier can't be unregistered until after
do_unmap(), but that's true no matter what since the mmu_notifier
holds the enclave's reference to mm_struct, i.e. this also fixes a
potential use-after-free bug of the mm_struct.

[1] https://www.spinics.net/lists/dri-devel/msg186827.html

Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
---
 arch/x86/kernel/cpu/sgx/driver/driver.h |  1 +
 arch/x86/kernel/cpu/sgx/driver/encl.c   | 18 ++++++++++--------
 2 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/arch/x86/kernel/cpu/sgx/driver/driver.h b/arch/x86/kernel/cpu/sgx/driver/driver.h
index 56f45cd433dd..d7c51284ef36 100644
--- a/arch/x86/kernel/cpu/sgx/driver/driver.h
+++ b/arch/x86/kernel/cpu/sgx/driver/driver.h
@@ -89,6 +89,7 @@ enum sgx_encl_flags {
 	SGX_ENCL_DEBUG		= BIT(1),
 	SGX_ENCL_SUSPEND	= BIT(2),
 	SGX_ENCL_DEAD		= BIT(3),
+	SGX_ENCL_MM_RELEASED	= BIT(4),
 };
 
 struct sgx_encl {
diff --git a/arch/x86/kernel/cpu/sgx/driver/encl.c b/arch/x86/kernel/cpu/sgx/driver/encl.c
index 923e31eb6552..77c5e65533fb 100644
--- a/arch/x86/kernel/cpu/sgx/driver/encl.c
+++ b/arch/x86/kernel/cpu/sgx/driver/encl.c
@@ -311,7 +311,7 @@ static void sgx_mmu_notifier_release(struct mmu_notifier *mn,
 		container_of(mn, struct sgx_encl, mmu_notifier);
 
 	mutex_lock(&encl->lock);
-	encl->flags |= SGX_ENCL_DEAD;
+	encl->flags |= SGX_ENCL_DEAD | SGX_ENCL_MM_RELEASED;
 	mutex_unlock(&encl->lock);
 }
 
@@ -967,10 +967,15 @@ static void sgx_encl_release_worker(struct work_struct *work)
 	struct sgx_encl *encl = container_of(work, struct sgx_encl, work);
 	unsigned long backing_size = encl->size + PAGE_SIZE;
 
-	down_write(&encl->mm->mmap_sem);
-	do_munmap(encl->mm, (unsigned long)encl->backing, backing_size +
-		  (backing_size >> 5), NULL);
-	up_write(&encl->mm->mmap_sem);
+	if (!(encl->flags & SGX_ENCL_MM_RELEASED)) {
+		down_write(&encl->mm->mmap_sem);
+		do_munmap(encl->mm, (unsigned long)encl->backing,
+			  backing_size + (backing_size >> 5), NULL);
+		up_write(&encl->mm->mmap_sem);
+	}
+
+	if (encl->mmu_notifier.ops)
+		mmu_notifier_unregister(&encl->mmu_notifier, encl->mm);
 
 	if (encl->tgid)
 		put_pid(encl->tgid);
@@ -990,9 +995,6 @@ void sgx_encl_release(struct kref *ref)
 {
 	struct sgx_encl *encl = container_of(ref, struct sgx_encl, refcount);
 
-	if (encl->mmu_notifier.ops)
-		mmu_notifier_unregister(&encl->mmu_notifier, encl->mm);
-
 	if (encl->pm_notifier.notifier_call)
 		unregister_pm_notifier(&encl->pm_notifier);
 
-- 
2.19.2


^ permalink raw reply related	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-16  1:01 ` [PATCH v17 18/23] platform/x86: Intel SGX driver Jarkko Sakkinen
                     ` (2 preceding siblings ...)
  2018-11-19 15:29   ` Andy Lutomirski
@ 2018-12-17 17:45   ` Dave Hansen
  2018-12-17 18:01     ` Jarkko Sakkinen
  2018-12-18  5:55   ` Andy Lutomirski
  4 siblings, 1 reply; 155+ messages in thread
From: Dave Hansen @ 2018-12-17 17:45 UTC (permalink / raw)
  To: Jarkko Sakkinen, x86, platform-driver-x86, linux-sgx
  Cc: sean.j.christopherson, nhorman, npmccallum, serge.ayoun,
	shay.katz-zamir, haitao.huang, andriy.shevchenko, tglx,
	kai.svahn, mark.shanahan, luto, Suresh Siddha, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

> +struct sgx_encl *sgx_encl_alloc(struct sgx_secs *secs)
> +{
...
> +	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->add_page_work, sgx_add_page_worker);
> +
> +	encl->mm = current->mm;  <---------------------------------> +	encl->base = secs->base;
> +	encl->size = secs->size;
> +	encl->ssaframesize = secs->ssa_frame_size;
> +	encl->backing = backing;
> +
> +	return encl;
> +}

How is this OK without taking a reference on the mm?

I have a feeling a bunch of your bugs with the mmu notifiers and so
forth are because the refcounting is wrong here.

Sean's SGX_ENCL_MM_RELEASED would, I think be unnecessary if you just
take a refcount here and release it when the enclave is destroyed.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 17:31                                                 ` Sean Christopherson
@ 2018-12-17 17:49                                                   ` Jarkko Sakkinen
  2018-12-17 18:09                                                     ` Sean Christopherson
  0 siblings, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-17 17:49 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Dr. Greg, Andy Lutomirski, Andy Lutomirski, X86 ML,
	Platform Driver, linux-sgx, Dave Hansen, nhorman, npmccallum,
	Ayoun, Serge, shay.katz-zamir, haitao.huang, Andy Shevchenko,
	Thomas Gleixner, Svahn, Kai, mark.shanahan, Suresh Siddha,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin, Darren Hart,
	Andy Shevchenko, LKML, jethro

On Mon, Dec 17, 2018 at 09:31:06AM -0800, Sean Christopherson wrote:
> This doesn't work as-is.  sgx_encl_release() needs to use sgx_free_page()
> and not __sgx_free_page() so that we get a WARN() if the page can't be
> freed.  sgx_invalidate() needs to use __sgx_free_page() as freeing a page
> can fail due to running concurrently with reclaim.  I'll play around with
> the code a bit, there's probably a fairly clean way to share code between
> the two flows.

Hmm... but why issue a warning in that case? It should be legit
behaviour.

> sgx_encl_release_worker() calls do_unmap() without checking the validity
> of the page tables[1].  As is, the code doesn't even guarantee mm_struct
> itself is valid.
> 
> The easiest fix I can think of is to add a SGX_ENCL_MM_RELEASED flag
> that is set along with SGX_ENCL_DEAD in sgx_mmu_notifier_release(), and
> only call do_unmap() if SGX_ENCL_MM_RELEASED is false.  Note that this
> means we cant unregister the mmu_notifier until after do_unmap(), but
> that's true no matter what since we're relying on the mmu_notifier to
> hold a reference to mm_struct.  Patch attached.

OK, the fix change makes sense but I'm thinking that would it be a
better idea just to set mm NULL and check that instead?

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 17:45   ` Dave Hansen
@ 2018-12-17 18:01     ` Jarkko Sakkinen
  2018-12-17 18:07       ` Dave Hansen
  2018-12-17 18:36       ` Sean Christopherson
  0 siblings, 2 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-17 18:01 UTC (permalink / raw)
  To: Dave Hansen
  Cc: x86, platform-driver-x86, linux-sgx, sean.j.christopherson,
	nhorman, npmccallum, serge.ayoun, shay.katz-zamir, haitao.huang,
	andriy.shevchenko, tglx, kai.svahn, mark.shanahan, luto,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Dec 17, 2018 at 09:45:40AM -0800, Dave Hansen wrote:
> > +struct sgx_encl *sgx_encl_alloc(struct sgx_secs *secs)
> > +{
> ...
> > +	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->add_page_work, sgx_add_page_worker);
> > +
> > +	encl->mm = current->mm;  <---------------------------------> +	encl->base = secs->base;
> > +	encl->size = secs->size;
> > +	encl->ssaframesize = secs->ssa_frame_size;
> > +	encl->backing = backing;
> > +
> > +	return encl;
> > +}
> 
> How is this OK without taking a reference on the mm?
> 
> I have a feeling a bunch of your bugs with the mmu notifiers and so
> forth are because the refcounting is wrong here.
> 
> Sean's SGX_ENCL_MM_RELEASED would, I think be unnecessary if you just
> take a refcount here and release it when the enclave is destroyed.

Right, atomic_inc(encl->mm->count) here and once when releasing.

The we would not even need the whole mmu notifier in the first place.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 18:01     ` Jarkko Sakkinen
@ 2018-12-17 18:07       ` Dave Hansen
  2018-12-17 18:31         ` Jarkko Sakkinen
  2018-12-17 18:36       ` Sean Christopherson
  1 sibling, 1 reply; 155+ messages in thread
From: Dave Hansen @ 2018-12-17 18:07 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: x86, platform-driver-x86, linux-sgx, sean.j.christopherson,
	nhorman, npmccallum, serge.ayoun, shay.katz-zamir, haitao.huang,
	andriy.shevchenko, tglx, kai.svahn, mark.shanahan, luto,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On 12/17/18 10:01 AM, Jarkko Sakkinen wrote:
>>> +	encl->mm = current->mm;  <---------------------------------> +	encl->base = secs->base;
>>> +	encl->size = secs->size;
>>> +	encl->ssaframesize = secs->ssa_frame_size;
>>> +	encl->backing = backing;
>>> +
>>> +	return encl;
>>> +}
>> How is this OK without taking a reference on the mm?
>>
>> I have a feeling a bunch of your bugs with the mmu notifiers and so
>> forth are because the refcounting is wrong here.
>>
>> Sean's SGX_ENCL_MM_RELEASED would, I think be unnecessary if you just
>> take a refcount here and release it when the enclave is destroyed.
> Right, atomic_inc(encl->mm->count) here and once when releasing.
> 
> The we would not even need the whole mmu notifier in the first place.

Please use mmget()/mmput().

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 17:49                                                   ` Jarkko Sakkinen
@ 2018-12-17 18:09                                                     ` Sean Christopherson
  2018-12-17 18:23                                                       ` Jarkko Sakkinen
  0 siblings, 1 reply; 155+ messages in thread
From: Sean Christopherson @ 2018-12-17 18:09 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Dr. Greg, Andy Lutomirski, Andy Lutomirski, X86 ML,
	Platform Driver, linux-sgx, Dave Hansen, nhorman, npmccallum,
	Ayoun, Serge, shay.katz-zamir, haitao.huang, Andy Shevchenko,
	Thomas Gleixner, Svahn, Kai, mark.shanahan, Suresh Siddha,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin, Darren Hart,
	Andy Shevchenko, LKML, jethro

On Mon, Dec 17, 2018 at 07:49:35PM +0200, Jarkko Sakkinen wrote:
> On Mon, Dec 17, 2018 at 09:31:06AM -0800, Sean Christopherson wrote:
> > This doesn't work as-is.  sgx_encl_release() needs to use sgx_free_page()
> > and not __sgx_free_page() so that we get a WARN() if the page can't be
> > freed.  sgx_invalidate() needs to use __sgx_free_page() as freeing a page
> > can fail due to running concurrently with reclaim.  I'll play around with
> > the code a bit, there's probably a fairly clean way to share code between
> > the two flows.
> 
> Hmm... but why issue a warning in that case? It should be legit
> behaviour.

No, EREMOVE should never fail if the enclave is being released, i.e. all
references to the enclave are gone.  And failure during sgx_encl_release()
means we leaked an EPC page, which warrants a WARN.

The only legitimate reason __sgx_free_page() can fail in sgx_invalidate()
is because a page might be in the process of being reclaimed.  We could
theoretically WARN on EREMOVE failure in that case, but it'd make the code
a little fragile and it's not "fatal" in the sense that we get a second
chance to free the page during sgx_encl_release().

And unless I missed something, using sgx_invalidate() means were' leaking
all sgx_encl_page structs as well as the radix tree entries.
 
> > sgx_encl_release_worker() calls do_unmap() without checking the validity
> > of the page tables[1].  As is, the code doesn't even guarantee mm_struct
> > itself is valid.
> > 
> > The easiest fix I can think of is to add a SGX_ENCL_MM_RELEASED flag
> > that is set along with SGX_ENCL_DEAD in sgx_mmu_notifier_release(), and
> > only call do_unmap() if SGX_ENCL_MM_RELEASED is false.  Note that this
> > means we cant unregister the mmu_notifier until after do_unmap(), but
> > that's true no matter what since we're relying on the mmu_notifier to
> > hold a reference to mm_struct.  Patch attached.
> 
> OK, the fix change makes sense but I'm thinking that would it be a
> better idea just to set mm NULL and check that instead?

That makes sense.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 18:09                                                     ` Sean Christopherson
@ 2018-12-17 18:23                                                       ` Jarkko Sakkinen
  2018-12-17 18:46                                                         ` Sean Christopherson
  0 siblings, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-17 18:23 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Dr. Greg, Andy Lutomirski, Andy Lutomirski, X86 ML,
	Platform Driver, linux-sgx, Dave Hansen, nhorman, npmccallum,
	Ayoun, Serge, shay.katz-zamir, haitao.huang, Andy Shevchenko,
	Thomas Gleixner, Svahn, Kai, mark.shanahan, Suresh Siddha,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin, Darren Hart,
	Andy Shevchenko, LKML, jethro

On Mon, Dec 17, 2018 at 10:09:57AM -0800, Sean Christopherson wrote:
> No, EREMOVE should never fail if the enclave is being released, i.e. all
> references to the enclave are gone.  And failure during sgx_encl_release()
> means we leaked an EPC page, which warrants a WARN.

Right that what I was suspecting as swapper should hold a ref to the
enclave while it is working on it. It is a programming error when this
happens.

Maybe change the boolean parameter to flags parameter have a flag to
use sgx_free_page()?

> That makes sense.

What do you think of Dave's proposal?

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 18:07       ` Dave Hansen
@ 2018-12-17 18:31         ` Jarkko Sakkinen
  0 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-17 18:31 UTC (permalink / raw)
  To: Dave Hansen
  Cc: x86, platform-driver-x86, linux-sgx, sean.j.christopherson,
	nhorman, npmccallum, serge.ayoun, shay.katz-zamir, haitao.huang,
	andriy.shevchenko, tglx, kai.svahn, mark.shanahan, luto,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Dec 17, 2018 at 10:07:08AM -0800, Dave Hansen wrote:
> On 12/17/18 10:01 AM, Jarkko Sakkinen wrote:
> >>> +	encl->mm = current->mm;  <---------------------------------> +	encl->base = secs->base;
> >>> +	encl->size = secs->size;
> >>> +	encl->ssaframesize = secs->ssa_frame_size;
> >>> +	encl->backing = backing;
> >>> +
> >>> +	return encl;
> >>> +}
> >> How is this OK without taking a reference on the mm?
> >>
> >> I have a feeling a bunch of your bugs with the mmu notifiers and so
> >> forth are because the refcounting is wrong here.
> >>
> >> Sean's SGX_ENCL_MM_RELEASED would, I think be unnecessary if you just
> >> take a refcount here and release it when the enclave is destroyed.
> > Right, atomic_inc(encl->mm->count) here and once when releasing.
> > 
> > The we would not even need the whole mmu notifier in the first place.
> 
> Please use mmget()/mmput().

There's now a patch to test on top of the master.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 18:01     ` Jarkko Sakkinen
  2018-12-17 18:07       ` Dave Hansen
@ 2018-12-17 18:36       ` Sean Christopherson
  2018-12-17 18:43         ` Jarkko Sakkinen
  1 sibling, 1 reply; 155+ messages in thread
From: Sean Christopherson @ 2018-12-17 18:36 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Dave Hansen, x86, platform-driver-x86, linux-sgx, nhorman,
	npmccallum, serge.ayoun, shay.katz-zamir, haitao.huang,
	andriy.shevchenko, tglx, kai.svahn, mark.shanahan, luto,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Dec 17, 2018 at 08:01:02PM +0200, Jarkko Sakkinen wrote:
> On Mon, Dec 17, 2018 at 09:45:40AM -0800, Dave Hansen wrote:
> > > +struct sgx_encl *sgx_encl_alloc(struct sgx_secs *secs)
> > > +{
> > ...
> > > +	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->add_page_work, sgx_add_page_worker);
> > > +
> > > +	encl->mm = current->mm;  <---------------------------------> +	encl->base = secs->base;
> > > +	encl->size = secs->size;
> > > +	encl->ssaframesize = secs->ssa_frame_size;
> > > +	encl->backing = backing;
> > > +
> > > +	return encl;
> > > +}
> > 
> > How is this OK without taking a reference on the mm?

It's subtle and the ordering is all kinds of weird, but technically we
are taking a reference on mm when the mmu_notifier is registered in
sgx_encl_create().  sgx_encl_alloc() and sgx_encl_create() are always
called in tandem and with mm->mm_users > 0, so we'll never use encl->mm
without holding a reference to mm.  We need to comment the weirdness
or maybe register the notifier before

> > I have a feeling a bunch of your bugs with the mmu notifiers and so
> > forth are because the refcounting is wrong here.

Eh, not really.  Maybe the mmu_notifier is more subtle, e.g. calling
do_unmap() after mmput() would be quite obvious, but there's no
fundamental bug, we just haven't needed to touch VMAs during release
prior to moving away from shmem.

> > Sean's SGX_ENCL_MM_RELEASED would, I think be unnecessary if you just
> > take a refcount here and release it when the enclave is destroyed.
> 
> Right, atomic_inc(encl->mm->count) here and once when releasing.
> 
> The we would not even need the whole mmu notifier in the first place.

I'm pretty sure doing mmget() would result in circular dependencies and
a zombie enclave.  In the do_exit() case where a task is abruptly killed:
 
  - __mmput() is never called because the enclave holds a ref
  - sgx_encl_release() is never be called because its VMAs hold refs
  - sgx_vma_close() is never called because __mmput()->exit_mmap() is
    blocked and the process itself is dead, i.e. won't unmap anything.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 18:36       ` Sean Christopherson
@ 2018-12-17 18:43         ` Jarkko Sakkinen
  2018-12-17 18:47           ` Dave Hansen
  2018-12-17 18:48           ` Sean Christopherson
  0 siblings, 2 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-17 18:43 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Dave Hansen, x86, platform-driver-x86, linux-sgx, nhorman,
	npmccallum, serge.ayoun, shay.katz-zamir, haitao.huang,
	andriy.shevchenko, tglx, kai.svahn, mark.shanahan, luto,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Dec 17, 2018 at 10:36:13AM -0800, Sean Christopherson wrote:
> I'm pretty sure doing mmget() would result in circular dependencies and
> a zombie enclave.  In the do_exit() case where a task is abruptly killed:
>  
>   - __mmput() is never called because the enclave holds a ref
>   - sgx_encl_release() is never be called because its VMAs hold refs
>   - sgx_vma_close() is never called because __mmput()->exit_mmap() is
>     blocked and the process itself is dead, i.e. won't unmap anything.

Right, it does, you are absolutely right. Tried it and removed the
commit already.

Well, what we came up from your suggestion i.e. setting mm to NULL
and checking that is very subtle change and does not have any such
circular dependencies. We'll go with that.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 18:23                                                       ` Jarkko Sakkinen
@ 2018-12-17 18:46                                                         ` Sean Christopherson
  2018-12-17 19:36                                                           ` Jarkko Sakkinen
  0 siblings, 1 reply; 155+ messages in thread
From: Sean Christopherson @ 2018-12-17 18:46 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Dr. Greg, Andy Lutomirski, Andy Lutomirski, X86 ML,
	Platform Driver, linux-sgx, Dave Hansen, nhorman, npmccallum,
	Ayoun, Serge, shay.katz-zamir, haitao.huang, Andy Shevchenko,
	Thomas Gleixner, Svahn, Kai, mark.shanahan, Suresh Siddha,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin, Darren Hart,
	Andy Shevchenko, LKML, jethro

On Mon, Dec 17, 2018 at 08:23:19PM +0200, Jarkko Sakkinen wrote:
> On Mon, Dec 17, 2018 at 10:09:57AM -0800, Sean Christopherson wrote:
> > No, EREMOVE should never fail if the enclave is being released, i.e. all
> > references to the enclave are gone.  And failure during sgx_encl_release()
> > means we leaked an EPC page, which warrants a WARN.
> 
> Right that what I was suspecting as swapper should hold a ref to the
> enclave while it is working on it. It is a programming error when this
> happens.
> 
> Maybe change the boolean parameter to flags parameter have a flag to
> use sgx_free_page()?

I tried that approach when I first split it to __sgx_free_page() and
sgx_free_page(), but IMO the code is more difficult to read and harder
to maintain since sgx_free_page() should be used except under special
circumstances, e.g. race with reclaim or the freeing is "untrusted",
i.e. requested by userspace via sgx_ioc_enclave_remove_pages().

> 
> > That makes sense.
> 
> What do you think of Dave's proposal?
> 
> /Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 18:43         ` Jarkko Sakkinen
@ 2018-12-17 18:47           ` Dave Hansen
  2018-12-17 19:12             ` Andy Lutomirski
  2018-12-17 18:48           ` Sean Christopherson
  1 sibling, 1 reply; 155+ messages in thread
From: Dave Hansen @ 2018-12-17 18:47 UTC (permalink / raw)
  To: Jarkko Sakkinen, Sean Christopherson
  Cc: x86, platform-driver-x86, linux-sgx, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Suresh Siddha, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On 12/17/18 10:43 AM, Jarkko Sakkinen wrote:
> On Mon, Dec 17, 2018 at 10:36:13AM -0800, Sean Christopherson wrote:
>> I'm pretty sure doing mmget() would result in circular dependencies and
>> a zombie enclave.  In the do_exit() case where a task is abruptly killed:
>>  
>>   - __mmput() is never called because the enclave holds a ref
>>   - sgx_encl_release() is never be called because its VMAs hold refs
>>   - sgx_vma_close() is never called because __mmput()->exit_mmap() is
>>     blocked and the process itself is dead, i.e. won't unmap anything.
> Right, it does, you are absolutely right. Tried it and removed the
> commit already.
> 
> Well, what we came up from your suggestion i.e. setting mm to NULL
> and checking that is very subtle change and does not have any such
> circular dependencies. We'll go with that.

This all screams that you need to break out this code from the massive
"18" patch and get the mm interactions reviewed more thoroughly.

Also, no matter what method you go with, you have a bunch of commenting
and changelogging to do here.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 18:43         ` Jarkko Sakkinen
  2018-12-17 18:47           ` Dave Hansen
@ 2018-12-17 18:48           ` Sean Christopherson
  2018-12-17 19:09             ` Dave Hansen
  2018-12-17 19:33             ` Jarkko Sakkinen
  1 sibling, 2 replies; 155+ messages in thread
From: Sean Christopherson @ 2018-12-17 18:48 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Dave Hansen, x86, platform-driver-x86, linux-sgx, nhorman,
	npmccallum, serge.ayoun, shay.katz-zamir, haitao.huang,
	andriy.shevchenko, tglx, kai.svahn, mark.shanahan, luto,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Dec 17, 2018 at 08:43:33PM +0200, Jarkko Sakkinen wrote:
> On Mon, Dec 17, 2018 at 10:36:13AM -0800, Sean Christopherson wrote:
> > I'm pretty sure doing mmget() would result in circular dependencies and
> > a zombie enclave.  In the do_exit() case where a task is abruptly killed:
> >  
> >   - __mmput() is never called because the enclave holds a ref
> >   - sgx_encl_release() is never be called because its VMAs hold refs
> >   - sgx_vma_close() is never called because __mmput()->exit_mmap() is
> >     blocked and the process itself is dead, i.e. won't unmap anything.
> 
> Right, it does, you are absolutely right. Tried it and removed the
> commit already.
> 
> Well, what we came up from your suggestion i.e. setting mm to NULL
> and checking that is very subtle change and does not have any such
> circular dependencies. We'll go with that.

We can't set mm to NULL as we need it to unregister the notifier, and
I'm fairly certain attempting to unregister in the release callback
will deadlock.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 18:48           ` Sean Christopherson
@ 2018-12-17 19:09             ` Dave Hansen
  2018-12-17 19:37               ` Jarkko Sakkinen
  2018-12-17 19:33             ` Jarkko Sakkinen
  1 sibling, 1 reply; 155+ messages in thread
From: Dave Hansen @ 2018-12-17 19:09 UTC (permalink / raw)
  To: Sean Christopherson, Jarkko Sakkinen
  Cc: x86, platform-driver-x86, linux-sgx, nhorman, npmccallum,
	serge.ayoun, shay.katz-zamir, haitao.huang, andriy.shevchenko,
	tglx, kai.svahn, mark.shanahan, luto, Suresh Siddha, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On 12/17/18 10:48 AM, Sean Christopherson wrote:
> We can't set mm to NULL as we need it to unregister the notifier, and
> I'm fairly certain attempting to unregister in the release callback
> will deadlock.

Suggestion:

It looks like you only expect one VMA per enclave.  Things go bonkers if
this is not true.  So, instead of storing encl->mm, don't.  You can get
the mm from vma->vm_mm and you could just store encl->vma instead.

Doing that, you could even axe encl->base and encl->size, I think
because you just get those from the VMA itself.

That makes the relationship clearer: 1 VMA per enclave.  We also
implicitly understand that if you have a VMA, you implicitly have a ref
to the mm *and* the VMA is immutable.

If there were ever a path where encl->vma wasn't immutable, we'd have a
bug (or load of bugs) somewhere, right?

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 18:47           ` Dave Hansen
@ 2018-12-17 19:12             ` Andy Lutomirski
  2018-12-17 19:17               ` Dave Hansen
                                 ` (2 more replies)
  0 siblings, 3 replies; 155+ messages in thread
From: Andy Lutomirski @ 2018-12-17 19:12 UTC (permalink / raw)
  To: Dave Hansen
  Cc: Jarkko Sakkinen, Sean Christopherson, X86 ML, Platform Driver,
	linux-sgx, nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir,
	Haitao Huang, Andy Shevchenko, Thomas Gleixner, Svahn, Kai,
	mark.shanahan, Suresh Siddha, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Dec 17, 2018 at 10:47 AM Dave Hansen <dave.hansen@intel.com> wrote:
>
> On 12/17/18 10:43 AM, Jarkko Sakkinen wrote:
> > On Mon, Dec 17, 2018 at 10:36:13AM -0800, Sean Christopherson wrote:
> >> I'm pretty sure doing mmget() would result in circular dependencies and
> >> a zombie enclave.  In the do_exit() case where a task is abruptly killed:
> >>
> >>   - __mmput() is never called because the enclave holds a ref
> >>   - sgx_encl_release() is never be called because its VMAs hold refs
> >>   - sgx_vma_close() is never called because __mmput()->exit_mmap() is
> >>     blocked and the process itself is dead, i.e. won't unmap anything.
> > Right, it does, you are absolutely right. Tried it and removed the
> > commit already.
> >
> > Well, what we came up from your suggestion i.e. setting mm to NULL
> > and checking that is very subtle change and does not have any such
> > circular dependencies. We'll go with that.
>
> This all screams that you need to break out this code from the massive
> "18" patch and get the mm interactions reviewed more thoroughly.
>
> Also, no matter what method you go with, you have a bunch of commenting
> and changelogging to do here.

I'm going to ask an obnoxious high-level question: why does an enclave
even refer to a specific mm?

If I were designing this thing, and if I hadn't started trying to
implement it, my first thought would be that an enclave tracks its
linear address range, which is just a pair of numbers, and also keeps
track of a whole bunch of physical EPC pages, data structures, etc.
And that mmap() gets rejected unless the requested virtual address
matches the linear address range that the enclave wants and, aside
from that, just creates a VMA that keeps a reference to the enclave.
(And, for convenience, I suppose that the first mmap() call done
before any actual enclave setup happens could choose any address and
then cause the enclave to lock itself to that address, although a
regular anonymous PROT_NONE MAP_NORESERVE mapping would do just fine,
too.)  And the driver would explicitly allow multiple different mms to
have the same enclave mapped.  More importantly, a daemon could set up
an enclave without necessarily mapping it at all and then SCM_RIGHTS
the enclave over to the process that plans to run it.

Now I'm sure this has all kinds of problems, such as the ISA possibly
making it rather obnoxious to add pages to the enclave without having
it mapped.  But these operations could, in principle, be done by
having the enclave own a private mm that's used just for setup.  While
this would be vaguely annoying, Nadav's still-pending-but-nearly-done
text_poke series adds all the infrastructure that's needed for the
kernel to manage little private mms.  But some things get simpler --
invalidating the enclave can presumably use the regular rmap APIs to
zap all the PTEs in all VMAs pointing into the enclave.

So I'm not saying that you shouldn't do it the way you are now, but I
do think that the changelog or at least some emails should explain
*why* the enclave needs to keep a pointer to the creating process's
mm.  And, if you do keep the current model, it would be nice to
understand what happens if you do something awful like mremap()ing an
enclave, or calling madvise on it, or otherwise abusing the vma.  Or
doing fork(), for that matter.

I also find it suspicious that the various ioctl handlers
systematically ignore their "filep" parameters and instead use
find_vma() to find the relevant mm data structures.  That seems
backwards.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 19:12             ` Andy Lutomirski
@ 2018-12-17 19:17               ` Dave Hansen
  2018-12-17 19:25                 ` Andy Lutomirski
  2018-12-17 19:49                 ` Jarkko Sakkinen
  2018-12-17 22:20               ` Sean Christopherson
  2018-12-18  1:17               ` Jarkko Sakkinen
  2 siblings, 2 replies; 155+ messages in thread
From: Dave Hansen @ 2018-12-17 19:17 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Jarkko Sakkinen, Sean Christopherson, X86 ML, Platform Driver,
	linux-sgx, nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir,
	Haitao Huang, Andy Shevchenko, Thomas Gleixner, Svahn, Kai,
	mark.shanahan, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On 12/17/18 11:12 AM, Andy Lutomirski wrote:
> So I'm not saying that you shouldn't do it the way you are now, but I
> do think that the changelog or at least some emails should explain
> *why* the enclave needs to keep a pointer to the creating process's
> mm.  And, if you do keep the current model, it would be nice to
> understand what happens if you do something awful like mremap()ing an
> enclave, or calling madvise on it, or otherwise abusing the vma.  Or
> doing fork(), for that matter.

Yeah, the code is built to have one VMA and only one VMA per enclave.
You need to go over the origin of this restriction and what enforces this.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 19:17               ` Dave Hansen
@ 2018-12-17 19:25                 ` Andy Lutomirski
  2018-12-17 19:54                   ` Jarkko Sakkinen
  2018-12-17 19:49                 ` Jarkko Sakkinen
  1 sibling, 1 reply; 155+ messages in thread
From: Andy Lutomirski @ 2018-12-17 19:25 UTC (permalink / raw)
  To: Dave Hansen
  Cc: Andy Lutomirski, Jarkko Sakkinen, Sean Christopherson, X86 ML,
	Platform Driver, linux-sgx, nhorman, npmccallum, Ayoun, Serge,
	shay.katz-zamir, Haitao Huang, Andy Shevchenko, Thomas Gleixner,
	Svahn, Kai, mark.shanahan, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Dec 17, 2018 at 11:17 AM Dave Hansen <dave.hansen@intel.com> wrote:
>
> On 12/17/18 11:12 AM, Andy Lutomirski wrote:
> > So I'm not saying that you shouldn't do it the way you are now, but I
> > do think that the changelog or at least some emails should explain
> > *why* the enclave needs to keep a pointer to the creating process's
> > mm.  And, if you do keep the current model, it would be nice to
> > understand what happens if you do something awful like mremap()ing an
> > enclave, or calling madvise on it, or otherwise abusing the vma.  Or
> > doing fork(), for that matter.
>
> Yeah, the code is built to have one VMA and only one VMA per enclave.
> You need to go over the origin of this restriction and what enforces this.

There is a sad historical reason that you may regret keeping this
restriction.  There are plenty of pieces of code out there that think
it's reasonable to spawn a subprocess by calling fork() and then
execve().  (This is *not* a sensible thing to do.  One should use
posix_spawn() or some CLONE_VM variant.  But even fairly recent
posix_spawn() implementations will fork().  So the driver has to do
*something* sensible on fork() or a bunch of things that use SGX
unsuspectingly via, for example, PKCS #11, are going to be very sad.
I suppose you could make enclaves just not show up in the fork()ed
children, but then you have a different problem: creating an enclave
and then doing daemon() won't work.

Yes, POSIX traditions are rather silly.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 18:48           ` Sean Christopherson
  2018-12-17 19:09             ` Dave Hansen
@ 2018-12-17 19:33             ` Jarkko Sakkinen
  2018-12-17 20:21               ` Jarkko Sakkinen
  1 sibling, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-17 19:33 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Dave Hansen, x86, platform-driver-x86, linux-sgx, nhorman,
	npmccallum, serge.ayoun, shay.katz-zamir, haitao.huang,
	andriy.shevchenko, tglx, kai.svahn, mark.shanahan, luto,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Dec 17, 2018 at 10:48:58AM -0800, Sean Christopherson wrote:
> On Mon, Dec 17, 2018 at 08:43:33PM +0200, Jarkko Sakkinen wrote:
> > On Mon, Dec 17, 2018 at 10:36:13AM -0800, Sean Christopherson wrote:
> > > I'm pretty sure doing mmget() would result in circular dependencies and
> > > a zombie enclave.  In the do_exit() case where a task is abruptly killed:
> > >  
> > >   - __mmput() is never called because the enclave holds a ref
> > >   - sgx_encl_release() is never be called because its VMAs hold refs
> > >   - sgx_vma_close() is never called because __mmput()->exit_mmap() is
> > >     blocked and the process itself is dead, i.e. won't unmap anything.
> > 
> > Right, it does, you are absolutely right. Tried it and removed the
> > commit already.
> > 
> > Well, what we came up from your suggestion i.e. setting mm to NULL
> > and checking that is very subtle change and does not have any such
> > circular dependencies. We'll go with that.
> 
> We can't set mm to NULL as we need it to unregister the notifier, and
> I'm fairly certain attempting to unregister in the release callback
> will deadlock.

Noticed that too. mmu_notifier_unregister() requires a valid mm.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 18:46                                                         ` Sean Christopherson
@ 2018-12-17 19:36                                                           ` Jarkko Sakkinen
  0 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-17 19:36 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Dr. Greg, Andy Lutomirski, Andy Lutomirski, X86 ML,
	Platform Driver, linux-sgx, Dave Hansen, nhorman, npmccallum,
	Ayoun, Serge, shay.katz-zamir, haitao.huang, Andy Shevchenko,
	Thomas Gleixner, Svahn, Kai, mark.shanahan, Suresh Siddha,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin, Darren Hart,
	Andy Shevchenko, LKML, jethro

On Mon, Dec 17, 2018 at 10:46:25AM -0800, Sean Christopherson wrote:
> On Mon, Dec 17, 2018 at 08:23:19PM +0200, Jarkko Sakkinen wrote:
> > On Mon, Dec 17, 2018 at 10:09:57AM -0800, Sean Christopherson wrote:
> > > No, EREMOVE should never fail if the enclave is being released, i.e. all
> > > references to the enclave are gone.  And failure during sgx_encl_release()
> > > means we leaked an EPC page, which warrants a WARN.
> > 
> > Right that what I was suspecting as swapper should hold a ref to the
> > enclave while it is working on it. It is a programming error when this
> > happens.
> > 
> > Maybe change the boolean parameter to flags parameter have a flag to
> > use sgx_free_page()?
> 
> I tried that approach when I first split it to __sgx_free_page() and
> sgx_free_page(), but IMO the code is more difficult to read and harder
> to maintain since sgx_free_page() should be used except under special
> circumstances, e.g. race with reclaim or the freeing is "untrusted",
> i.e. requested by userspace via sgx_ioc_enclave_remove_pages().

I mean inside sgx_invalidate() call either __sgx_free_page() or
sgx_free_page() depending on a flag.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 19:09             ` Dave Hansen
@ 2018-12-17 19:37               ` Jarkko Sakkinen
  2018-12-17 19:40                 ` Dave Hansen
  0 siblings, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-17 19:37 UTC (permalink / raw)
  To: Dave Hansen
  Cc: Sean Christopherson, x86, platform-driver-x86, linux-sgx,
	nhorman, npmccallum, serge.ayoun, shay.katz-zamir, haitao.huang,
	andriy.shevchenko, tglx, kai.svahn, mark.shanahan, luto,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Dec 17, 2018 at 11:09:33AM -0800, Dave Hansen wrote:
> On 12/17/18 10:48 AM, Sean Christopherson wrote:
> > We can't set mm to NULL as we need it to unregister the notifier, and
> > I'm fairly certain attempting to unregister in the release callback
> > will deadlock.
> 
> Suggestion:
> 
> It looks like you only expect one VMA per enclave.  Things go bonkers if
> this is not true.  So, instead of storing encl->mm, don't.  You can get
> the mm from vma->vm_mm and you could just store encl->vma instead.

The code actually supports having multiple VMAs per enclave.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 19:37               ` Jarkko Sakkinen
@ 2018-12-17 19:40                 ` Dave Hansen
  0 siblings, 0 replies; 155+ messages in thread
From: Dave Hansen @ 2018-12-17 19:40 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Sean Christopherson, x86, platform-driver-x86, linux-sgx,
	nhorman, npmccallum, serge.ayoun, shay.katz-zamir, haitao.huang,
	andriy.shevchenko, tglx, kai.svahn, mark.shanahan, luto,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On 12/17/18 11:37 AM, Jarkko Sakkinen wrote:
>> Suggestion:
>>
>> It looks like you only expect one VMA per enclave.  Things go bonkers if
>> this is not true.  So, instead of storing encl->mm, don't.  You can get
>> the mm from vma->vm_mm and you could just store encl->vma instead.
> The code actually supports having multiple VMAs per enclave.

That seems at least somewhat at odds with this comment:

> static void sgx_vma_open(struct vm_area_struct *vma)
> {
>         struct sgx_encl *encl = vma->vm_private_data;
> 
>         if (!encl)
>                 return;
> 
>         /* kref cannot underflow because ECREATE ioctl checks that there is only
>          * one single VMA for the enclave before proceeding.
>          */
>         kref_get(&encl->refcount);
> }

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 19:17               ` Dave Hansen
  2018-12-17 19:25                 ` Andy Lutomirski
@ 2018-12-17 19:49                 ` Jarkko Sakkinen
  2018-12-17 19:53                   ` Dave Hansen
  1 sibling, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-17 19:49 UTC (permalink / raw)
  To: Dave Hansen
  Cc: Andy Lutomirski, Sean Christopherson, X86 ML, Platform Driver,
	linux-sgx, nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir,
	Haitao Huang, Andy Shevchenko, Thomas Gleixner, Svahn, Kai,
	mark.shanahan, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Dec 17, 2018 at 11:17:49AM -0800, Dave Hansen wrote:
> On 12/17/18 11:12 AM, Andy Lutomirski wrote:
> > So I'm not saying that you shouldn't do it the way you are now, but I
> > do think that the changelog or at least some emails should explain
> > *why* the enclave needs to keep a pointer to the creating process's
> > mm.  And, if you do keep the current model, it would be nice to
> > understand what happens if you do something awful like mremap()ing an
> > enclave, or calling madvise on it, or otherwise abusing the vma.  Or
> > doing fork(), for that matter.
> 
> Yeah, the code is built to have one VMA and only one VMA per enclave.
> You need to go over the origin of this restriction and what enforces this.

It is before ECREATE but after that you can split it with mprotect().

Lets take an example. I'm not sure how we would acquire mm efficiently
in sgx_encl_page_reclaim() otherwise than having it as a field in encl.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 19:49                 ` Jarkko Sakkinen
@ 2018-12-17 19:53                   ` Dave Hansen
  2018-12-17 19:55                     ` Andy Lutomirski
  0 siblings, 1 reply; 155+ messages in thread
From: Dave Hansen @ 2018-12-17 19:53 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Andy Lutomirski, Sean Christopherson, X86 ML, Platform Driver,
	linux-sgx, nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir,
	Haitao Huang, Andy Shevchenko, Thomas Gleixner, Svahn, Kai,
	mark.shanahan, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On 12/17/18 11:49 AM, Jarkko Sakkinen wrote:
>> Yeah, the code is built to have one VMA and only one VMA per enclave.
>> You need to go over the origin of this restriction and what enforces this.
> It is before ECREATE but after that you can split it with mprotect().
> 
> Lets take an example. I'm not sure how we would acquire mm efficiently
> in sgx_encl_page_reclaim() otherwise than having it as a field in encl.

You're effectively rebuilding reverse-mapping infrastructure here.  It's
a frequent thing for the core VM to need to go from 'struct page' back
to the page tables mapping it.  For that we go (logically)
page->{anon_vma,mapping}->vma->vm_mm->pagetable.

This, on the other hand, is trying to do page->encl->mm->pagetable.  You
could very easily have a VMA analog in there instead of jumping straight
to the mm.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 19:25                 ` Andy Lutomirski
@ 2018-12-17 19:54                   ` Jarkko Sakkinen
  0 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-17 19:54 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Dave Hansen, Sean Christopherson, X86 ML, Platform Driver,
	linux-sgx, nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir,
	Haitao Huang, Andy Shevchenko, Thomas Gleixner, Svahn, Kai,
	mark.shanahan, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Dec 17, 2018 at 11:25:47AM -0800, Andy Lutomirski wrote:
> On Mon, Dec 17, 2018 at 11:17 AM Dave Hansen <dave.hansen@intel.com> wrote:
> >
> > On 12/17/18 11:12 AM, Andy Lutomirski wrote:
> > > So I'm not saying that you shouldn't do it the way you are now, but I
> > > do think that the changelog or at least some emails should explain
> > > *why* the enclave needs to keep a pointer to the creating process's
> > > mm.  And, if you do keep the current model, it would be nice to
> > > understand what happens if you do something awful like mremap()ing an
> > > enclave, or calling madvise on it, or otherwise abusing the vma.  Or
> > > doing fork(), for that matter.
> >
> > Yeah, the code is built to have one VMA and only one VMA per enclave.
> > You need to go over the origin of this restriction and what enforces this.
> 
> There is a sad historical reason that you may regret keeping this
> restriction.  There are plenty of pieces of code out there that think
> it's reasonable to spawn a subprocess by calling fork() and then
> execve().  (This is *not* a sensible thing to do.  One should use
> posix_spawn() or some CLONE_VM variant.  But even fairly recent
> posix_spawn() implementations will fork().  So the driver has to do
> *something* sensible on fork() or a bunch of things that use SGX
> unsuspectingly via, for example, PKCS #11, are going to be very sad.
> I suppose you could make enclaves just not show up in the fork()ed
> children, but then you have a different problem: creating an enclave
> and then doing daemon() won't work.
> 
> Yes, POSIX traditions are rather silly.

ATM enclave VMAs are not copied on fork. Not sure how you would
implement COW semantics with enclaves.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 19:53                   ` Dave Hansen
@ 2018-12-17 19:55                     ` Andy Lutomirski
  2018-12-17 20:03                       ` Dave Hansen
  0 siblings, 1 reply; 155+ messages in thread
From: Andy Lutomirski @ 2018-12-17 19:55 UTC (permalink / raw)
  To: Dave Hansen
  Cc: Jarkko Sakkinen, Andy Lutomirski, Sean Christopherson, X86 ML,
	Platform Driver, linux-sgx, nhorman, npmccallum, Ayoun, Serge,
	shay.katz-zamir, Haitao Huang, Andy Shevchenko, Thomas Gleixner,
	Svahn, Kai, mark.shanahan, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Dec 17, 2018 at 11:53 AM Dave Hansen <dave.hansen@intel.com> wrote:
>
> On 12/17/18 11:49 AM, Jarkko Sakkinen wrote:
> >> Yeah, the code is built to have one VMA and only one VMA per enclave.
> >> You need to go over the origin of this restriction and what enforces this.
> > It is before ECREATE but after that you can split it with mprotect().
> >
> > Lets take an example. I'm not sure how we would acquire mm efficiently
> > in sgx_encl_page_reclaim() otherwise than having it as a field in encl.
>
> You're effectively rebuilding reverse-mapping infrastructure here.  It's
> a frequent thing for the core VM to need to go from 'struct page' back
> to the page tables mapping it.  For that we go (logically)
> page->{anon_vma,mapping}->vma->vm_mm->pagetable.

This is a bit outside my expertise here, but doesn't
unmap_mapping_range() do exactly what SGX wants?

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 19:55                     ` Andy Lutomirski
@ 2018-12-17 20:03                       ` Dave Hansen
  2018-12-17 20:10                         ` Andy Lutomirski
  0 siblings, 1 reply; 155+ messages in thread
From: Dave Hansen @ 2018-12-17 20:03 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Jarkko Sakkinen, Sean Christopherson, X86 ML, Platform Driver,
	linux-sgx, nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir,
	Haitao Huang, Andy Shevchenko, Thomas Gleixner, Svahn, Kai,
	mark.shanahan, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On 12/17/18 11:55 AM, Andy Lutomirski wrote:
>> You're effectively rebuilding reverse-mapping infrastructure here.  It's
>> a frequent thing for the core VM to need to go from 'struct page' back
>> to the page tables mapping it.  For that we go (logically)
>> page->{anon_vma,mapping}->vma->vm_mm->pagetable.
> This is a bit outside my expertise here, but doesn't
> unmap_mapping_range() do exactly what SGX wants?

There's no 'struct page' for enclave memory as it stands.  That means no
page cache, and that means there's no 'struct address_space *mapping' in
the first place.

Basically, the choice was made a long time ago to have SGX's memory
management live outside the core VM.  I've waffled back and forth on it,
but I do still think this is the right way to do it.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 20:03                       ` Dave Hansen
@ 2018-12-17 20:10                         ` Andy Lutomirski
  2018-12-17 20:15                           ` Dave Hansen
  2018-12-18  1:40                           ` Jarkko Sakkinen
  0 siblings, 2 replies; 155+ messages in thread
From: Andy Lutomirski @ 2018-12-17 20:10 UTC (permalink / raw)
  To: Dave Hansen
  Cc: Andy Lutomirski, Jarkko Sakkinen, Sean Christopherson, X86 ML,
	Platform Driver, linux-sgx, nhorman, npmccallum, Ayoun, Serge,
	shay.katz-zamir, Haitao Huang, Andy Shevchenko, Thomas Gleixner,
	Svahn, Kai, mark.shanahan, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Dec 17, 2018 at 12:03 PM Dave Hansen <dave.hansen@intel.com> wrote:
>
> On 12/17/18 11:55 AM, Andy Lutomirski wrote:
> >> You're effectively rebuilding reverse-mapping infrastructure here.  It's
> >> a frequent thing for the core VM to need to go from 'struct page' back
> >> to the page tables mapping it.  For that we go (logically)
> >> page->{anon_vma,mapping}->vma->vm_mm->pagetable.
> > This is a bit outside my expertise here, but doesn't
> > unmap_mapping_range() do exactly what SGX wants?
>
> There's no 'struct page' for enclave memory as it stands.  That means no
> page cache, and that means there's no 'struct address_space *mapping' in
> the first place.
>
> Basically, the choice was made a long time ago to have SGX's memory
> management live outside the core VM.  I've waffled back and forth on it,
> but I do still think this is the right way to do it.

AFAICS a lack of struct page isn't a problem.  The core code seems to
understand that address_space objects might cover non-struct-page
memory.  Morally, enclave memory is a lot like hot-unpluggable PCI
space.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 20:10                         ` Andy Lutomirski
@ 2018-12-17 20:15                           ` Dave Hansen
  2018-12-17 22:36                             ` Sean Christopherson
  2018-12-18  1:40                           ` Jarkko Sakkinen
  1 sibling, 1 reply; 155+ messages in thread
From: Dave Hansen @ 2018-12-17 20:15 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Jarkko Sakkinen, Sean Christopherson, X86 ML, Platform Driver,
	linux-sgx, nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir,
	Haitao Huang, Andy Shevchenko, Thomas Gleixner, Svahn, Kai,
	mark.shanahan, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On 12/17/18 12:10 PM, Andy Lutomirski wrote:
>> There's no 'struct page' for enclave memory as it stands.  That means no
>> page cache, and that means there's no 'struct address_space *mapping' in
>> the first place.
>>
>> Basically, the choice was made a long time ago to have SGX's memory
>> management live outside the core VM.  I've waffled back and forth on it,
>> but I do still think this is the right way to do it.
> AFAICS a lack of struct page isn't a problem.  The core code seems to
> understand that address_space objects might cover non-struct-page
> memory.  Morally, enclave memory is a lot like hot-unpluggable PCI
> space.

Yeah, this is true.  The existing code seems to make it all the way from
unmap_mapping_range() down to zap_page_range() without 'struct page'.

Overall, I think what Andy is saying here is that an open(/dev/sgx)
should give you a "unique" enclave fd.  That fd can end up mapped into
one or more processes either via fork() or the other ways fds end up
getting handed around.  mmap() of this fd would be *required* to be
MAP_SHARED.  That means you don't need to support COW, and the semantics
are the same as any other MAP_SHARED mapping: children and parents and
anybody mmap()'ing it must all coordinate.

This sounds interesting at least.  It might lead to an unholy mess in
the driver, or it might be a great cleanup.  But, it does sound like
something that would both potentially simplify the semantics and the
implementation.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 19:33             ` Jarkko Sakkinen
@ 2018-12-17 20:21               ` Jarkko Sakkinen
  2018-12-18 13:13                 ` Jarkko Sakkinen
  0 siblings, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-17 20:21 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Dave Hansen, x86, platform-driver-x86, linux-sgx, nhorman,
	npmccallum, serge.ayoun, shay.katz-zamir, haitao.huang,
	andriy.shevchenko, tglx, kai.svahn, mark.shanahan, luto,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Dec 17, 2018 at 09:33:22PM +0200, Jarkko Sakkinen wrote:
> On Mon, Dec 17, 2018 at 10:48:58AM -0800, Sean Christopherson wrote:
> > On Mon, Dec 17, 2018 at 08:43:33PM +0200, Jarkko Sakkinen wrote:
> > > On Mon, Dec 17, 2018 at 10:36:13AM -0800, Sean Christopherson wrote:
> > > > I'm pretty sure doing mmget() would result in circular dependencies and
> > > > a zombie enclave.  In the do_exit() case where a task is abruptly killed:
> > > >  
> > > >   - __mmput() is never called because the enclave holds a ref
> > > >   - sgx_encl_release() is never be called because its VMAs hold refs
> > > >   - sgx_vma_close() is never called because __mmput()->exit_mmap() is
> > > >     blocked and the process itself is dead, i.e. won't unmap anything.
> > > 
> > > Right, it does, you are absolutely right. Tried it and removed the
> > > commit already.
> > > 
> > > Well, what we came up from your suggestion i.e. setting mm to NULL
> > > and checking that is very subtle change and does not have any such
> > > circular dependencies. We'll go with that.
> > 
> > We can't set mm to NULL as we need it to unregister the notifier, and
> > I'm fairly certain attempting to unregister in the release callback
> > will deadlock.
> 
> Noticed that too. mmu_notifier_unregister() requires a valid mm.

Both branches updated...

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 19:12             ` Andy Lutomirski
  2018-12-17 19:17               ` Dave Hansen
@ 2018-12-17 22:20               ` Sean Christopherson
  2018-12-18  1:39                 ` Jarkko Sakkinen
  2018-12-18  4:59                 ` Andy Lutomirski
  2018-12-18  1:17               ` Jarkko Sakkinen
  2 siblings, 2 replies; 155+ messages in thread
From: Sean Christopherson @ 2018-12-17 22:20 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Dave Hansen, Jarkko Sakkinen, X86 ML, Platform Driver, linux-sgx,
	nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir, Haitao Huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Dec 17, 2018 at 11:12:21AM -0800, Andy Lutomirski wrote:
> On Mon, Dec 17, 2018 at 10:47 AM Dave Hansen <dave.hansen@intel.com> wrote:
> >
> > On 12/17/18 10:43 AM, Jarkko Sakkinen wrote:
> > > On Mon, Dec 17, 2018 at 10:36:13AM -0800, Sean Christopherson wrote:
> > >> I'm pretty sure doing mmget() would result in circular dependencies and
> > >> a zombie enclave.  In the do_exit() case where a task is abruptly killed:
> > >>
> > >>   - __mmput() is never called because the enclave holds a ref
> > >>   - sgx_encl_release() is never be called because its VMAs hold refs
> > >>   - sgx_vma_close() is never called because __mmput()->exit_mmap() is
> > >>     blocked and the process itself is dead, i.e. won't unmap anything.
> > > Right, it does, you are absolutely right. Tried it and removed the
> > > commit already.
> > >
> > > Well, what we came up from your suggestion i.e. setting mm to NULL
> > > and checking that is very subtle change and does not have any such
> > > circular dependencies. We'll go with that.
> >
> > This all screams that you need to break out this code from the massive
> > "18" patch and get the mm interactions reviewed more thoroughly.
> >
> > Also, no matter what method you go with, you have a bunch of commenting
> > and changelogging to do here.
> 
> I'm going to ask an obnoxious high-level question: why does an enclave
> even refer to a specific mm?

Primarily because that's what the code has "always" done.  I can't
speak for Jarkko, but I got involved with this joyful project long after
the code was originally written.

> If I were designing this thing, and if I hadn't started trying to
> implement it, my first thought would be that an enclave tracks its
> linear address range, which is just a pair of numbers, and also keeps
> track of a whole bunch of physical EPC pages, data structures, etc.
> And that mmap() gets rejected unless the requested virtual address
> matches the linear address range that the enclave wants and, aside
> from that, just creates a VMA that keeps a reference to the enclave.
> (And, for convenience, I suppose that the first mmap() call done
> before any actual enclave setup happens could choose any address and
> then cause the enclave to lock itself to that address, although a
> regular anonymous PROT_NONE MAP_NORESERVE mapping would do just fine,
> too.)  And the driver would explicitly allow multiple different mms to
> have the same enclave mapped.  More importantly, a daemon could set up
> an enclave without necessarily mapping it at all and then SCM_RIGHTS
> the enclave over to the process that plans to run it.

Hmm, this could work, the obvious weirdness would be ensuring the linear
range is available in the destination mm, but that'd be userspace's
problem.

I don't think we'd need to keep a reference to the enclave in the VMA.
The enclave's ref could be held by the fd.  Assuming the kernel is using
its private mapping to access the enclave, that's all we'd need to be
able to manipulate the enclave, e.g. reclaim EPC pages.  Userspace would
need to keep the fd alive in order to use the VMA, but that sort of goes
without saying.  The mm/VMA juggling today is for zapping/testing the
correct PTEs, but as you pointed out in a different email we can use
unmap_mapping_range(), with the enclave's fd being the source of the
address space passed to unmap_mapping_range().  Removing a VMA simply
means we don't need to zap it or test its age.
 
> Now I'm sure this has all kinds of problems, such as the ISA possibly
> making it rather obnoxious to add pages to the enclave without having
> it mapped.  But these operations could, in principle, be done by
> having the enclave own a private mm that's used just for setup.  While
> this would be vaguely annoying, Nadav's still-pending-but-nearly-done
> text_poke series adds all the infrastructure that's needed for the
> kernel to manage little private mms.  But some things get simpler --
> invalidating the enclave can presumably use the regular rmap APIs to
> zap all the PTEs in all VMAs pointing into the enclave.

We don't even need a private mm, we can (and already do) use the kernel's
translations for ENCLS instructions.  Hardware only enforces the linear
address stuff when it's actually in enclave mode, i.e. executing the
enclave.  ENCLS instructions aren't subject to the ELRANGE checks and
can use any VA->PA combination.

> So I'm not saying that you shouldn't do it the way you are now, but I
> do think that the changelog or at least some emails should explain
> *why* the enclave needs to keep a pointer to the creating process's
> mm.  And, if you do keep the current model, it would be nice to
> understand what happens if you do something awful like mremap()ing an
> enclave, or calling madvise on it, or otherwise abusing the vma.  Or
> doing fork(), for that matter.
> 
> I also find it suspicious that the various ioctl handlers
> systematically ignore their "filep" parameters and instead use
> find_vma() to find the relevant mm data structures.  That seems
> backwards.

My brain is still sorting out the details, but I generally like the idea
of allocating an anon inode when creating an enclave, and exposing the
other ioctls() via the returned fd.  This is essentially the approach
used by KVM to manage multiple "layers" of ioctls across KVM itself, VMs
and vCPUS.  There are even similarities to accessing physical memory via
multiple disparate domains, e.g. host kernel, host userspace and guest.

The only potential hiccup I can see is the build flow.  Currently,
EADD+EEXTEND is done via a work queue to avoid major performance issues
(10x regression) when userspace is building multiple enclaves in parallel
using goroutines to wrap Cgo (the issue might apply to any M:N scheduler,
but I've only confirmed the Golang case).  The issue is that allocating
an EPC page acts like a blocking syscall when the EPC is under pressure,
i.e. an EPC page isn't immediately available.  This causes Go's scheduler
to thrash and tank performance[1].

That being said, I think we could simply do mmgrab()/mmdrop() for each
page to be added, and then do mmget_not_zero()/mmput() when actually
inserting into the mm's page tables.  Conceptually that seems cleaner
than implicitly relying on the mmu_notifier to guarantee the lifecycle
of the mm.

Alternatively, we could change the EADD+EEXTEND flow to not insert the
added page's PFN into the owner's process space, i.e. force userspace to
fault when it runs the enclave.  But that only delays the issue because
eventually we'll want to account EPC pages, i.e. add a cgroup, at which
point we'll likely need current->mm anyways.

[1] https://github.com/golang/go/issues/19574

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 20:15                           ` Dave Hansen
@ 2018-12-17 22:36                             ` Sean Christopherson
  0 siblings, 0 replies; 155+ messages in thread
From: Sean Christopherson @ 2018-12-17 22:36 UTC (permalink / raw)
  To: Dave Hansen
  Cc: Andy Lutomirski, Jarkko Sakkinen, X86 ML, Platform Driver,
	linux-sgx, nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir,
	Haitao Huang, Andy Shevchenko, Thomas Gleixner, Svahn, Kai,
	mark.shanahan, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Dec 17, 2018 at 12:15:47PM -0800, Dave Hansen wrote:
> On 12/17/18 12:10 PM, Andy Lutomirski wrote:
> >> There's no 'struct page' for enclave memory as it stands.  That means no
> >> page cache, and that means there's no 'struct address_space *mapping' in
> >> the first place.
> >>
> >> Basically, the choice was made a long time ago to have SGX's memory
> >> management live outside the core VM.  I've waffled back and forth on it,
> >> but I do still think this is the right way to do it.
> > AFAICS a lack of struct page isn't a problem.  The core code seems to
> > understand that address_space objects might cover non-struct-page
> > memory.  Morally, enclave memory is a lot like hot-unpluggable PCI
> > space.
> 
> Yeah, this is true.  The existing code seems to make it all the way from
> unmap_mapping_range() down to zap_page_range() without 'struct page'.
> 
> Overall, I think what Andy is saying here is that an open(/dev/sgx)
> should give you a "unique" enclave fd.  That fd can end up mapped into
> one or more processes either via fork() or the other ways fds end up
> getting handed around.  mmap() of this fd would be *required* to be
> MAP_SHARED.  That means you don't need to support COW, and the semantics
> are the same as any other MAP_SHARED mapping: children and parents and
> anybody mmap()'ing it must all coordinate.
> 
> This sounds interesting at least.  It might lead to an unholy mess in
> the driver, or it might be a great cleanup.  But, it does sound like
> something that would both potentially simplify the semantics and the
> implementation.

It's very similar to KVM's model, which has proven to be fairly robust,
so I don't think it'll be an unholy mess (famous last words).  It
probably won't be a "great" cleanup per se, but it definitely should
make the code more maintainable in the long run.

The other interesting aspect of the enclave fd approach is that it would
allow userspace to *execute* an enclave from multiple processes, so long
as it did the necessary multiplexing of pthreads to enclave threads.  I
think SGX2 instructions (dynamic EPC management) would even allow adding
new enclave threads on-demand.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 19:12             ` Andy Lutomirski
  2018-12-17 19:17               ` Dave Hansen
  2018-12-17 22:20               ` Sean Christopherson
@ 2018-12-18  1:17               ` Jarkko Sakkinen
  2018-12-18  1:31                 ` Jarkko Sakkinen
  2 siblings, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-18  1:17 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Dave Hansen, Sean Christopherson, X86 ML, Platform Driver,
	linux-sgx, nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir,
	Haitao Huang, Andy Shevchenko, Thomas Gleixner, Svahn, Kai,
	mark.shanahan, Suresh Siddha, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Dec 17, 2018 at 11:12:21AM -0800, Andy Lutomirski wrote:
> I'm going to ask an obnoxious high-level question: why does an enclave
> even refer to a specific mm?

The reason is that it has not been yet in focus in the review process
and there has been other concerns.

At least the code is fairly stable i.e. working code is usually good
starting point for making something different (ignoring the recent
regression caused by the shmem to VMA migration).

> If I were designing this thing, and if I hadn't started trying to
> implement it, my first thought would be that an enclave tracks its
> linear address range, which is just a pair of numbers, and also keeps
> track of a whole bunch of physical EPC pages, data structures, etc.
> And that mmap() gets rejected unless the requested virtual address
> matches the linear address range that the enclave wants and, aside
> from that, just creates a VMA that keeps a reference to the enclave.
> (And, for convenience, I suppose that the first mmap() call done
> before any actual enclave setup happens could choose any address and
> then cause the enclave to lock itself to that address, although a
> regular anonymous PROT_NONE MAP_NORESERVE mapping would do just fine,
> too.)  And the driver would explicitly allow multiple different mms to
> have the same enclave mapped.  More importantly, a daemon could set up
> an enclave without necessarily mapping it at all and then SCM_RIGHTS
> the enclave over to the process that plans to run it.

The current SGX_IOC_ENCLAVE_CREATE ioctl would be trivial to change to
use this approach. Instead looking up VMA with an enclave instance it
would create a new enclave instance.

Then we could have SGX_IOC_ENCLAVE_ATTACH to attach an enclave to a VMA.

This does not sound too complicated.

> Now I'm sure this has all kinds of problems, such as the ISA possibly
> making it rather obnoxious to add pages to the enclave without having
> it mapped.  But these operations could, in principle, be done by

We do EADD in a kthread. What this would require to put current->mm
into a request that it is processed by that thread. This would be
doable with mmget().

The deadlock that Sean mentioned would not exist since closing VMAs
is not bounded to the enclave life-cycle anymore.

So at least non-swapping ISA is easy to fit to this framework. I can
rework this for v19.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-18  1:17               ` Jarkko Sakkinen
@ 2018-12-18  1:31                 ` Jarkko Sakkinen
  0 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-18  1:31 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Dave Hansen, Sean Christopherson, X86 ML, Platform Driver,
	linux-sgx, nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir,
	Haitao Huang, Andy Shevchenko, Thomas Gleixner, Svahn, Kai,
	mark.shanahan, Suresh Siddha, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Tue, Dec 18, 2018 at 03:17:25AM +0200, Jarkko Sakkinen wrote:
> On Mon, Dec 17, 2018 at 11:12:21AM -0800, Andy Lutomirski wrote:
> > I'm going to ask an obnoxious high-level question: why does an enclave
> > even refer to a specific mm?
> 
> The reason is that it has not been yet in focus in the review process
> and there has been other concerns.
> 
> At least the code is fairly stable i.e. working code is usually good
> starting point for making something different (ignoring the recent
> regression caused by the shmem to VMA migration).
> 
> > If I were designing this thing, and if I hadn't started trying to
> > implement it, my first thought would be that an enclave tracks its
> > linear address range, which is just a pair of numbers, and also keeps
> > track of a whole bunch of physical EPC pages, data structures, etc.
> > And that mmap() gets rejected unless the requested virtual address
> > matches the linear address range that the enclave wants and, aside
> > from that, just creates a VMA that keeps a reference to the enclave.
> > (And, for convenience, I suppose that the first mmap() call done
> > before any actual enclave setup happens could choose any address and
> > then cause the enclave to lock itself to that address, although a
> > regular anonymous PROT_NONE MAP_NORESERVE mapping would do just fine,
> > too.)  And the driver would explicitly allow multiple different mms to
> > have the same enclave mapped.  More importantly, a daemon could set up
> > an enclave without necessarily mapping it at all and then SCM_RIGHTS
> > the enclave over to the process that plans to run it.
> 
> The current SGX_IOC_ENCLAVE_CREATE ioctl would be trivial to change to
> use this approach. Instead looking up VMA with an enclave instance it
> would create a new enclave instance.
> 
> Then we could have SGX_IOC_ENCLAVE_ATTACH to attach an enclave to a VMA.
> 
> This does not sound too complicated.
> 
> > Now I'm sure this has all kinds of problems, such as the ISA possibly
> > making it rather obnoxious to add pages to the enclave without having
> > it mapped.  But these operations could, in principle, be done by
> 
> We do EADD in a kthread. What this would require to put current->mm
> into a request that it is processed by that thread. This would be
> doable with mmget().

Correction here. We need mm just for vm_insert_pfn(), which would be
removed, no need to pass mm.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 22:20               ` Sean Christopherson
@ 2018-12-18  1:39                 ` Jarkko Sakkinen
  2018-12-18  3:27                   ` Jarkko Sakkinen
  2018-12-18  4:55                   ` Andy Lutomirski
  2018-12-18  4:59                 ` Andy Lutomirski
  1 sibling, 2 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-18  1:39 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Andy Lutomirski, Dave Hansen, X86 ML, Platform Driver, linux-sgx,
	nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir, Haitao Huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Dec 17, 2018 at 02:20:48PM -0800, Sean Christopherson wrote:
> The only potential hiccup I can see is the build flow.  Currently,
> EADD+EEXTEND is done via a work queue to avoid major performance issues
> (10x regression) when userspace is building multiple enclaves in parallel
> using goroutines to wrap Cgo (the issue might apply to any M:N scheduler,
> but I've only confirmed the Golang case).  The issue is that allocating
> an EPC page acts like a blocking syscall when the EPC is under pressure,
> i.e. an EPC page isn't immediately available.  This causes Go's scheduler
> to thrash and tank performance[1].

I don't see any major issues having that kthread. All the code that
maps the enclave would be removed.

I would only allow to map enclave to process address space after the
enclave has been initialized i.e. SGX_IOC_ENCLAVE_ATTACH.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 20:10                         ` Andy Lutomirski
  2018-12-17 20:15                           ` Dave Hansen
@ 2018-12-18  1:40                           ` Jarkko Sakkinen
  1 sibling, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-18  1:40 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Dave Hansen, Sean Christopherson, X86 ML, Platform Driver,
	linux-sgx, nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir,
	Haitao Huang, Andy Shevchenko, Thomas Gleixner, Svahn, Kai,
	mark.shanahan, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Dec 17, 2018 at 12:10:17PM -0800, Andy Lutomirski wrote:
> On Mon, Dec 17, 2018 at 12:03 PM Dave Hansen <dave.hansen@intel.com> wrote:
> >
> > On 12/17/18 11:55 AM, Andy Lutomirski wrote:
> > >> You're effectively rebuilding reverse-mapping infrastructure here.  It's
> > >> a frequent thing for the core VM to need to go from 'struct page' back
> > >> to the page tables mapping it.  For that we go (logically)
> > >> page->{anon_vma,mapping}->vma->vm_mm->pagetable.
> > > This is a bit outside my expertise here, but doesn't
> > > unmap_mapping_range() do exactly what SGX wants?
> >
> > There's no 'struct page' for enclave memory as it stands.  That means no
> > page cache, and that means there's no 'struct address_space *mapping' in
> > the first place.
> >
> > Basically, the choice was made a long time ago to have SGX's memory
> > management live outside the core VM.  I've waffled back and forth on it,
> > but I do still think this is the right way to do it.
> 
> AFAICS a lack of struct page isn't a problem.  The core code seems to
> understand that address_space objects might cover non-struct-page
> memory.  Morally, enclave memory is a lot like hot-unpluggable PCI
> space.

I'm fine using it if it works. Will try it for v19.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-18  1:39                 ` Jarkko Sakkinen
@ 2018-12-18  3:27                   ` Jarkko Sakkinen
  2018-12-18  5:02                     ` Andy Lutomirski
  2018-12-18  4:55                   ` Andy Lutomirski
  1 sibling, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-18  3:27 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Andy Lutomirski, Dave Hansen, X86 ML, Platform Driver, linux-sgx,
	nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir, Haitao Huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Tue, Dec 18, 2018 at 03:39:18AM +0200, Jarkko Sakkinen wrote:
> On Mon, Dec 17, 2018 at 02:20:48PM -0800, Sean Christopherson wrote:
> > The only potential hiccup I can see is the build flow.  Currently,
> > EADD+EEXTEND is done via a work queue to avoid major performance issues
> > (10x regression) when userspace is building multiple enclaves in parallel
> > using goroutines to wrap Cgo (the issue might apply to any M:N scheduler,
> > but I've only confirmed the Golang case).  The issue is that allocating
> > an EPC page acts like a blocking syscall when the EPC is under pressure,
> > i.e. an EPC page isn't immediately available.  This causes Go's scheduler
> > to thrash and tank performance[1].
> 
> I don't see any major issues having that kthread. All the code that
> maps the enclave would be removed.
> 
> I would only allow to map enclave to process address space after the
> enclave has been initialized i.e. SGX_IOC_ENCLAVE_ATTACH.

Some refined thoughts.

PTE insertion can done in the #PF handler. In fact, we can PoC this
already with the current architecture (and I will right after sending
v18).

The backing space is a bit more nasty issue in the add pager thread.
The previous shmem swapping would have been a better fit. Maybe that
should be reconsidered?

If shmem was used, all the commits up to "SGX Enclave Driver" could
be reworked to the new model.

When we think about the swapping code, there uprises some difficulties.
Namely, when a page is swapped, the enclave must unmap the PTE from all
processes that have it mapped.

I have a one compromise solution for the problem above: make enclaves
shared BUT mutually exclusive. When you attach an enclave it gets
detached from the previous process that had it. This would still fully
implement the daemon example that Andy gave in earlier response.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-18  1:39                 ` Jarkko Sakkinen
  2018-12-18  3:27                   ` Jarkko Sakkinen
@ 2018-12-18  4:55                   ` Andy Lutomirski
  2018-12-18 13:18                     ` Jarkko Sakkinen
  1 sibling, 1 reply; 155+ messages in thread
From: Andy Lutomirski @ 2018-12-18  4:55 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Sean Christopherson, Andy Lutomirski, Dave Hansen, X86 ML,
	Platform Driver, linux-sgx, nhorman, npmccallum, Ayoun, Serge,
	shay.katz-zamir, Haitao Huang, Andy Shevchenko, Thomas Gleixner,
	Svahn, Kai, mark.shanahan, Suresh Siddha, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Dec 17, 2018 at 5:39 PM Jarkko Sakkinen
<jarkko.sakkinen@linux.intel.com> wrote:
>
> On Mon, Dec 17, 2018 at 02:20:48PM -0800, Sean Christopherson wrote:
> > The only potential hiccup I can see is the build flow.  Currently,
> > EADD+EEXTEND is done via a work queue to avoid major performance issues
> > (10x regression) when userspace is building multiple enclaves in parallel
> > using goroutines to wrap Cgo (the issue might apply to any M:N scheduler,
> > but I've only confirmed the Golang case).  The issue is that allocating
> > an EPC page acts like a blocking syscall when the EPC is under pressure,
> > i.e. an EPC page isn't immediately available.  This causes Go's scheduler
> > to thrash and tank performance[1].
>
> I don't see any major issues having that kthread. All the code that
> maps the enclave would be removed.
>
> I would only allow to map enclave to process address space after the
> enclave has been initialized i.e. SGX_IOC_ENCLAVE_ATTACH.
>

What's SGX_IOC_ENCLAVE_ATTACH?  Why would it be needed at all?  I
would imagine that all pages would be faulted in as needed (or
prefaulted as an optimization) and the enclave would just work in any
process.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 22:20               ` Sean Christopherson
  2018-12-18  1:39                 ` Jarkko Sakkinen
@ 2018-12-18  4:59                 ` Andy Lutomirski
  2018-12-18 13:11                   ` Jarkko Sakkinen
  2018-12-18 15:44                   ` Sean Christopherson
  1 sibling, 2 replies; 155+ messages in thread
From: Andy Lutomirski @ 2018-12-18  4:59 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Dave Hansen, Jarkko Sakkinen, X86 ML, Platform Driver, linux-sgx,
	nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir, Haitao Huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Dec 17, 2018 at 2:20 PM Sean Christopherson
<sean.j.christopherson@intel.com> wrote:
>

> My brain is still sorting out the details, but I generally like the idea
> of allocating an anon inode when creating an enclave, and exposing the
> other ioctls() via the returned fd.  This is essentially the approach
> used by KVM to manage multiple "layers" of ioctls across KVM itself, VMs
> and vCPUS.  There are even similarities to accessing physical memory via
> multiple disparate domains, e.g. host kernel, host userspace and guest.
>

In my mind, opening /dev/sgx would give you the requisite inode.  I'm
not 100% sure that the chardev infrastructure allows this, but I think
it does.

> The only potential hiccup I can see is the build flow.  Currently,
> EADD+EEXTEND is done via a work queue to avoid major performance issues
> (10x regression) when userspace is building multiple enclaves in parallel
> using goroutines to wrap Cgo (the issue might apply to any M:N scheduler,
> but I've only confirmed the Golang case).  The issue is that allocating
> an EPC page acts like a blocking syscall when the EPC is under pressure,
> i.e. an EPC page isn't immediately available.  This causes Go's scheduler
> to thrash and tank performance[1].

What's the issue, and how does a workqueue help?  I'm wondering if a
nicer solution would be an ioctl to add lots of pages in a single
call.

>
> Alternatively, we could change the EADD+EEXTEND flow to not insert the
> added page's PFN into the owner's process space, i.e. force userspace to
> fault when it runs the enclave.  But that only delays the issue because
> eventually we'll want to account EPC pages, i.e. add a cgroup, at which
> point we'll likely need current->mm anyways.

You should be able to account the backing pages to a cgroup without
actually sticking them into the EPC, no?  Or am I misunderstanding?  I
guess we'll eventually want a cgroup to limit use of the limited EPC
resources.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-18  3:27                   ` Jarkko Sakkinen
@ 2018-12-18  5:02                     ` Andy Lutomirski
  2018-12-18 13:27                       ` Jarkko Sakkinen
  0 siblings, 1 reply; 155+ messages in thread
From: Andy Lutomirski @ 2018-12-18  5:02 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Sean Christopherson, Andy Lutomirski, Dave Hansen, X86 ML,
	Platform Driver, linux-sgx, nhorman, npmccallum, Ayoun, Serge,
	shay.katz-zamir, Haitao Huang, Andy Shevchenko, Thomas Gleixner,
	Svahn, Kai, mark.shanahan, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Dec 17, 2018 at 7:27 PM Jarkko Sakkinen
<jarkko.sakkinen@linux.intel.com> wrote:
>
> On Tue, Dec 18, 2018 at 03:39:18AM +0200, Jarkko Sakkinen wrote:
> > On Mon, Dec 17, 2018 at 02:20:48PM -0800, Sean Christopherson wrote:
> > > The only potential hiccup I can see is the build flow.  Currently,
> > > EADD+EEXTEND is done via a work queue to avoid major performance issues
> > > (10x regression) when userspace is building multiple enclaves in parallel
> > > using goroutines to wrap Cgo (the issue might apply to any M:N scheduler,
> > > but I've only confirmed the Golang case).  The issue is that allocating
> > > an EPC page acts like a blocking syscall when the EPC is under pressure,
> > > i.e. an EPC page isn't immediately available.  This causes Go's scheduler
> > > to thrash and tank performance[1].
> >
> > I don't see any major issues having that kthread. All the code that
> > maps the enclave would be removed.
> >
> > I would only allow to map enclave to process address space after the
> > enclave has been initialized i.e. SGX_IOC_ENCLAVE_ATTACH.
>
> Some refined thoughts.
>
> PTE insertion can done in the #PF handler. In fact, we can PoC this
> already with the current architecture (and I will right after sending
> v18).
>
> The backing space is a bit more nasty issue in the add pager thread.
> The previous shmem swapping would have been a better fit. Maybe that
> should be reconsidered?
>
> If shmem was used, all the commits up to "SGX Enclave Driver" could
> be reworked to the new model.
>
> When we think about the swapping code, there uprises some difficulties.
> Namely, when a page is swapped, the enclave must unmap the PTE from all
> processes that have it mapped.

That's what unmap_mapping_range(), etc do for you, no?  IOW make a
struct address_space that represents the logical enclave address
space, i.e. address 0 is the start and the pages count up from there.
You can unmap pages whenever you want, and the core mm code will take
care of zapping the pages from all vmas referencing that
address_space.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-11-16  1:01 ` [PATCH v17 18/23] platform/x86: Intel SGX driver Jarkko Sakkinen
                     ` (3 preceding siblings ...)
  2018-12-17 17:45   ` Dave Hansen
@ 2018-12-18  5:55   ` Andy Lutomirski
  2018-12-19  5:22     ` Jarkko Sakkinen
  4 siblings, 1 reply; 155+ messages in thread
From: Andy Lutomirski @ 2018-12-18  5:55 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: X86 ML, Platform Driver, linux-sgx, Dave Hansen, Christopherson,
	Sean J, nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir,
	Haitao Huang, Andy Shevchenko, Thomas Gleixner, Svahn, Kai,
	mark.shanahan, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Thu, Nov 15, 2018 at 5:08 PM Jarkko Sakkinen
<jarkko.sakkinen@linux.intel.com> wrote:
>
> 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 is a very partial review.

> +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;
> +}

I realize that this function may go away entirely but, if you keep it:
what are the locking rules?  What, if anything, prevents another
thread from destroying the enclave after sgx_encl_find() returns?

> +static int sgx_validate_secs(const struct sgx_secs *secs,
> +                            unsigned long ssaframesize)
> +{

...

> +       if (secs->attributes & SGX_ATTR_MODE64BIT) {
> +               if (secs->size > sgx_encl_size_max_64)
> +                       return -EINVAL;
> +       } else {
> +               /* On 64-bit architecture allow 32-bit encls only in
> +                * the compatibility mode.
> +                */
> +               if (!test_thread_flag(TIF_ADDR32))
> +                       return -EINVAL;
> +               if (secs->size > sgx_encl_size_max_32)
> +                       return -EINVAL;
> +       }

Why do we need the 32-bit-on-64-bit check?  In general, anything that
checks per-task or per-mm flags like TIF_ADDR32 is IMO likely to be
problematic.  You're allowing 64-bit enclaves in 32-bit tasks, so I'm
guessing you could just delete the check.

> +
> +       if (!(secs->xfrm & XFEATURE_MASK_FP) ||
> +           !(secs->xfrm & XFEATURE_MASK_SSE) ||
> +           (((secs->xfrm >> XFEATURE_BNDREGS) & 1) !=
> +            ((secs->xfrm >> XFEATURE_BNDCSR) & 1)) ||
> +           (secs->xfrm & ~sgx_xfrm_mask))
> +               return -EINVAL;

Do we need to check that the enclave doesn't use xfeatures that the
kernel doesn't know about?  Or are they all safe by design in enclave
mode?

> +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;

Hmm.  There's an argument to made that omitting this would better
exercise the code that handles fully asynchronous loss of an enclave.
Also, I think you're unnecessarily killing enclaves when suspend is
attempted but fails.

> +
> +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;
> +}
> +

I'm so sorry you had to deal with this API.  Once Zinc lands, you
could clean this up :)


> +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);
> +       }

Hmm.  This version has explicit refcounting.

> +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 |
> +                        VM_DONTCOPY;
> +
> +       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)))
> +               return -EINVAL;
> +
> +       if (len > sgx_encl_size_max_64)
> +               return -EINVAL;
> +
> +       if (len > sgx_encl_size_max_32 && test_thread_flag(TIF_ADDR32))
> +               return -EINVAL;

Generally speaking, this type of check wants to be
in_compat_syscall().  But I'm not sure I understand why you need it at
all.

> +static void sgx_ipi_cb(void *info)
> +{
> +}
> +
> +void sgx_flush_cpus(struct sgx_encl *encl)
> +{
> +       on_each_cpu_mask(mm_cpumask(encl->mm), sgx_ipi_cb, NULL, 1);
> +}

Please add a comment explaining what this promises to do.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-18  4:59                 ` Andy Lutomirski
@ 2018-12-18 13:11                   ` Jarkko Sakkinen
  2018-12-18 15:44                   ` Sean Christopherson
  1 sibling, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-18 13:11 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Sean Christopherson, Dave Hansen, X86 ML, Platform Driver,
	linux-sgx, nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir,
	Haitao Huang, Andy Shevchenko, Thomas Gleixner, Svahn, Kai,
	mark.shanahan, Suresh Siddha, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Dec 17, 2018 at 08:59:54PM -0800, Andy Lutomirski wrote:
> On Mon, Dec 17, 2018 at 2:20 PM Sean Christopherson
> <sean.j.christopherson@intel.com> wrote:
> >
> 
> > My brain is still sorting out the details, but I generally like the idea
> > of allocating an anon inode when creating an enclave, and exposing the
> > other ioctls() via the returned fd.  This is essentially the approach
> > used by KVM to manage multiple "layers" of ioctls across KVM itself, VMs
> > and vCPUS.  There are even similarities to accessing physical memory via
> > multiple disparate domains, e.g. host kernel, host userspace and guest.
> >
> 
> In my mind, opening /dev/sgx would give you the requisite inode.  I'm
> not 100% sure that the chardev infrastructure allows this, but I think
> it does.

Yes, this is what I was thinking too i.e.

enclave_fd = open("/dev/sgx/", O_RDWR);

After this enclave_fd "is" the enclave up until the file is closed.

> > The only potential hiccup I can see is the build flow.  Currently,
> > EADD+EEXTEND is done via a work queue to avoid major performance issues
> > (10x regression) when userspace is building multiple enclaves in parallel
> > using goroutines to wrap Cgo (the issue might apply to any M:N scheduler,
> > but I've only confirmed the Golang case).  The issue is that allocating
> > an EPC page acts like a blocking syscall when the EPC is under pressure,
> > i.e. an EPC page isn't immediately available.  This causes Go's scheduler
> > to thrash and tank performance[1].
> 
> What's the issue, and how does a workqueue help?  I'm wondering if a
> nicer solution would be an ioctl to add lots of pages in a single
> call.

I don't think this really is an issue as long as the thread does not
depend on any VMAs.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-17 20:21               ` Jarkko Sakkinen
@ 2018-12-18 13:13                 ` Jarkko Sakkinen
  2018-12-18 15:46                   ` Sean Christopherson
  0 siblings, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-18 13:13 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Dave Hansen, x86, platform-driver-x86, linux-sgx, nhorman,
	npmccallum, serge.ayoun, shay.katz-zamir, haitao.huang,
	andriy.shevchenko, tglx, kai.svahn, mark.shanahan, luto,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Dec 17, 2018 at 10:21:49PM +0200, Jarkko Sakkinen wrote:
> On Mon, Dec 17, 2018 at 09:33:22PM +0200, Jarkko Sakkinen wrote:
> > On Mon, Dec 17, 2018 at 10:48:58AM -0800, Sean Christopherson wrote:
> > > On Mon, Dec 17, 2018 at 08:43:33PM +0200, Jarkko Sakkinen wrote:
> > > > On Mon, Dec 17, 2018 at 10:36:13AM -0800, Sean Christopherson wrote:
> > > > > I'm pretty sure doing mmget() would result in circular dependencies and
> > > > > a zombie enclave.  In the do_exit() case where a task is abruptly killed:
> > > > >  
> > > > >   - __mmput() is never called because the enclave holds a ref
> > > > >   - sgx_encl_release() is never be called because its VMAs hold refs
> > > > >   - sgx_vma_close() is never called because __mmput()->exit_mmap() is
> > > > >     blocked and the process itself is dead, i.e. won't unmap anything.
> > > > 
> > > > Right, it does, you are absolutely right. Tried it and removed the
> > > > commit already.
> > > > 
> > > > Well, what we came up from your suggestion i.e. setting mm to NULL
> > > > and checking that is very subtle change and does not have any such
> > > > circular dependencies. We'll go with that.
> > > 
> > > We can't set mm to NULL as we need it to unregister the notifier, and
> > > I'm fairly certain attempting to unregister in the release callback
> > > will deadlock.
> > 
> > Noticed that too. mmu_notifier_unregister() requires a valid mm.
> 
> Both branches updated...

I'm not still seeing why you would want to call sgx_free_page() from
sgx_invalidate(). Kind of resistant to adding extra logging just for
checking for programming errors. What I would do if I had to debug
there a leak would be simply put kretprobe on __sgx_free_page().

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-18  4:55                   ` Andy Lutomirski
@ 2018-12-18 13:18                     ` Jarkko Sakkinen
  0 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-18 13:18 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Sean Christopherson, Dave Hansen, X86 ML, Platform Driver,
	linux-sgx, nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir,
	Haitao Huang, Andy Shevchenko, Thomas Gleixner, Svahn, Kai,
	mark.shanahan, Suresh Siddha, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Dec 17, 2018 at 08:55:02PM -0800, Andy Lutomirski wrote:
> On Mon, Dec 17, 2018 at 5:39 PM Jarkko Sakkinen
> <jarkko.sakkinen@linux.intel.com> wrote:
> >
> > On Mon, Dec 17, 2018 at 02:20:48PM -0800, Sean Christopherson wrote:
> > > The only potential hiccup I can see is the build flow.  Currently,
> > > EADD+EEXTEND is done via a work queue to avoid major performance issues
> > > (10x regression) when userspace is building multiple enclaves in parallel
> > > using goroutines to wrap Cgo (the issue might apply to any M:N scheduler,
> > > but I've only confirmed the Golang case).  The issue is that allocating
> > > an EPC page acts like a blocking syscall when the EPC is under pressure,
> > > i.e. an EPC page isn't immediately available.  This causes Go's scheduler
> > > to thrash and tank performance[1].
> >
> > I don't see any major issues having that kthread. All the code that
> > maps the enclave would be removed.
> >
> > I would only allow to map enclave to process address space after the
> > enclave has been initialized i.e. SGX_IOC_ENCLAVE_ATTACH.
> >
> 
> What's SGX_IOC_ENCLAVE_ATTACH?  Why would it be needed at all?  I
> would imagine that all pages would be faulted in as needed (or
> prefaulted as an optimization) and the enclave would just work in any
> process.

The way I see it the efficient way to implement this is to have the
enclave attached to a single process address space at a time.

#PF handler is trivial with multiple address spaces but swapping is
a bit tedious as you would need to zap N processes.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-18  5:02                     ` Andy Lutomirski
@ 2018-12-18 13:27                       ` Jarkko Sakkinen
  0 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-18 13:27 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Sean Christopherson, Dave Hansen, X86 ML, Platform Driver,
	linux-sgx, nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir,
	Haitao Huang, Andy Shevchenko, Thomas Gleixner, Svahn, Kai,
	mark.shanahan, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Dec 17, 2018 at 09:02:03PM -0800, Andy Lutomirski wrote:
> That's what unmap_mapping_range(), etc do for you, no?  IOW make a
> struct address_space that represents the logical enclave address
> space, i.e. address 0 is the start and the pages count up from there.
> You can unmap pages whenever you want, and the core mm code will take
> care of zapping the pages from all vmas referencing that
> address_space.

OK, so it does. Did not have time to look at it last night (about
3AM) :-) Yes, we could use that to do the N process zapping.

Based on this discussion I can take the first steps with the swapping
code.

And yeah, I don't think we need anon inode for this one. Can just use
the dev inode (did not check in detail but on the surface looks like
it).

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-18  4:59                 ` Andy Lutomirski
  2018-12-18 13:11                   ` Jarkko Sakkinen
@ 2018-12-18 15:44                   ` Sean Christopherson
  2018-12-18 18:53                     ` Sean Christopherson
  2018-12-19  4:47                     ` Jarkko Sakkinen
  1 sibling, 2 replies; 155+ messages in thread
From: Sean Christopherson @ 2018-12-18 15:44 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Dave Hansen, Jarkko Sakkinen, X86 ML, Platform Driver, linux-sgx,
	nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir, Haitao Huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Dec 17, 2018 at 08:59:54PM -0800, Andy Lutomirski wrote:
> On Mon, Dec 17, 2018 at 2:20 PM Sean Christopherson
> <sean.j.christopherson@intel.com> wrote:
> >
> 
> > My brain is still sorting out the details, but I generally like the idea
> > of allocating an anon inode when creating an enclave, and exposing the
> > other ioctls() via the returned fd.  This is essentially the approach
> > used by KVM to manage multiple "layers" of ioctls across KVM itself, VMs
> > and vCPUS.  There are even similarities to accessing physical memory via
> > multiple disparate domains, e.g. host kernel, host userspace and guest.
> >
> 
> In my mind, opening /dev/sgx would give you the requisite inode.  I'm
> not 100% sure that the chardev infrastructure allows this, but I think
> it does.

My fd/inode knowledge is lacking, to say the least.  Whatever works, so
long as we have a way to uniquely identify enclaves.

> > The only potential hiccup I can see is the build flow.  Currently,
> > EADD+EEXTEND is done via a work queue to avoid major performance issues
> > (10x regression) when userspace is building multiple enclaves in parallel
> > using goroutines to wrap Cgo (the issue might apply to any M:N scheduler,
> > but I've only confirmed the Golang case).  The issue is that allocating
> > an EPC page acts like a blocking syscall when the EPC is under pressure,
> > i.e. an EPC page isn't immediately available.  This causes Go's scheduler
> > to thrash and tank performance[1].
> 
> What's the issue, and how does a workqueue help?  I'm wondering if a
> nicer solution would be an ioctl to add lots of pages in a single
> call.

Adding pages via workqueue makes the ioctl itself fast enough to avoid
triggering Go's rescheduling.  A batched EADD flow would likely help,
I just haven't had the time to rework the userspace side to be able to
test the performance.

> >
> > Alternatively, we could change the EADD+EEXTEND flow to not insert the
> > added page's PFN into the owner's process space, i.e. force userspace to
> > fault when it runs the enclave.  But that only delays the issue because
> > eventually we'll want to account EPC pages, i.e. add a cgroup, at which
> > point we'll likely need current->mm anyways.
> 
> You should be able to account the backing pages to a cgroup without
> actually sticking them into the EPC, no?  Or am I misunderstanding?  I
> guess we'll eventually want a cgroup to limit use of the limited EPC
> resources.

It's the latter, a cgroup to limit EPC.  The mm is used to retrieve the
cgroup without having track e.g. the task_struct.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-18 13:13                 ` Jarkko Sakkinen
@ 2018-12-18 15:46                   ` Sean Christopherson
  0 siblings, 0 replies; 155+ messages in thread
From: Sean Christopherson @ 2018-12-18 15:46 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Dave Hansen, x86, platform-driver-x86, linux-sgx, nhorman,
	npmccallum, serge.ayoun, shay.katz-zamir, haitao.huang,
	andriy.shevchenko, tglx, kai.svahn, mark.shanahan, luto,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Tue, Dec 18, 2018 at 03:13:11PM +0200, Jarkko Sakkinen wrote:
> On Mon, Dec 17, 2018 at 10:21:49PM +0200, Jarkko Sakkinen wrote:
> > On Mon, Dec 17, 2018 at 09:33:22PM +0200, Jarkko Sakkinen wrote:
> > > On Mon, Dec 17, 2018 at 10:48:58AM -0800, Sean Christopherson wrote:
> > > > On Mon, Dec 17, 2018 at 08:43:33PM +0200, Jarkko Sakkinen wrote:
> > > > > On Mon, Dec 17, 2018 at 10:36:13AM -0800, Sean Christopherson wrote:
> > > > > > I'm pretty sure doing mmget() would result in circular dependencies and
> > > > > > a zombie enclave.  In the do_exit() case where a task is abruptly killed:
> > > > > >  
> > > > > >   - __mmput() is never called because the enclave holds a ref
> > > > > >   - sgx_encl_release() is never be called because its VMAs hold refs
> > > > > >   - sgx_vma_close() is never called because __mmput()->exit_mmap() is
> > > > > >     blocked and the process itself is dead, i.e. won't unmap anything.
> > > > > 
> > > > > Right, it does, you are absolutely right. Tried it and removed the
> > > > > commit already.
> > > > > 
> > > > > Well, what we came up from your suggestion i.e. setting mm to NULL
> > > > > and checking that is very subtle change and does not have any such
> > > > > circular dependencies. We'll go with that.
> > > > 
> > > > We can't set mm to NULL as we need it to unregister the notifier, and
> > > > I'm fairly certain attempting to unregister in the release callback
> > > > will deadlock.
> > > 
> > > Noticed that too. mmu_notifier_unregister() requires a valid mm.
> > 
> > Both branches updated...
> 
> I'm not still seeing why you would want to call sgx_free_page() from
> sgx_invalidate(). Kind of resistant to adding extra logging just for
> checking for programming errors. What I would do if I had to debug
> there a leak would be simply put kretprobe on __sgx_free_page().

The WARN is needed to detect the leak in the first place.  And leaking
pages because EREMOVE fails usually means there's a serious bug.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-18 15:44                   ` Sean Christopherson
@ 2018-12-18 18:53                     ` Sean Christopherson
  2018-12-19  5:00                       ` Jarkko Sakkinen
  2018-12-19  4:47                     ` Jarkko Sakkinen
  1 sibling, 1 reply; 155+ messages in thread
From: Sean Christopherson @ 2018-12-18 18:53 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Dave Hansen, Jarkko Sakkinen, X86 ML, Platform Driver, linux-sgx,
	nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir, Haitao Huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Tue, Dec 18, 2018 at 07:44:18AM -0800, Sean Christopherson wrote:
> On Mon, Dec 17, 2018 at 08:59:54PM -0800, Andy Lutomirski wrote:
> > On Mon, Dec 17, 2018 at 2:20 PM Sean Christopherson
> > <sean.j.christopherson@intel.com> wrote:
> > >
> > 
> > > My brain is still sorting out the details, but I generally like the idea
> > > of allocating an anon inode when creating an enclave, and exposing the
> > > other ioctls() via the returned fd.  This is essentially the approach
> > > used by KVM to manage multiple "layers" of ioctls across KVM itself, VMs
> > > and vCPUS.  There are even similarities to accessing physical memory via
> > > multiple disparate domains, e.g. host kernel, host userspace and guest.
> > >
> > 
> > In my mind, opening /dev/sgx would give you the requisite inode.  I'm
> > not 100% sure that the chardev infrastructure allows this, but I think
> > it does.
> 
> My fd/inode knowledge is lacking, to say the least.  Whatever works, so
> long as we have a way to uniquely identify enclaves.

Actually, while we're dissecting the interface...

What if we re-organize the ioctls in such a way that we leave open the
possibility of allocating raw EPC for KVM via /dev/sgx?  I'm not 100%
positive this approach will work[1], but conceptually it fits well with
KVM's memory model, e.g. KVM is aware of the GPA<->HVA association but
generally speaking doesn't know what's physically backing each memory
region.

Tangentially related, I think we should support allocating multiple
enclaves from a single /dev/sgx fd, i.e. a process shouldn't have to
open /dev/sgx every time it wants to create a new enclave.

Something like this:

/dev/sgx
  |
  -> mmap() { return -EINVAL; }
  |
  -> unlocked_ioctl()
     |
     -> SGX_CREATE_ENCLAVE: { return alloc_enclave_fd(); }
     |  |
     |   -> mmap() { ... }
     |  | 
     |   -> get_unmapped_area() { 
     |  |           if (enclave->size) {
     |  |                   if (!addr)
     |  |                           addr = enclave->base;
     |  |                   if (addr + len + pgoff > enclave->base + enclave->size)
     |  |                           return -EINVAL;
     |  |           } else {
     |  |                   if (!validate_size(len))
     |  |                           return -EINVAL;
     |  |                   addr = naturally_align(len);
     |  |           }
     |  |   }
     |  |
     |   -> unlocked_ioctl() {
     |              SGX_ENCLAVE_ADD_PAGE: { ... }
     |              SGX_ENCLAVE_INIT: { ... }
     |              SGX_ENCLAVE_REMOVE_PAGES: { ... }
     |              SGX_ENCLAVE_MODIFY_PAGES: { ... }
     |      }
     |
     -> SGX_CREATE_VIRTUAL_EPC: {return alloc_epc_fd(); }
        |
         -> mmap() { ... }
        |
	 -> get_unmapped_area() {<page aligned/sized> }
        |
         -> unlocked_ioctl() {
                    SGX_VIRTUAL_EPC_???:
		    SGX_VIRTUAL_EPC_???:
	    }


[1] Delegating EPC management to /dev/sgx is viable for virtualizing SGX
    without oversubscribing EPC to guests, but oversubscribing EPC in a
    VMM requires handling EPC-related VM-Exits and using instructions
    that will #UD if the CPU is not post-VMXON.  I *think* having KVM
    forward VM-Exits to x86/sgx would work, but it's entirely possible
    it'd be a complete cluster.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-18 15:44                   ` Sean Christopherson
  2018-12-18 18:53                     ` Sean Christopherson
@ 2018-12-19  4:47                     ` Jarkko Sakkinen
  2018-12-19  5:24                       ` Jarkko Sakkinen
  1 sibling, 1 reply; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-19  4:47 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Andy Lutomirski, Dave Hansen, X86 ML, Platform Driver, linux-sgx,
	nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir, Haitao Huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Tue, Dec 18, 2018 at 07:44:18AM -0800, Sean Christopherson wrote:
> My fd/inode knowledge is lacking, to say the least.  Whatever works, so
> long as we have a way to uniquely identify enclaves.

I will simply trial and error :-) I think it should work since it does
own an address space, but yeah, testing will tell. We can go also with
anon inode if required.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-18 18:53                     ` Sean Christopherson
@ 2018-12-19  5:00                       ` Jarkko Sakkinen
  2018-12-19  5:13                         ` Jarkko Sakkinen
  2018-12-21 18:28                         ` Sean Christopherson
  0 siblings, 2 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-19  5:00 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Andy Lutomirski, Dave Hansen, X86 ML, Platform Driver, linux-sgx,
	nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir, Haitao Huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Tue, Dec 18, 2018 at 10:53:49AM -0800, Sean Christopherson wrote:
> What if we re-organize the ioctls in such a way that we leave open the
> possibility of allocating raw EPC for KVM via /dev/sgx?  I'm not 100%
> positive this approach will work[1], but conceptually it fits well with
> KVM's memory model, e.g. KVM is aware of the GPA<->HVA association but
> generally speaking doesn't know what's physically backing each memory
> region.

Why would you want to pass EPC through user space to KVM rather than
KVM allocating it through kernel interfaces?

> Tangentially related, I think we should support allocating multiple
> enclaves from a single /dev/sgx fd, i.e. a process shouldn't have to
> open /dev/sgx every time it wants to create a new enclave.

I'm fine with this. It just requires to create anon inode. I'll just
add a new field called 'enclave_fd' to struct sgx_enclave_create and
that's all.

I think I have otherwise ingredients for v19 ready except where to swap.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-19  5:00                       ` Jarkko Sakkinen
@ 2018-12-19  5:13                         ` Jarkko Sakkinen
  2018-12-21 18:28                         ` Sean Christopherson
  1 sibling, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-19  5:13 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Andy Lutomirski, Dave Hansen, X86 ML, Platform Driver, linux-sgx,
	nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir, Haitao Huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Wed, Dec 19, 2018 at 07:00:47AM +0200, Jarkko Sakkinen wrote:
> On Tue, Dec 18, 2018 at 10:53:49AM -0800, Sean Christopherson wrote:
> > What if we re-organize the ioctls in such a way that we leave open the
> > possibility of allocating raw EPC for KVM via /dev/sgx?  I'm not 100%
> > positive this approach will work[1], but conceptually it fits well with
> > KVM's memory model, e.g. KVM is aware of the GPA<->HVA association but
> > generally speaking doesn't know what's physically backing each memory
> > region.
> 
> Why would you want to pass EPC through user space to KVM rather than
> KVM allocating it through kernel interfaces?
> 
> > Tangentially related, I think we should support allocating multiple
> > enclaves from a single /dev/sgx fd, i.e. a process shouldn't have to
> > open /dev/sgx every time it wants to create a new enclave.
> 
> I'm fine with this. It just requires to create anon inode. I'll just
> add a new field called 'enclave_fd' to struct sgx_enclave_create and
> that's all.
> 
> I think I have otherwise ingredients for v19 ready except where to swap.

If I follow your proposal here and allow to create multiple enclaves
(i.e. with anon inodes for each) with one descriptor, is that sufficient
API to later add what you want to KVM?

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-18  5:55   ` Andy Lutomirski
@ 2018-12-19  5:22     ` Jarkko Sakkinen
  0 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-19  5:22 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: X86 ML, Platform Driver, linux-sgx, Dave Hansen, Christopherson,
	Sean J, nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir,
	Haitao Huang, Andy Shevchenko, Thomas Gleixner, Svahn, Kai,
	mark.shanahan, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Mon, Dec 17, 2018 at 09:55:08PM -0800, Andy Lutomirski wrote:
> On Thu, Nov 15, 2018 at 5:08 PM Jarkko Sakkinen
> <jarkko.sakkinen@linux.intel.com> wrote:
> >
> > 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 is a very partial review.

Thank you, appreciate it.

> > +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;
> > +}
> 
> I realize that this function may go away entirely but, if you keep it:
> what are the locking rules?  What, if anything, prevents another
> thread from destroying the enclave after sgx_encl_find() returns?

The kref inside the enclave is used to manage this but this function
directly does not prevent it (see for example sgx_encl_get). But yes,
this function does not give any guarantees (should probably have
a documentation stating this).

> > +static int sgx_validate_secs(const struct sgx_secs *secs,
> > +                            unsigned long ssaframesize)
> > +{
> 
> ...
> 
> > +       if (secs->attributes & SGX_ATTR_MODE64BIT) {
> > +               if (secs->size > sgx_encl_size_max_64)
> > +                       return -EINVAL;
> > +       } else {
> > +               /* On 64-bit architecture allow 32-bit encls only in
> > +                * the compatibility mode.
> > +                */
> > +               if (!test_thread_flag(TIF_ADDR32))
> > +                       return -EINVAL;
> > +               if (secs->size > sgx_encl_size_max_32)
> > +                       return -EINVAL;
> > +       }
> 
> Why do we need the 32-bit-on-64-bit check?  In general, anything that
> checks per-task or per-mm flags like TIF_ADDR32 is IMO likely to be
> problematic.  You're allowing 64-bit enclaves in 32-bit tasks, so I'm
> guessing you could just delete the check.

I guess you are right. I can remove this.


> 
> > +
> > +       if (!(secs->xfrm & XFEATURE_MASK_FP) ||
> > +           !(secs->xfrm & XFEATURE_MASK_SSE) ||
> > +           (((secs->xfrm >> XFEATURE_BNDREGS) & 1) !=
> > +            ((secs->xfrm >> XFEATURE_BNDCSR) & 1)) ||
> > +           (secs->xfrm & ~sgx_xfrm_mask))
> > +               return -EINVAL;
> 
> Do we need to check that the enclave doesn't use xfeatures that the
> kernel doesn't know about?  Or are they all safe by design in enclave
> mode?

Really good catch BTW. We don't check what kernel doesn't know about.

I'm not sure what harm this would have as the enclave cannot have much
effect to the outside world. Is there easy way to get similar mask
of kernel supported features as sgx_xfrm_mask? The safe play would
be to use such here as I don't have definitive answer to your second
question.

> 
> > +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;
> 
> Hmm.  There's an argument to made that omitting this would better
> exercise the code that handles fully asynchronous loss of an enclave.
> Also, I think you're unnecessarily killing enclaves when suspend is
> attempted but fails.

Are you proposing to not do anything at all to the enclaves? There was
is a problem that it could lead to infinite #PF loop if we don't do
it.


> 
> > +
> > +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;
> > +}
> > +
> 
> I'm so sorry you had to deal with this API.  Once Zinc lands, you
> could clean this up :)
> 
> 
> > +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);
> > +       }
> 
> Hmm.  This version has explicit refcounting.
> 
> > +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 |
> > +                        VM_DONTCOPY;
> > +
> > +       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)))
> > +               return -EINVAL;
> > +
> > +       if (len > sgx_encl_size_max_64)
> > +               return -EINVAL;
> > +
> > +       if (len > sgx_encl_size_max_32 && test_thread_flag(TIF_ADDR32))
> > +               return -EINVAL;
> 
> Generally speaking, this type of check wants to be
> in_compat_syscall().  But I'm not sure I understand why you need it at
> all.

I'll remove it.

> 
> > +static void sgx_ipi_cb(void *info)
> > +{
> > +}
> > +
> > +void sgx_flush_cpus(struct sgx_encl *encl)
> > +{
> > +       on_each_cpu_mask(mm_cpumask(encl->mm), sgx_ipi_cb, NULL, 1);
> > +}
> 
> Please add a comment explaining what this promises to do.

Will do.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-19  4:47                     ` Jarkko Sakkinen
@ 2018-12-19  5:24                       ` Jarkko Sakkinen
  0 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-19  5:24 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Andy Lutomirski, Dave Hansen, X86 ML, Platform Driver, linux-sgx,
	nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir, Haitao Huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Wed, Dec 19, 2018 at 06:47:32AM +0200, Jarkko Sakkinen wrote:
> On Tue, Dec 18, 2018 at 07:44:18AM -0800, Sean Christopherson wrote:
> > My fd/inode knowledge is lacking, to say the least.  Whatever works, so
> > long as we have a way to uniquely identify enclaves.
> 
> I will simply trial and error :-) I think it should work since it does
> own an address space, but yeah, testing will tell. We can go also with
> anon inode if required.

I think this can be concluded with the fact that it is nice to be able
to multiplex the dev fd. That is the key reason for using anon inode.
You KVM comment locks the decision here.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-19  5:00                       ` Jarkko Sakkinen
  2018-12-19  5:13                         ` Jarkko Sakkinen
@ 2018-12-21 18:28                         ` Sean Christopherson
  2018-12-22  0:01                           ` Jarkko Sakkinen
  1 sibling, 1 reply; 155+ messages in thread
From: Sean Christopherson @ 2018-12-21 18:28 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Andy Lutomirski, Dave Hansen, X86 ML, Platform Driver, linux-sgx,
	nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir, Haitao Huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Wed, Dec 19, 2018 at 07:00:47AM +0200, Jarkko Sakkinen wrote:
> On Tue, Dec 18, 2018 at 10:53:49AM -0800, Sean Christopherson wrote:
> > What if we re-organize the ioctls in such a way that we leave open the
> > possibility of allocating raw EPC for KVM via /dev/sgx?  I'm not 100%
> > positive this approach will work[1], but conceptually it fits well with
> > KVM's memory model, e.g. KVM is aware of the GPA<->HVA association but
> > generally speaking doesn't know what's physically backing each memory
> > region.
> 
> Why would you want to pass EPC through user space to KVM rather than
> KVM allocating it through kernel interfaces?

Delegating EPC management to userspace fits better with KVM's existing
memory ABI.  KVM provides a single ioctl(), KVM_SET_USER_MEMORY_REGION[1],
that allows userspace to create, move, modify and delete memory regions.

Skipping over a lot of details, there are essentially three options for
exposing EPC to a KVM guest:

 1) Provide a dedicated KVM ioctl() to manage EPC without routing it
    through KVM_SET_USER_MEMORY_REGION.

 2) Add a flag to 'struct kvm_userspace_memory_region' that denotes an
    EPC memory region and mmap() / allocate EPC in KVM.

 3) Provide an ABI to allocate raw EPC and let userspace manage it like
    any other memory region.

Option (1) requires duplicating all of KVM_SET_USER_MEMORY_REGION's
functionality unless the ioctl() is severly restricted.

Option (2) is an ugly abuse of KVM_SET_USER_MEMORY_REGION since the EPC
flag would have completely different semantics than all other usage of
KVM_SET_USER_MEMORY_REGION.

Thus, option (3).

Probably a better question to answer is why provide the ABI through
/dev/sgx and not /dev/kvm.  IMO /dev/sgx is a more logical way to
advertise support to userspace, e.g. userspace can simply check if
/dev/sgx (or /dev/sgx/epc) exists vs. probing a KVM capability.

Without EPC oversubscription in KVM, /dev/sgx is easily the best fit
since the EPC management would reside completely in x86/sgx, i.e. KVM
would essentially have zero code related to EPC management.

EPC oversubscription complicates things because the architecture forces
aspects of VMM oversubscription into the KVM domain, e.g. requires a
post-VMXON instruction (ENCLV) and a VM-Exit handler.   I still think
/dev/sgx is a better fit, my only concern is that the oversubscription
code would be even more heinous due to splitting responsibilities.
But, Andy's idea of having /dev/sgx/enclave vs. /dev/sgx/epc might help
avoid that entirely.

^ permalink raw reply	[flat|nested] 155+ messages in thread

* Re: [PATCH v17 18/23] platform/x86: Intel SGX driver
  2018-12-21 18:28                         ` Sean Christopherson
@ 2018-12-22  0:01                           ` Jarkko Sakkinen
  0 siblings, 0 replies; 155+ messages in thread
From: Jarkko Sakkinen @ 2018-12-22  0:01 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Andy Lutomirski, Dave Hansen, X86 ML, Platform Driver, linux-sgx,
	nhorman, npmccallum, Ayoun, Serge, shay.katz-zamir, Haitao Huang,
	Andy Shevchenko, Thomas Gleixner, Svahn, Kai, mark.shanahan,
	Suresh Siddha, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Darren Hart, Andy Shevchenko,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Fri, Dec 21, 2018 at 10:28:09AM -0800, Sean Christopherson wrote:
> > Why would you want to pass EPC through user space to KVM rather than
> > KVM allocating it through kernel interfaces?
> 
> Delegating EPC management to userspace fits better with KVM's existing
> memory ABI.  KVM provides a single ioctl(), KVM_SET_USER_MEMORY_REGION[1],
> that allows userspace to create, move, modify and delete memory regions.
> 
> Skipping over a lot of details, there are essentially three options for
> exposing EPC to a KVM guest:
> 
>  1) Provide a dedicated KVM ioctl() to manage EPC without routing it
>     through KVM_SET_USER_MEMORY_REGION.
> 
>  2) Add a flag to 'struct kvm_userspace_memory_region' that denotes an
>     EPC memory region and mmap() / allocate EPC in KVM.
> 
>  3) Provide an ABI to allocate raw EPC and let userspace manage it like
>     any other memory region.
> 
> Option (1) requires duplicating all of KVM_SET_USER_MEMORY_REGION's
> functionality unless the ioctl() is severly restricted.
> 
> Option (2) is an ugly abuse of KVM_SET_USER_MEMORY_REGION since the EPC
> flag would have completely different semantics than all other usage of
> KVM_SET_USER_MEMORY_REGION.
> 
> Thus, option (3).

OK, thank you for patience explaining this.

> Probably a better question to answer is why provide the ABI through
> /dev/sgx and not /dev/kvm.  IMO /dev/sgx is a more logical way to
> advertise support to userspace, e.g. userspace can simply check if
> /dev/sgx (or /dev/sgx/epc) exists vs. probing a KVM capability.

You have to understand that for a KVM non-expert like me it was really
important to get the context, which you kindly gave. I have never used
KVM's memory management API but now that I know how it works all of this
makes perfect sense. This is not a better question but it is definitely
a good follow up question :-)

I don't really understand you deduction here, however. If SGX was not
supported, why couldn't the hypothetical /dev/kvm functionality just
return an error?

For me it sounds a bit messy that KVM functionality, which is a client
to the SGX functionality, places some of its functionality to the SGX
core.

/Jarkko

^ permalink raw reply	[flat|nested] 155+ messages in thread

end of thread, other threads:[~2018-12-22  0:02 UTC | newest]

Thread overview: 155+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20181116010412.23967-1-jarkko.sakkinen@linux.intel.com>
2018-11-16  1:01 ` [PATCH v17 01/23] x86/sgx: Update MAINTAINERS Jarkko Sakkinen
2018-11-16 14:22   ` Borislav Petkov
2018-11-16 15:07     ` Jarkko Sakkinen
2018-11-16 20:24       ` Borislav Petkov
2018-11-18  8:20         ` Jarkko Sakkinen
2018-11-16  1:01 ` [PATCH v17 02/23] x86/cpufeatures: Add Intel-defined SGX feature bit Jarkko Sakkinen
2018-11-16 14:28   ` Borislav Petkov
2018-11-16 15:13     ` Jarkko Sakkinen
2018-11-16 15:18       ` Jarkko Sakkinen
2018-11-16 20:53         ` Borislav Petkov
2018-11-16  1:01 ` [PATCH v17 03/23] x86/cpufeatures: Add SGX sub-features (as Linux-defined bits) Jarkko Sakkinen
2018-11-16 14:37   ` Borislav Petkov
2018-11-16 15:38     ` Sean Christopherson
2018-11-16 23:31   ` Dave Hansen
2018-11-18  8:36     ` Jarkko Sakkinen
2018-11-16  1:01 ` [PATCH v17 04/23] x86/msr: Add IA32_FEATURE_CONTROL.SGX_ENABLE definition Jarkko Sakkinen
2018-11-16  1:01 ` [PATCH v17 05/23] x86/cpufeatures: Add Intel-defined SGX_LC feature bit Jarkko Sakkinen
2018-11-16  1:01 ` [PATCH v17 06/23] x86/cpu/intel: Detect SGX support and update caps appropriately Jarkko Sakkinen
2018-11-16 23:32   ` Dave Hansen
2018-11-18  8:37     ` Jarkko Sakkinen
2018-11-21 18:17   ` Borislav Petkov
2018-11-24 13:54     ` Jarkko Sakkinen
2018-11-16  1:01 ` [PATCH v17 07/23] x86/mm: x86/sgx: Add new 'PF_SGX' page fault error code bit Jarkko Sakkinen
2018-11-16 23:33   ` Dave Hansen
2018-11-18  8:38     ` Jarkko Sakkinen
2018-11-16  1:01 ` [PATCH v17 08/23] x86/mm: x86/sgx: Signal SIGSEGV for userspace #PFs w/ PF_SGX Jarkko Sakkinen
2018-11-16  1:01 ` [PATCH v17 09/23] x86/sgx: Define SGX1 and SGX2 ENCLS leafs Jarkko Sakkinen
2018-11-16  1:01 ` [PATCH v17 10/23] x86/sgx: Add ENCLS architectural error codes Jarkko Sakkinen
2018-11-16  1:01 ` [PATCH v17 11/23] x86/sgx: Add SGX1 and SGX2 architectural data structures Jarkko Sakkinen
2018-11-16  1:01 ` [PATCH v17 12/23] x86/sgx: Add definitions for SGX's CPUID leaf and variable sub-leafs Jarkko Sakkinen
2018-11-16  1:01 ` [PATCH v17 13/23] x86/msr: Add SGX Launch Control MSR definitions Jarkko Sakkinen
2018-11-16 17:29   ` Sean Christopherson
2018-11-18  8:19     ` Jarkko Sakkinen
2018-11-16  1:01 ` [PATCH v17 14/23] x86/sgx: Add wrappers for ENCLS leaf functions Jarkko Sakkinen
2018-11-16  1:01 ` [PATCH v17 15/23] x86/sgx: Enumerate and track EPC sections Jarkko Sakkinen
2018-11-16  1:01 ` [PATCH v17 16/23] x86/sgx: Add functions to allocate and free EPC pages Jarkko Sakkinen
2018-11-16  1:01 ` [PATCH v17 17/23] x86/sgx: Add sgx_einit() for initializing enclaves Jarkko Sakkinen
2018-11-16  1:01 ` [PATCH v17 18/23] platform/x86: Intel SGX driver Jarkko Sakkinen
2018-11-16  1:37   ` Randy Dunlap
2018-11-16 11:23     ` Jarkko Sakkinen
2018-11-19 15:06   ` Jarkko Sakkinen
2018-11-19 16:22     ` Jethro Beekman
2018-11-19 17:19       ` Jarkko Sakkinen
2018-11-19 18:18         ` Andy Lutomirski
2018-11-20 11:00           ` Jarkko Sakkinen
2018-11-19 15:29   ` Andy Lutomirski
2018-11-19 16:19     ` Jarkko Sakkinen
2018-11-19 16:59       ` Andy Lutomirski
2018-11-20 12:04         ` Jarkko Sakkinen
2018-11-22 11:12           ` Dr. Greg
2018-11-22 15:21             ` Andy Lutomirski
2018-11-24 17:21               ` Jarkko Sakkinen
2018-11-24 20:13                 ` Dr. Greg
2018-11-26 21:15                   ` Jarkko Sakkinen
2018-11-25 14:53                 ` Jarkko Sakkinen
2018-11-25 16:22                   ` Andy Lutomirski
2018-11-25 18:55                     ` Dr. Greg
2018-11-25 23:51                       ` Jarkko Sakkinen
     [not found]                       ` <D45BC005-5064-4C75-B486-4E43C454E2F6@amacapital.net>
2018-11-26  0:37                         ` Andy Lutomirski
2018-11-26 11:00                           ` Dr. Greg
2018-11-26 18:22                             ` Andy Lutomirski
2018-11-26 22:16                             ` Jarkko Sakkinen
2018-11-26 21:51                     ` Jarkko Sakkinen
2018-11-26 23:04                       ` Jarkko Sakkinen
2018-11-27  8:55                         ` Dr. Greg
2018-11-27 16:41                           ` Jarkko Sakkinen
2018-11-27 17:55                             ` Andy Lutomirski
2018-11-28 10:49                               ` Dr. Greg
2018-11-28 19:22                                 ` Jarkko Sakkinen
2018-12-10 10:49                                   ` Dr. Greg
2018-12-12 18:00                                     ` Jarkko Sakkinen
2018-12-14 23:59                                       ` Dr. Greg
2018-12-15  0:06                                         ` Sean Christopherson
2018-12-15 23:22                                           ` Dr. Greg
2018-12-17 14:27                                             ` Sean Christopherson
2018-12-17 13:28                                           ` Jarkko Sakkinen
2018-12-17 13:39                                             ` Jarkko Sakkinen
2018-12-17 14:08                                               ` Jarkko Sakkinen
2018-12-17 14:13                                                 ` Jarkko Sakkinen
2018-12-17 16:34                                                   ` Dr. Greg
2018-12-17 17:31                                                 ` Sean Christopherson
2018-12-17 17:49                                                   ` Jarkko Sakkinen
2018-12-17 18:09                                                     ` Sean Christopherson
2018-12-17 18:23                                                       ` Jarkko Sakkinen
2018-12-17 18:46                                                         ` Sean Christopherson
2018-12-17 19:36                                                           ` Jarkko Sakkinen
2018-11-27 16:46                           ` Jarkko Sakkinen
2018-11-28 21:52                           ` Andy Lutomirski
2018-11-22 20:56             ` Andy Lutomirski
2018-11-23 10:39               ` Dr. Greg
2018-11-24 16:45                 ` Jarkko Sakkinen
2018-11-28  5:08                   ` Jarkko Sakkinen
2018-12-09 17:01         ` Pavel Machek
2018-11-20 11:15     ` Dr. Greg
2018-11-24 16:15       ` Jarkko Sakkinen
2018-11-24 19:24         ` Dr. Greg
2018-11-26 19:39           ` Jarkko Sakkinen
2018-12-09 17:01     ` Pavel Machek
2018-12-10 14:46       ` Dr. Greg
2018-12-17 17:45   ` Dave Hansen
2018-12-17 18:01     ` Jarkko Sakkinen
2018-12-17 18:07       ` Dave Hansen
2018-12-17 18:31         ` Jarkko Sakkinen
2018-12-17 18:36       ` Sean Christopherson
2018-12-17 18:43         ` Jarkko Sakkinen
2018-12-17 18:47           ` Dave Hansen
2018-12-17 19:12             ` Andy Lutomirski
2018-12-17 19:17               ` Dave Hansen
2018-12-17 19:25                 ` Andy Lutomirski
2018-12-17 19:54                   ` Jarkko Sakkinen
2018-12-17 19:49                 ` Jarkko Sakkinen
2018-12-17 19:53                   ` Dave Hansen
2018-12-17 19:55                     ` Andy Lutomirski
2018-12-17 20:03                       ` Dave Hansen
2018-12-17 20:10                         ` Andy Lutomirski
2018-12-17 20:15                           ` Dave Hansen
2018-12-17 22:36                             ` Sean Christopherson
2018-12-18  1:40                           ` Jarkko Sakkinen
2018-12-17 22:20               ` Sean Christopherson
2018-12-18  1:39                 ` Jarkko Sakkinen
2018-12-18  3:27                   ` Jarkko Sakkinen
2018-12-18  5:02                     ` Andy Lutomirski
2018-12-18 13:27                       ` Jarkko Sakkinen
2018-12-18  4:55                   ` Andy Lutomirski
2018-12-18 13:18                     ` Jarkko Sakkinen
2018-12-18  4:59                 ` Andy Lutomirski
2018-12-18 13:11                   ` Jarkko Sakkinen
2018-12-18 15:44                   ` Sean Christopherson
2018-12-18 18:53                     ` Sean Christopherson
2018-12-19  5:00                       ` Jarkko Sakkinen
2018-12-19  5:13                         ` Jarkko Sakkinen
2018-12-21 18:28                         ` Sean Christopherson
2018-12-22  0:01                           ` Jarkko Sakkinen
2018-12-19  4:47                     ` Jarkko Sakkinen
2018-12-19  5:24                       ` Jarkko Sakkinen
2018-12-18  1:17               ` Jarkko Sakkinen
2018-12-18  1:31                 ` Jarkko Sakkinen
2018-12-17 18:48           ` Sean Christopherson
2018-12-17 19:09             ` Dave Hansen
2018-12-17 19:37               ` Jarkko Sakkinen
2018-12-17 19:40                 ` Dave Hansen
2018-12-17 19:33             ` Jarkko Sakkinen
2018-12-17 20:21               ` Jarkko Sakkinen
2018-12-18 13:13                 ` Jarkko Sakkinen
2018-12-18 15:46                   ` Sean Christopherson
2018-12-18  5:55   ` Andy Lutomirski
2018-12-19  5:22     ` Jarkko Sakkinen
2018-11-16  1:01 ` [PATCH v17 19/23] platform/x86: sgx: Add swapping functionality to the " Jarkko Sakkinen
2018-11-16  1:01 ` [PATCH v17 20/23] x86/sgx: Add a simple swapper for the EPC memory manager Jarkko Sakkinen
2018-11-16  1:01 ` [PATCH v17 21/23] platform/x86: ptrace() support for the SGX driver Jarkko Sakkinen
2018-11-16  1:01 ` [PATCH v17 22/23] x86/sgx: SGX documentation Jarkko Sakkinen
2018-12-03  3:28   ` Randy Dunlap
2018-12-03  9:32     ` Jarkko Sakkinen
2018-11-16  1:01 ` [PATCH v17 23/23] selftests/x86: Add a selftest for SGX Jarkko Sakkinen
2018-11-16 11:17 ` [PATCH v17 00/23] Intel SGX1 support Jarkko Sakkinen

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).