On Thu, Aug 13, 2009 at 04:34:28PM -0400, Masami Hiramatsu wrote: > Ensure safeness of inserting kprobes by checking whether the specified > address is at the first byte of a instruction on x86. > This is done by decoding probed function from its head to the probe point. > > Signed-off-by: Masami Hiramatsu <mhiramat@xxxxxxxxxx> > Acked-by: Ananth N Mavinakayanahalli <ananth@xxxxxxxxxx> > Cc: Avi Kivity <avi@xxxxxxxxxx> > Cc: Andi Kleen <ak@xxxxxxxxxxxxxxx> > Cc: Christoph Hellwig <hch@xxxxxxxxxxxxx> > Cc: Frank Ch. Eigler <fche@xxxxxxxxxx> > Cc: Frederic Weisbecker <fweisbec@xxxxxxxxx> > Cc: H. Peter Anvin <hpa@xxxxxxxxx> > Cc: Ingo Molnar <mingo@xxxxxxx> > Cc: Jason Baron <jbaron@xxxxxxxxxx> > Cc: Jim Keniston <jkenisto@xxxxxxxxxx> > Cc: K.Prasad <prasad@xxxxxxxxxxxxxxxxxx> > Cc: Lai Jiangshan <laijs@xxxxxxxxxxxxxx> > Cc: Li Zefan <lizf@xxxxxxxxxxxxxx> > Cc: Przemysław Pawełczyk <przemyslaw@xxxxxxxxxxxx> > Cc: Roland McGrath <roland@xxxxxxxxxx> > Cc: Sam Ravnborg <sam@xxxxxxxxxxxx> > Cc: Srikar Dronamraju <srikar@xxxxxxxxxxxxxxxxxx> > Cc: Steven Rostedt <rostedt@xxxxxxxxxxx> > Cc: Tom Zanussi <tzanussi@xxxxxxxxx> > Cc: Vegard Nossum <vegard.nossum@xxxxxxxxx> > --- > > arch/x86/kernel/kprobes.c | 69 +++++++++++++++++++++++++++++++++++++++++++++ > 1 files changed, 69 insertions(+), 0 deletions(-) > > diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c > index b5b1848..80d493f 100644 > --- a/arch/x86/kernel/kprobes.c > +++ b/arch/x86/kernel/kprobes.c > @@ -48,6 +48,7 @@ > #include <linux/preempt.h> > #include <linux/module.h> > #include <linux/kdebug.h> > +#include <linux/kallsyms.h> > > #include <asm/cacheflush.h> > #include <asm/desc.h> > @@ -55,6 +56,7 @@ > #include <asm/uaccess.h> > #include <asm/alternative.h> > #include <asm/debugreg.h> > +#include <asm/insn.h> > > void jprobe_return_end(void); > > @@ -245,6 +247,71 @@ retry: > } > } > > +/* Recover the probed instruction at addr for further analysis. */ > +static int recover_probed_instruction(kprobe_opcode_t *buf, unsigned long addr) > +{ > + struct kprobe *kp; > + kp = get_kprobe((void *)addr); > + if (!kp) > + return -EINVAL; > + > + /* > + * Basically, kp->ainsn.insn has an original instruction. > + * However, RIP-relative instruction can not do single-stepping > + * at different place, fix_riprel() tweaks the displacement of > + * that instruction. In that case, we can't recover the instruction > + * from the kp->ainsn.insn. > + * > + * On the other hand, kp->opcode has a copy of the first byte of > + * the probed instruction, which is overwritten by int3. And > + * the instruction at kp->addr is not modified by kprobes except > + * for the first byte, we can recover the original instruction > + * from it and kp->opcode. > + */ > + memcpy(buf, kp->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); > + buf[0] = kp->opcode; > + return 0; > +} > + > +/* Dummy buffers for kallsyms_lookup */ > +static char __dummy_buf[KSYM_NAME_LEN]; > + > +/* Check if paddr is at an instruction boundary */ > +static int __kprobes can_probe(unsigned long paddr) > +{ > + int ret; > + unsigned long addr, offset = 0; > + struct insn insn; > + kprobe_opcode_t buf[MAX_INSN_SIZE]; > + > + if (!kallsyms_lookup(paddr, NULL, &offset, NULL, __dummy_buf)) > + return 0; > + > + /* Decode instructions */ > + addr = paddr - offset; > + while (addr < paddr) { > + kernel_insn_init(&insn, (void *)addr); > + insn_get_opcode(&insn); > + > + /* Check if the instruction has been modified. */ > + if (insn.opcode.bytes[0] == BREAKPOINT_INSTRUCTION) { > + ret = recover_probed_instruction(buf, addr); I'm confused about the reason of this recovering. Is it to remove kprobes behind the current setting one in the current function? If such cleanup is needed for whatever reason, I wonder what happens to the corresponding kprobe structure, why isn't it using the arch_disarm_ helper to patch back? (Questions that may prove my solid misunderstanding of the kprobes code ;-) Frederic. -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html