diff options
-rw-r--r-- | arch/arm/kernel/kprobes.c | 8 | ||||
-rw-r--r-- | arch/arm/kernel/traps.c | 12 | ||||
-rw-r--r-- | include/asm-arm/kprobes.h | 7 |
3 files changed, 20 insertions, 7 deletions
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c index 450ee2cbfe17..a22a98c43ca5 100644 --- a/arch/arm/kernel/kprobes.c +++ b/arch/arm/kernel/kprobes.c | |||
@@ -26,12 +26,6 @@ | |||
26 | #include <asm/traps.h> | 26 | #include <asm/traps.h> |
27 | #include <asm/cacheflush.h> | 27 | #include <asm/cacheflush.h> |
28 | 28 | ||
29 | /* | ||
30 | * This undefined instruction must be unique and | ||
31 | * reserved solely for kprobes' use. | ||
32 | */ | ||
33 | #define KPROBE_BREAKPOINT_INSTRUCTION 0xe7f001f8 | ||
34 | |||
35 | #define MIN_STACK_SIZE(addr) \ | 29 | #define MIN_STACK_SIZE(addr) \ |
36 | min((unsigned long)MAX_STACK_SIZE, \ | 30 | min((unsigned long)MAX_STACK_SIZE, \ |
37 | (unsigned long)current_thread_info() + THREAD_START_SP - (addr)) | 31 | (unsigned long)current_thread_info() + THREAD_START_SP - (addr)) |
@@ -206,7 +200,7 @@ void __kprobes kprobe_handler(struct pt_regs *regs) | |||
206 | } | 200 | } |
207 | } | 201 | } |
208 | 202 | ||
209 | static int kprobe_trap_handler(struct pt_regs *regs, unsigned int instr) | 203 | int kprobe_trap_handler(struct pt_regs *regs, unsigned int instr) |
210 | { | 204 | { |
211 | kprobe_handler(regs); | 205 | kprobe_handler(regs); |
212 | return 0; | 206 | return 0; |
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 65bb762b2d80..5595fdd75e82 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/kallsyms.h> | 19 | #include <linux/kallsyms.h> |
20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/kprobes.h> | ||
22 | 23 | ||
23 | #include <asm/atomic.h> | 24 | #include <asm/atomic.h> |
24 | #include <asm/cacheflush.h> | 25 | #include <asm/cacheflush.h> |
@@ -313,6 +314,17 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs) | |||
313 | get_user(instr, (u32 __user *)pc); | 314 | get_user(instr, (u32 __user *)pc); |
314 | } | 315 | } |
315 | 316 | ||
317 | #ifdef CONFIG_KPROBES | ||
318 | /* | ||
319 | * It is possible to have recursive kprobes, so we can't call | ||
320 | * the kprobe trap handler with the undef_lock held. | ||
321 | */ | ||
322 | if (instr == KPROBE_BREAKPOINT_INSTRUCTION && !user_mode(regs)) { | ||
323 | kprobe_trap_handler(regs, instr); | ||
324 | return; | ||
325 | } | ||
326 | #endif | ||
327 | |||
316 | spin_lock_irqsave(&undef_lock, flags); | 328 | spin_lock_irqsave(&undef_lock, flags); |
317 | list_for_each_entry(hook, &undef_hook, node) { | 329 | list_for_each_entry(hook, &undef_hook, node) { |
318 | if ((instr & hook->instr_mask) == hook->instr_val && | 330 | if ((instr & hook->instr_mask) == hook->instr_val && |
diff --git a/include/asm-arm/kprobes.h b/include/asm-arm/kprobes.h index 273f37413ee6..4e7bd32288ae 100644 --- a/include/asm-arm/kprobes.h +++ b/include/asm-arm/kprobes.h | |||
@@ -25,6 +25,12 @@ | |||
25 | #define MAX_INSN_SIZE 2 | 25 | #define MAX_INSN_SIZE 2 |
26 | #define MAX_STACK_SIZE 64 /* 32 would probably be OK */ | 26 | #define MAX_STACK_SIZE 64 /* 32 would probably be OK */ |
27 | 27 | ||
28 | /* | ||
29 | * This undefined instruction must be unique and | ||
30 | * reserved solely for kprobes' use. | ||
31 | */ | ||
32 | #define KPROBE_BREAKPOINT_INSTRUCTION 0xe7f001f8 | ||
33 | |||
28 | #define regs_return_value(regs) ((regs)->ARM_r0) | 34 | #define regs_return_value(regs) ((regs)->ARM_r0) |
29 | #define flush_insn_slot(p) do { } while (0) | 35 | #define flush_insn_slot(p) do { } while (0) |
30 | #define kretprobe_blacklist_size 0 | 36 | #define kretprobe_blacklist_size 0 |
@@ -55,6 +61,7 @@ struct kprobe_ctlblk { | |||
55 | 61 | ||
56 | void arch_remove_kprobe(struct kprobe *); | 62 | void arch_remove_kprobe(struct kprobe *); |
57 | 63 | ||
64 | int kprobe_trap_handler(struct pt_regs *regs, unsigned int instr); | ||
58 | int kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr); | 65 | int kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr); |
59 | int kprobe_exceptions_notify(struct notifier_block *self, | 66 | int kprobe_exceptions_notify(struct notifier_block *self, |
60 | unsigned long val, void *data); | 67 | unsigned long val, void *data); |