Message ID | 20200915112842.897265-4-jarkko.sakkinen@linux.intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Intel SGX foundations | expand |
On Tue, Sep 15, 2020 at 02:28:21PM +0300, Jarkko Sakkinen wrote: > From: Sean Christopherson <sean.j.christopherson@intel.com> > > Include SGX bit to the PF error codes and throw SIGSEGV with PF_SGX when > a #PF with SGX set happens. > > CPU throws a #PF with the SGX set in the event of Enclave Page Cache Map > (EPCM) conflict. The EPCM is a CPU-internal table, which describes the > properties for a enclave page. Enclaves are measured and signed software > entities, which SGX hosts. [1] > > Although the primary purpose of the EPCM conflict checks is to prevent > malicious accesses to an enclave, an illegit access can happen also for > legit reasons. > > All SGX reserved memory, including EPCM is encrypted with a transient key > that does not survive from the power transition. Throwing a SIGSEGV allows > user space software to react when this happens (e.g. recreate the enclave, > which was invalidated). > > [1] Intel SDM: 36.5.1 Enclave Page Cache Map (EPCM) > > Acked-by: Jethro Beekman <jethro@fortanix.com> > Reviewed-by: Darren Kenny <darren.kenny@oracle.com> > Reviewed-by: Borislav Petkov <bp@suse.de> > 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 | 14 ++++++++------ The SEV-ES patchset moved that to arch/x86/include/asm/trap_pf.h but fixing that up is real easy. Simply do this search-replace s!arch/x86/include/asm/traps.h!arch/x86/include/asm/trap_pf.h! on this patch.
On Wed, Sep 16, 2020 at 01:44:48PM +0200, Borislav Petkov wrote: > On Tue, Sep 15, 2020 at 02:28:21PM +0300, Jarkko Sakkinen wrote: > > From: Sean Christopherson <sean.j.christopherson@intel.com> > > > > Include SGX bit to the PF error codes and throw SIGSEGV with PF_SGX when > > a #PF with SGX set happens. > > > > CPU throws a #PF with the SGX set in the event of Enclave Page Cache Map > > (EPCM) conflict. The EPCM is a CPU-internal table, which describes the > > properties for a enclave page. Enclaves are measured and signed software > > entities, which SGX hosts. [1] > > > > Although the primary purpose of the EPCM conflict checks is to prevent > > malicious accesses to an enclave, an illegit access can happen also for > > legit reasons. > > > > All SGX reserved memory, including EPCM is encrypted with a transient key > > that does not survive from the power transition. Throwing a SIGSEGV allows > > user space software to react when this happens (e.g. recreate the enclave, > > which was invalidated). > > > > [1] Intel SDM: 36.5.1 Enclave Page Cache Map (EPCM) > > > > Acked-by: Jethro Beekman <jethro@fortanix.com> > > Reviewed-by: Darren Kenny <darren.kenny@oracle.com> > > Reviewed-by: Borislav Petkov <bp@suse.de> > > 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 | 14 ++++++++------ > > The SEV-ES patchset moved that to arch/x86/include/asm/trap_pf.h but > fixing that up is real easy. Simply do this search-replace > > s!arch/x86/include/asm/traps.h!arch/x86/include/asm/trap_pf.h! > > on this patch. Hey, I just did git fetch mainline && git rebase mainline/master Zero conflicts and there is no trap_pf.h yet. So this is not yet in Linus' tree? /Jarkko
On Wed, Sep 16, 2020 at 11:30:08PM +0300, Jarkko Sakkinen wrote: > Zero conflicts and there is no trap_pf.h yet. So this is not yet in > Linus' tree? tip tree: https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git/log/?h=x86/seves
diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h index 714b1a30e7b0..4446f95ad997 100644 --- a/arch/x86/include/asm/traps.h +++ b/arch/x86/include/asm/traps.h @@ -44,12 +44,13 @@ void __noreturn handle_stack_overflow(const char *message, /* * Page fault error code bits: * - * bit 0 == 0: no page found 1: protection fault - * bit 1 == 0: read access 1: write access - * bit 2 == 0: kernel-mode access 1: user-mode access - * bit 3 == 1: use of reserved bit detected - * bit 4 == 1: fault was an instruction fetch - * bit 5 == 1: protection keys block access + * bit 0 == 0: no page found 1: protection fault + * bit 1 == 0: read access 1: write access + * bit 2 == 0: kernel-mode access 1: user-mode access + * bit 3 == 1: use of reserved bit detected + * bit 4 == 1: fault was an instruction fetch + * bit 5 == 1: protection keys block access + * bit 15 == 1: inside SGX enclave */ enum x86_pf_error_code { X86_PF_PROT = 1 << 0, @@ -58,5 +59,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 */ diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 35f1498e9832..1a7cc6d3281a 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -1054,6 +1054,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 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