diff options
Diffstat (limited to 'arch/x86_64/mm/fault.c')
-rw-r--r-- | arch/x86_64/mm/fault.c | 47 |
1 files changed, 42 insertions, 5 deletions
diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c index 55250593d8c9..08dc696f54ee 100644 --- a/arch/x86_64/mm/fault.c +++ b/arch/x86_64/mm/fault.c | |||
@@ -41,6 +41,41 @@ | |||
41 | #define PF_RSVD (1<<3) | 41 | #define PF_RSVD (1<<3) |
42 | #define PF_INSTR (1<<4) | 42 | #define PF_INSTR (1<<4) |
43 | 43 | ||
44 | #ifdef CONFIG_KPROBES | ||
45 | ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); | ||
46 | |||
47 | /* Hook to register for page fault notifications */ | ||
48 | int register_page_fault_notifier(struct notifier_block *nb) | ||
49 | { | ||
50 | vmalloc_sync_all(); | ||
51 | return atomic_notifier_chain_register(¬ify_page_fault_chain, nb); | ||
52 | } | ||
53 | |||
54 | int unregister_page_fault_notifier(struct notifier_block *nb) | ||
55 | { | ||
56 | return atomic_notifier_chain_unregister(¬ify_page_fault_chain, nb); | ||
57 | } | ||
58 | |||
59 | static inline int notify_page_fault(enum die_val val, const char *str, | ||
60 | struct pt_regs *regs, long err, int trap, int sig) | ||
61 | { | ||
62 | struct die_args args = { | ||
63 | .regs = regs, | ||
64 | .str = str, | ||
65 | .err = err, | ||
66 | .trapnr = trap, | ||
67 | .signr = sig | ||
68 | }; | ||
69 | return atomic_notifier_call_chain(¬ify_page_fault_chain, val, &args); | ||
70 | } | ||
71 | #else | ||
72 | static inline int notify_page_fault(enum die_val val, const char *str, | ||
73 | struct pt_regs *regs, long err, int trap, int sig) | ||
74 | { | ||
75 | return NOTIFY_DONE; | ||
76 | } | ||
77 | #endif | ||
78 | |||
44 | void bust_spinlocks(int yes) | 79 | void bust_spinlocks(int yes) |
45 | { | 80 | { |
46 | int loglevel_save = console_loglevel; | 81 | int loglevel_save = console_loglevel; |
@@ -160,7 +195,7 @@ void dump_pagetable(unsigned long address) | |||
160 | printk("PGD %lx ", pgd_val(*pgd)); | 195 | printk("PGD %lx ", pgd_val(*pgd)); |
161 | if (!pgd_present(*pgd)) goto ret; | 196 | if (!pgd_present(*pgd)) goto ret; |
162 | 197 | ||
163 | pud = __pud_offset_k((pud_t *)pgd_page(*pgd), address); | 198 | pud = pud_offset(pgd, address); |
164 | if (bad_address(pud)) goto bad; | 199 | if (bad_address(pud)) goto bad; |
165 | printk("PUD %lx ", pud_val(*pud)); | 200 | printk("PUD %lx ", pud_val(*pud)); |
166 | if (!pud_present(*pud)) goto ret; | 201 | if (!pud_present(*pud)) goto ret; |
@@ -348,7 +383,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, | |||
348 | if (vmalloc_fault(address) >= 0) | 383 | if (vmalloc_fault(address) >= 0) |
349 | return; | 384 | return; |
350 | } | 385 | } |
351 | if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, | 386 | if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, |
352 | SIGSEGV) == NOTIFY_STOP) | 387 | SIGSEGV) == NOTIFY_STOP) |
353 | return; | 388 | return; |
354 | /* | 389 | /* |
@@ -358,7 +393,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, | |||
358 | goto bad_area_nosemaphore; | 393 | goto bad_area_nosemaphore; |
359 | } | 394 | } |
360 | 395 | ||
361 | if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, | 396 | if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, |
362 | SIGSEGV) == NOTIFY_STOP) | 397 | SIGSEGV) == NOTIFY_STOP) |
363 | return; | 398 | return; |
364 | 399 | ||
@@ -410,8 +445,10 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, | |||
410 | if (!(vma->vm_flags & VM_GROWSDOWN)) | 445 | if (!(vma->vm_flags & VM_GROWSDOWN)) |
411 | goto bad_area; | 446 | goto bad_area; |
412 | if (error_code & 4) { | 447 | if (error_code & 4) { |
413 | // XXX: align red zone size with ABI | 448 | /* Allow userspace just enough access below the stack pointer |
414 | if (address + 128 < regs->rsp) | 449 | * to let the 'enter' instruction work. |
450 | */ | ||
451 | if (address + 65536 + 32 * sizeof(unsigned long) < regs->rsp) | ||
415 | goto bad_area; | 452 | goto bad_area; |
416 | } | 453 | } |
417 | if (expand_stack(vma, address)) | 454 | if (expand_stack(vma, address)) |