aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mm/fault.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/mm/fault.c')
-rw-r--r--arch/x86/mm/fault.c54
1 files changed, 39 insertions, 15 deletions
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 6dea040cc3a1..8e5722992677 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -584,8 +584,13 @@ show_fault_oops(struct pt_regs *regs, unsigned long error_code,
584 584
585 if (error_code & PF_INSTR) { 585 if (error_code & PF_INSTR) {
586 unsigned int level; 586 unsigned int level;
587 pgd_t *pgd;
588 pte_t *pte;
587 589
588 pte_t *pte = lookup_address(address, &level); 590 pgd = __va(read_cr3() & PHYSICAL_PAGE_MASK);
591 pgd += pgd_index(address);
592
593 pte = lookup_address_in_pgd(pgd, address, &level);
589 594
590 if (pte && pte_present(*pte) && !pte_exec(*pte)) 595 if (pte && pte_present(*pte) && !pte_exec(*pte))
591 printk(nx_warning, from_kuid(&init_user_ns, current_uid())); 596 printk(nx_warning, from_kuid(&init_user_ns, current_uid()));
@@ -1020,13 +1025,17 @@ static inline bool smap_violation(int error_code, struct pt_regs *regs)
1020 * This routine handles page faults. It determines the address, 1025 * This routine handles page faults. It determines the address,
1021 * and the problem, and then passes it off to one of the appropriate 1026 * and the problem, and then passes it off to one of the appropriate
1022 * routines. 1027 * routines.
1028 *
1029 * This function must have noinline because both callers
1030 * {,trace_}do_page_fault() have notrace on. Having this an actual function
1031 * guarantees there's a function trace entry.
1023 */ 1032 */
1024static void __kprobes 1033static void __kprobes noinline
1025__do_page_fault(struct pt_regs *regs, unsigned long error_code) 1034__do_page_fault(struct pt_regs *regs, unsigned long error_code,
1035 unsigned long address)
1026{ 1036{
1027 struct vm_area_struct *vma; 1037 struct vm_area_struct *vma;
1028 struct task_struct *tsk; 1038 struct task_struct *tsk;
1029 unsigned long address;
1030 struct mm_struct *mm; 1039 struct mm_struct *mm;
1031 int fault; 1040 int fault;
1032 unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; 1041 unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
@@ -1034,9 +1043,6 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code)
1034 tsk = current; 1043 tsk = current;
1035 mm = tsk->mm; 1044 mm = tsk->mm;
1036 1045
1037 /* Get the faulting address: */
1038 address = read_cr2();
1039
1040 /* 1046 /*
1041 * Detect and handle instructions that would cause a page fault for 1047 * Detect and handle instructions that would cause a page fault for
1042 * both a tracked kernel page and a userspace page. 1048 * both a tracked kernel page and a userspace page.
@@ -1248,32 +1254,50 @@ good_area:
1248 up_read(&mm->mmap_sem); 1254 up_read(&mm->mmap_sem);
1249} 1255}
1250 1256
1251dotraplinkage void __kprobes 1257dotraplinkage void __kprobes notrace
1252do_page_fault(struct pt_regs *regs, unsigned long error_code) 1258do_page_fault(struct pt_regs *regs, unsigned long error_code)
1253{ 1259{
1260 unsigned long address = read_cr2(); /* Get the faulting address */
1254 enum ctx_state prev_state; 1261 enum ctx_state prev_state;
1255 1262
1263 /*
1264 * We must have this function tagged with __kprobes, notrace and call
1265 * read_cr2() before calling anything else. To avoid calling any kind
1266 * of tracing machinery before we've observed the CR2 value.
1267 *
1268 * exception_{enter,exit}() contain all sorts of tracepoints.
1269 */
1270
1256 prev_state = exception_enter(); 1271 prev_state = exception_enter();
1257 __do_page_fault(regs, error_code); 1272 __do_page_fault(regs, error_code, address);
1258 exception_exit(prev_state); 1273 exception_exit(prev_state);
1259} 1274}
1260 1275
1261static void trace_page_fault_entries(struct pt_regs *regs, 1276#ifdef CONFIG_TRACING
1277static void trace_page_fault_entries(unsigned long address, struct pt_regs *regs,
1262 unsigned long error_code) 1278 unsigned long error_code)
1263{ 1279{
1264 if (user_mode(regs)) 1280 if (user_mode(regs))
1265 trace_page_fault_user(read_cr2(), regs, error_code); 1281 trace_page_fault_user(address, regs, error_code);
1266 else 1282 else
1267 trace_page_fault_kernel(read_cr2(), regs, error_code); 1283 trace_page_fault_kernel(address, regs, error_code);
1268} 1284}
1269 1285
1270dotraplinkage void __kprobes 1286dotraplinkage void __kprobes notrace
1271trace_do_page_fault(struct pt_regs *regs, unsigned long error_code) 1287trace_do_page_fault(struct pt_regs *regs, unsigned long error_code)
1272{ 1288{
1289 /*
1290 * The exception_enter and tracepoint processing could
1291 * trigger another page faults (user space callchain
1292 * reading) and destroy the original cr2 value, so read
1293 * the faulting address now.
1294 */
1295 unsigned long address = read_cr2();
1273 enum ctx_state prev_state; 1296 enum ctx_state prev_state;
1274 1297
1275 prev_state = exception_enter(); 1298 prev_state = exception_enter();
1276 trace_page_fault_entries(regs, error_code); 1299 trace_page_fault_entries(address, regs, error_code);
1277 __do_page_fault(regs, error_code); 1300 __do_page_fault(regs, error_code, address);
1278 exception_exit(prev_state); 1301 exception_exit(prev_state);
1279} 1302}
1303#endif /* CONFIG_TRACING */