|
@@ -223,27 +223,41 @@ static unsigned long
|
|
|
__recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr)
|
|
|
{
|
|
|
struct kprobe *kp;
|
|
|
+ unsigned long faddr;
|
|
|
|
|
|
kp = get_kprobe((void *)addr);
|
|
|
- /* There is no probe, return original address */
|
|
|
- if (!kp)
|
|
|
+ faddr = ftrace_location(addr);
|
|
|
+ /*
|
|
|
+ * Use the current code if it is not modified by Kprobe
|
|
|
+ * and it cannot be modified by ftrace.
|
|
|
+ */
|
|
|
+ if (!kp && !faddr)
|
|
|
return addr;
|
|
|
|
|
|
/*
|
|
|
- * Basically, kp->ainsn.insn has an original instruction.
|
|
|
- * However, RIP-relative instruction can not do single-stepping
|
|
|
- * at different place, __copy_instruction() tweaks the displacement of
|
|
|
- * that instruction. In that case, we can't recover the instruction
|
|
|
- * from the kp->ainsn.insn.
|
|
|
+ * Basically, kp->ainsn.insn has an original instruction.
|
|
|
+ * However, RIP-relative instruction can not do single-stepping
|
|
|
+ * at different place, __copy_instruction() 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.
|
|
|
+ * On the other hand, in case on normal Kprobe, 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.
|
|
|
+ *
|
|
|
+ * In case of Kprobes using ftrace, we do not have a copy of
|
|
|
+ * the original instruction. In fact, the ftrace location might
|
|
|
+ * be modified at anytime and even could be in an inconsistent state.
|
|
|
+ * Fortunately, we know that the original code is the ideal 5-byte
|
|
|
+ * long NOP.
|
|
|
*/
|
|
|
- memcpy(buf, kp->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
|
|
|
- buf[0] = kp->opcode;
|
|
|
+ memcpy(buf, (void *)addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
|
|
|
+ if (faddr)
|
|
|
+ memcpy(buf, ideal_nops[NOP_ATOMIC5], 5);
|
|
|
+ else
|
|
|
+ buf[0] = kp->opcode;
|
|
|
return (unsigned long)buf;
|
|
|
}
|
|
|
|