aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/kernel/kprobes.c8
-rw-r--r--arch/arm/kernel/traps.c12
-rw-r--r--include/asm-arm/kprobes.h7
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
209static int kprobe_trap_handler(struct pt_regs *regs, unsigned int instr) 203int 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
56void arch_remove_kprobe(struct kprobe *); 62void arch_remove_kprobe(struct kprobe *);
57 63
64int kprobe_trap_handler(struct pt_regs *regs, unsigned int instr);
58int kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr); 65int kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr);
59int kprobe_exceptions_notify(struct notifier_block *self, 66int kprobe_exceptions_notify(struct notifier_block *self,
60 unsigned long val, void *data); 67 unsigned long val, void *data);