diff options
Diffstat (limited to 'arch/x86/mm/fault_32.c')
-rw-r--r-- | arch/x86/mm/fault_32.c | 43 |
1 files changed, 19 insertions, 24 deletions
diff --git a/arch/x86/mm/fault_32.c b/arch/x86/mm/fault_32.c index fcb38e7f3543..be72c2a5b03b 100644 --- a/arch/x86/mm/fault_32.c +++ b/arch/x86/mm/fault_32.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/kprobes.h> | 25 | #include <linux/kprobes.h> |
26 | #include <linux/uaccess.h> | 26 | #include <linux/uaccess.h> |
27 | #include <linux/kdebug.h> | 27 | #include <linux/kdebug.h> |
28 | #include <linux/kprobes.h> | ||
28 | 29 | ||
29 | #include <asm/system.h> | 30 | #include <asm/system.h> |
30 | #include <asm/desc.h> | 31 | #include <asm/desc.h> |
@@ -32,33 +33,27 @@ | |||
32 | 33 | ||
33 | extern void die(const char *,struct pt_regs *,long); | 34 | extern void die(const char *,struct pt_regs *,long); |
34 | 35 | ||
35 | static ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); | 36 | #ifdef CONFIG_KPROBES |
36 | 37 | static inline int notify_page_fault(struct pt_regs *regs) | |
37 | int register_page_fault_notifier(struct notifier_block *nb) | ||
38 | { | 38 | { |
39 | vmalloc_sync_all(); | 39 | int ret = 0; |
40 | return atomic_notifier_chain_register(¬ify_page_fault_chain, nb); | 40 | |
41 | } | 41 | /* kprobe_running() needs smp_processor_id() */ |
42 | EXPORT_SYMBOL_GPL(register_page_fault_notifier); | 42 | if (!user_mode_vm(regs)) { |
43 | preempt_disable(); | ||
44 | if (kprobe_running() && kprobe_fault_handler(regs, 14)) | ||
45 | ret = 1; | ||
46 | preempt_enable(); | ||
47 | } | ||
43 | 48 | ||
44 | int unregister_page_fault_notifier(struct notifier_block *nb) | 49 | return ret; |
45 | { | ||
46 | return atomic_notifier_chain_unregister(¬ify_page_fault_chain, nb); | ||
47 | } | 50 | } |
48 | EXPORT_SYMBOL_GPL(unregister_page_fault_notifier); | 51 | #else |
49 | 52 | static inline int notify_page_fault(struct pt_regs *regs) | |
50 | static inline int notify_page_fault(struct pt_regs *regs, long err) | ||
51 | { | 53 | { |
52 | struct die_args args = { | 54 | return 0; |
53 | .regs = regs, | ||
54 | .str = "page fault", | ||
55 | .err = err, | ||
56 | .trapnr = 14, | ||
57 | .signr = SIGSEGV | ||
58 | }; | ||
59 | return atomic_notifier_call_chain(¬ify_page_fault_chain, | ||
60 | DIE_PAGE_FAULT, &args); | ||
61 | } | 55 | } |
56 | #endif | ||
62 | 57 | ||
63 | /* | 58 | /* |
64 | * Return EIP plus the CS segment base. The segment limit is also | 59 | * Return EIP plus the CS segment base. The segment limit is also |
@@ -331,7 +326,7 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs, | |||
331 | if (unlikely(address >= TASK_SIZE)) { | 326 | if (unlikely(address >= TASK_SIZE)) { |
332 | if (!(error_code & 0x0000000d) && vmalloc_fault(address) >= 0) | 327 | if (!(error_code & 0x0000000d) && vmalloc_fault(address) >= 0) |
333 | return; | 328 | return; |
334 | if (notify_page_fault(regs, error_code) == NOTIFY_STOP) | 329 | if (notify_page_fault(regs)) |
335 | return; | 330 | return; |
336 | /* | 331 | /* |
337 | * Don't take the mm semaphore here. If we fixup a prefetch | 332 | * Don't take the mm semaphore here. If we fixup a prefetch |
@@ -340,7 +335,7 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs, | |||
340 | goto bad_area_nosemaphore; | 335 | goto bad_area_nosemaphore; |
341 | } | 336 | } |
342 | 337 | ||
343 | if (notify_page_fault(regs, error_code) == NOTIFY_STOP) | 338 | if (notify_page_fault(regs)) |
344 | return; | 339 | return; |
345 | 340 | ||
346 | /* It's safe to allow irq's after cr2 has been saved and the vmalloc | 341 | /* It's safe to allow irq's after cr2 has been saved and the vmalloc |