On Wed, 05 Mar 2014 20:59:39 +0900 Masami Hiramatsu <masami.hiramatsu...@hitachi.com> wrote:
> To avoid a kernel crash by probing on lockdep code, call > kprobe_int3_handler and kprobe_debug_handler directly > from do_int3 and do_debug. Since there is a locking code > in notify_die, lockdep code can be invoked. And because > the lockdep involves printk() related things, theoretically, > we need to prohibit probing on much more code... > > Anyway, most of the int3 handlers in the kernel are already > called from do_int3 directly, e.g. ftrace_int3_handler, > poke_int3_handler, kgdb_ll_trap. Actually only > kprobe_exceptions_notify is on the notifier_call_chain. > > Signed-off-by: Masami Hiramatsu <masami.hiramatsu...@hitachi.com> > Cc: Thomas Gleixner <t...@linutronix.de> > Cc: Ingo Molnar <mi...@redhat.com> > Cc: "H. Peter Anvin" <h...@zytor.com> > Cc: Ananth N Mavinakayanahalli <ana...@in.ibm.com> > Cc: Andi Kleen <a...@linux.intel.com> > Cc: Steven Rostedt <rost...@goodmis.org> > Cc: Sasha Levin <sasha.le...@oracle.com> > Cc: Andrew Morton <a...@linux-foundation.org> > Cc: Seiji Aguchi <seiji.agu...@hds.com> > Cc: Frederic Weisbecker <fweis...@gmail.com> > --- > arch/x86/include/asm/kprobes.h | 2 ++ > arch/x86/kernel/kprobes/core.c | 24 +++--------------------- > arch/x86/kernel/traps.c | 10 ++++++++++ > 3 files changed, 15 insertions(+), 21 deletions(-) > > diff --git a/arch/x86/include/asm/kprobes.h b/arch/x86/include/asm/kprobes.h > index 9454c16..53cdfb2 100644 > --- a/arch/x86/include/asm/kprobes.h > +++ b/arch/x86/include/asm/kprobes.h > @@ -116,4 +116,6 @@ struct kprobe_ctlblk { > extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr); > extern int kprobe_exceptions_notify(struct notifier_block *self, > unsigned long val, void *data); > +extern int kprobe_int3_handler(struct pt_regs *regs); > +extern int kprobe_debug_handler(struct pt_regs *regs); > #endif /* _ASM_X86_KPROBES_H */ > diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c > index 4708d6e..566958e 100644 > --- a/arch/x86/kernel/kprobes/core.c > +++ b/arch/x86/kernel/kprobes/core.c > @@ -559,7 +559,7 @@ reenter_kprobe(struct kprobe *p, struct pt_regs *regs, > struct kprobe_ctlblk *kcb > * Interrupts are disabled on entry as trap3 is an interrupt gate and they > * remain disabled throughout this function. > */ > -static int __kprobes kprobe_handler(struct pt_regs *regs) > +int __kprobes kprobe_int3_handler(struct pt_regs *regs) > { > kprobe_opcode_t *addr; > struct kprobe *p; > @@ -857,7 +857,7 @@ no_change: > * Interrupts are disabled on entry as trap1 is an interrupt gate and they > * remain disabled throughout this function. > */ > -static int __kprobes post_kprobe_handler(struct pt_regs *regs) > +int __kprobes kprobe_debug_handler(struct pt_regs *regs) > { > struct kprobe *cur = kprobe_running(); > struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); > @@ -960,22 +960,7 @@ kprobe_exceptions_notify(struct notifier_block *self, > unsigned long val, void *d > if (args->regs && user_mode_vm(args->regs)) > return ret; > > - switch (val) { > - case DIE_INT3: > - if (kprobe_handler(args->regs)) > - ret = NOTIFY_STOP; > - break; > - case DIE_DEBUG: > - if (post_kprobe_handler(args->regs)) { > - /* > - * Reset the BS bit in dr6 (pointed by args->err) to > - * denote completion of processing > - */ > - (*(unsigned long *)ERR_PTR(args->err)) &= ~DR_STEP; > - ret = NOTIFY_STOP; > - } The DIE_DEBUG case is removed but not added anyplace else. The change log doesn't say why this was removed. -- Steve > - break; > - case DIE_GPF: > + if (val == DIE_GPF) { > /* > * To be potentially processing a kprobe fault and to > * trust the result from kprobe_running(), we have > @@ -984,9 +969,6 @@ kprobe_exceptions_notify(struct notifier_block *self, > unsigned long val, void *d > if (!preemptible() && kprobe_running() && > kprobe_fault_handler(args->regs, args->trapnr)) > ret = NOTIFY_STOP; > - break; > - default: > - break; > } > return ret; > } > diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c > index 57409f6..e5d4a70 100644 > --- a/arch/x86/kernel/traps.c > +++ b/arch/x86/kernel/traps.c > @@ -334,6 +334,11 @@ dotraplinkage void __kprobes notrace do_int3(struct > pt_regs *regs, long error_co > goto exit; > #endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */ > > +#ifdef CONFIG_KPROBES > + if (kprobe_int3_handler(regs)) > + return; > +#endif > + > if (notify_die(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP, > SIGTRAP) == NOTIFY_STOP) > goto exit; > @@ -440,6 +445,11 @@ dotraplinkage void __kprobes do_debug(struct pt_regs > *regs, long error_code) > /* Store the virtualized DR6 value */ > tsk->thread.debugreg6 = dr6; > > +#ifdef CONFIG_KPROBES > + if (kprobe_debug_handler(regs)) > + goto exit; > +#endif > + > if (notify_die(DIE_DEBUG, "debug", regs, (long)&dr6, error_code, > SIGTRAP) == NOTIFY_STOP) > goto exit; > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/