aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/mm/fault.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 76dcd9d8e0bc..f2fb75d46b96 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -995,6 +995,17 @@ static int fault_in_kernel_space(unsigned long address)
995 return address >= TASK_SIZE_MAX; 995 return address >= TASK_SIZE_MAX;
996} 996}
997 997
998static inline bool smap_violation(int error_code, struct pt_regs *regs)
999{
1000 if (error_code & PF_USER)
1001 return false;
1002
1003 if (!user_mode_vm(regs) && (regs->flags & X86_EFLAGS_AC))
1004 return false;
1005
1006 return true;
1007}
1008
998/* 1009/*
999 * This routine handles page faults. It determines the address, 1010 * This routine handles page faults. It determines the address,
1000 * and the problem, and then passes it off to one of the appropriate 1011 * and the problem, and then passes it off to one of the appropriate
@@ -1088,6 +1099,13 @@ do_page_fault(struct pt_regs *regs, unsigned long error_code)
1088 if (unlikely(error_code & PF_RSVD)) 1099 if (unlikely(error_code & PF_RSVD))
1089 pgtable_bad(regs, error_code, address); 1100 pgtable_bad(regs, error_code, address);
1090 1101
1102 if (static_cpu_has(X86_FEATURE_SMAP)) {
1103 if (unlikely(smap_violation(error_code, regs))) {
1104 bad_area_nosemaphore(regs, error_code, address);
1105 return;
1106 }
1107 }
1108
1091 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); 1109 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
1092 1110
1093 /* 1111 /*