diff options
| -rw-r--r-- | arch/x86/kernel/kprobes/core.c | 42 |
1 files changed, 28 insertions, 14 deletions
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c index 6a1146ea4d4d..c3b4b46b4797 100644 --- a/arch/x86/kernel/kprobes/core.c +++ b/arch/x86/kernel/kprobes/core.c | |||
| @@ -223,27 +223,41 @@ static unsigned long | |||
| 223 | __recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr) | 223 | __recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr) |
| 224 | { | 224 | { |
| 225 | struct kprobe *kp; | 225 | struct kprobe *kp; |
| 226 | unsigned long faddr; | ||
| 226 | 227 | ||
| 227 | kp = get_kprobe((void *)addr); | 228 | kp = get_kprobe((void *)addr); |
| 228 | /* There is no probe, return original address */ | 229 | faddr = ftrace_location(addr); |
| 229 | if (!kp) | 230 | /* |
| 231 | * Use the current code if it is not modified by Kprobe | ||
| 232 | * and it cannot be modified by ftrace. | ||
| 233 | */ | ||
| 234 | if (!kp && !faddr) | ||
| 230 | return addr; | 235 | return addr; |
| 231 | 236 | ||
| 232 | /* | 237 | /* |
| 233 | * Basically, kp->ainsn.insn has an original instruction. | 238 | * Basically, kp->ainsn.insn has an original instruction. |
| 234 | * However, RIP-relative instruction can not do single-stepping | 239 | * However, RIP-relative instruction can not do single-stepping |
| 235 | * at different place, __copy_instruction() tweaks the displacement of | 240 | * at different place, __copy_instruction() tweaks the displacement of |
| 236 | * that instruction. In that case, we can't recover the instruction | 241 | * that instruction. In that case, we can't recover the instruction |
| 237 | * from the kp->ainsn.insn. | 242 | * from the kp->ainsn.insn. |
| 238 | * | 243 | * |
| 239 | * On the other hand, kp->opcode has a copy of the first byte of | 244 | * On the other hand, in case on normal Kprobe, kp->opcode has a copy |
| 240 | * the probed instruction, which is overwritten by int3. And | 245 | * of the first byte of the probed instruction, which is overwritten |
| 241 | * the instruction at kp->addr is not modified by kprobes except | 246 | * by int3. And the instruction at kp->addr is not modified by kprobes |
| 242 | * for the first byte, we can recover the original instruction | 247 | * except for the first byte, we can recover the original instruction |
| 243 | * from it and kp->opcode. | 248 | * from it and kp->opcode. |
| 249 | * | ||
| 250 | * In case of Kprobes using ftrace, we do not have a copy of | ||
| 251 | * the original instruction. In fact, the ftrace location might | ||
| 252 | * be modified at anytime and even could be in an inconsistent state. | ||
| 253 | * Fortunately, we know that the original code is the ideal 5-byte | ||
| 254 | * long NOP. | ||
| 244 | */ | 255 | */ |
| 245 | memcpy(buf, kp->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); | 256 | memcpy(buf, (void *)addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); |
| 246 | buf[0] = kp->opcode; | 257 | if (faddr) |
| 258 | memcpy(buf, ideal_nops[NOP_ATOMIC5], 5); | ||
| 259 | else | ||
| 260 | buf[0] = kp->opcode; | ||
| 247 | return (unsigned long)buf; | 261 | return (unsigned long)buf; |
| 248 | } | 262 | } |
| 249 | 263 | ||
