tracing/kprobes: Dump the culprit kprobe in case of kprobe recursion
Kprobes can enter into a probing recursion, ie: a kprobe that does an endless loop because one of its core mechanism function used during probing is also probed itself. This patch helps pinpointing the kprobe that raised such recursion by dumping it and raising a BUG instead of a warning (we also disarm the kprobe to try avoiding recursion in BUG itself). Having a BUG instead of a warning stops the stacktrace in the right place and doesn't pollute the logs with hundreds of traces that eventually end up in a stack overflow. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Masami Hiramatsu <mhiramat@redhat.com> Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
This commit is contained in:
parent
30a7e073b5
commit
24851d2447
|
@ -490,9 +490,13 @@ static int __kprobes reenter_kprobe(struct kprobe *p, struct pt_regs *regs,
|
||||||
/* A probe has been hit in the codepath leading up
|
/* A probe has been hit in the codepath leading up
|
||||||
* to, or just after, single-stepping of a probed
|
* to, or just after, single-stepping of a probed
|
||||||
* instruction. This entire codepath should strictly
|
* instruction. This entire codepath should strictly
|
||||||
* reside in .kprobes.text section. Raise a warning
|
* reside in .kprobes.text section.
|
||||||
* to highlight this peculiar case.
|
* Raise a BUG or we'll continue in an endless
|
||||||
|
* reentering loop and eventually a stack overflow.
|
||||||
*/
|
*/
|
||||||
|
arch_disarm_kprobe(p);
|
||||||
|
dump_kprobe(p);
|
||||||
|
BUG();
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
/* impossible cases */
|
/* impossible cases */
|
||||||
|
|
|
@ -296,6 +296,8 @@ void recycle_rp_inst(struct kretprobe_instance *ri, struct hlist_head *head);
|
||||||
int disable_kprobe(struct kprobe *kp);
|
int disable_kprobe(struct kprobe *kp);
|
||||||
int enable_kprobe(struct kprobe *kp);
|
int enable_kprobe(struct kprobe *kp);
|
||||||
|
|
||||||
|
void dump_kprobe(struct kprobe *kp);
|
||||||
|
|
||||||
#else /* !CONFIG_KPROBES: */
|
#else /* !CONFIG_KPROBES: */
|
||||||
|
|
||||||
static inline int kprobes_built_in(void)
|
static inline int kprobes_built_in(void)
|
||||||
|
|
|
@ -1141,6 +1141,13 @@ static void __kprobes kill_kprobe(struct kprobe *p)
|
||||||
arch_remove_kprobe(p);
|
arch_remove_kprobe(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __kprobes dump_kprobe(struct kprobe *kp)
|
||||||
|
{
|
||||||
|
printk(KERN_WARNING "Dumping kprobe:\n");
|
||||||
|
printk(KERN_WARNING "Name: %s\nAddress: %p\nOffset: %x\n",
|
||||||
|
kp->symbol_name, kp->addr, kp->offset);
|
||||||
|
}
|
||||||
|
|
||||||
/* Module notifier call back, checking kprobes on the module */
|
/* Module notifier call back, checking kprobes on the module */
|
||||||
static int __kprobes kprobes_module_callback(struct notifier_block *nb,
|
static int __kprobes kprobes_module_callback(struct notifier_block *nb,
|
||||||
unsigned long val, void *data)
|
unsigned long val, void *data)
|
||||||
|
|
Loading…
Reference in New Issue