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); |
