Skip to content

Commit 7969691

Browse files
Nicolas PitreRussell King
authored andcommitted
ARM kprobes: special hook for the kprobes breakpoint handler
The kprobes code is already able to cope with reentrant probes, so its handler must be called outside of the region protected by undef_lock. If ever this lock is released when handlers are called then this commit could be reverted. Signed-off-by: Nicolas Pitre <nico@marvell.com>
1 parent 785d3cd commit 7969691

File tree

3 files changed

+20
-7
lines changed

3 files changed

+20
-7
lines changed

arch/arm/kernel/kprobes.c

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,6 @@
2626
#include <asm/traps.h>
2727
#include <asm/cacheflush.h>
2828

29-
/*
30-
* This undefined instruction must be unique and
31-
* reserved solely for kprobes' use.
32-
*/
33-
#define KPROBE_BREAKPOINT_INSTRUCTION 0xe7f001f8
34-
3529
#define MIN_STACK_SIZE(addr) \
3630
min((unsigned long)MAX_STACK_SIZE, \
3731
(unsigned long)current_thread_info() + THREAD_START_SP - (addr))
@@ -206,7 +200,7 @@ void __kprobes kprobe_handler(struct pt_regs *regs)
206200
}
207201
}
208202

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)
210204
{
211205
kprobe_handler(regs);
212206
return 0;

arch/arm/kernel/traps.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/kallsyms.h>
2020
#include <linux/delay.h>
2121
#include <linux/init.h>
22+
#include <linux/kprobes.h>
2223

2324
#include <asm/atomic.h>
2425
#include <asm/cacheflush.h>
@@ -313,6 +314,17 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
313314
get_user(instr, (u32 __user *)pc);
314315
}
315316

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+
316328
spin_lock_irqsave(&undef_lock, flags);
317329
list_for_each_entry(hook, &undef_hook, node) {
318330
if ((instr & hook->instr_mask) == hook->instr_val &&

include/asm-arm/kprobes.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@
2525
#define MAX_INSN_SIZE 2
2626
#define MAX_STACK_SIZE 64 /* 32 would probably be OK */
2727

28+
/*
29+
* This undefined instruction must be unique and
30+
* reserved solely for kprobes' use.
31+
*/
32+
#define KPROBE_BREAKPOINT_INSTRUCTION 0xe7f001f8
33+
2834
#define regs_return_value(regs) ((regs)->ARM_r0)
2935
#define flush_insn_slot(p) do { } while (0)
3036
#define kretprobe_blacklist_size 0
@@ -55,6 +61,7 @@ struct kprobe_ctlblk {
5561

5662
void arch_remove_kprobe(struct kprobe *);
5763

64+
int kprobe_trap_handler(struct pt_regs *regs, unsigned int instr);
5865
int kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr);
5966
int kprobe_exceptions_notify(struct notifier_block *self,
6067
unsigned long val, void *data);

0 commit comments

Comments
 (0)