aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/kprobes/core.c42
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