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 | ||