@@ -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 */
@@ -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