diff mbox series

[v19,07/27] x86/mm: x86/sgx: Signal SIGSEGV for userspace #PFs w/ PF_SGX

Message ID 20190317211456.13927-8-jarkko.sakkinen@linux.intel.com (mailing list archive)
State New, archived
Headers show
Series Intel SGX1 support | expand

Commit Message

Jarkko Sakkinen March 17, 2019, 9:14 p.m. UTC
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(+)

Comments

Dave Hansen March 18, 2019, 5:15 p.m. UTC | #1
On 3/17/19 2:14 PM, Jarkko Sakkinen wrote:
> +	/*
> +	 * 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;

A sanitized error_code gets passed up to userspace.  Is that how
userspace figures out that this was a PF_SGX fault instead of something
more routine?
Sean Christopherson March 18, 2019, 7:53 p.m. UTC | #2
On Mon, Mar 18, 2019 at 10:15:18AM -0700, Dave Hansen wrote:
> On 3/17/19 2:14 PM, Jarkko Sakkinen wrote:
> > +	/*
> > +	 * 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;
> 
> A sanitized error_code gets passed up to userspace.  Is that how
> userspace figures out that this was a PF_SGX fault instead of something
> more routine?

Yes.  Technically userspace can survive without PF_SGX, e.g. assume that
SIGSEGV on EENTER itself indicates an EPCM fault, but the explicit flag
does make things easier and cleaner.
diff mbox series

Patch

diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 667f1da36208..78e2807fbede 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -1214,6 +1214,19 @@  access_error(unsigned long error_code, struct vm_area_struct *vma)
 	if (error_code & X86_PF_PK)
 		return 1;
 
+	/*
+	 * Access is blocked by the Enclave Page Cache Map (EPCM), i.e. the
+	 * access is allowed by the PTE but not the EPCM.  This usually happens
+	 * when the EPCM is yanked out from under us, e.g. by hardware after a
+	 * suspend/resume cycle.  In any case, software, i.e. the kernel, can't
+	 * fix the source of the fault as the EPCM can't be directly modified
+	 * by software.  Handle the fault as an access error in order to signal
+	 * userspace, e.g. so that userspace can rebuild their enclave(s), even
+	 * though userspace may not have actually violated access permissions.
+	 */
+	if (unlikely(error_code & X86_PF_SGX))
+		return 1;
+
 	/*
 	 * Make sure to check the VMA so that we do not perform
 	 * faults just to hit a X86_PF_PK as soon as we fill in a