On Thursday, 2020-07-16 at 16:52:42 +03, Jarkko Sakkinen wrote: > From: Sean Christopherson <sean.j.christopherson@xxxxxxxxx> > > 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@xxxxxxxxxxxx> > Signed-off-by: Sean Christopherson <sean.j.christopherson@xxxxxxxxx> > Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@xxxxxxxxxxxxxxx> Reviewed-by: Darren Kenny <darren.kenny@xxxxxxxxxx> > --- > arch/x86/include/asm/traps.h | 14 ++++++++------ > arch/x86/mm/fault.c | 13 +++++++++++++ > 2 files changed, 21 insertions(+), 6 deletions(-) > > 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 1ead568c0101..1db6fbd7af8e 100644 > --- a/arch/x86/mm/fault.c > +++ b/arch/x86/mm/fault.c > @@ -1055,6 +1055,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 > -- > 2.25.1