copy_optimized_instructions() copies whole instructions until it covers the five-byte jump. Pass the iterator's kprobe to instruction recovery at each instruction start, avoiding a separate lookup. Other __copy_instruction() callers retain the lookup behavior by passing NULL. Signed-off-by: Jiri Olsa --- arch/x86/kernel/kprobes/common.h | 3 ++- arch/x86/kernel/kprobes/core.c | 6 +++--- arch/x86/kernel/kprobes/opt.c | 9 +++++++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/kprobes/common.h b/arch/x86/kernel/kprobes/common.h index 062746e20c35..c04d01fe075a 100644 --- a/arch/x86/kernel/kprobes/common.h +++ b/arch/x86/kernel/kprobes/common.h @@ -86,7 +86,8 @@ extern unsigned long recover_probed_instruction(kprobe_opcode_t *buf, * Copy an instruction and adjust the displacement if the instruction * uses the %rip-relative addressing mode. */ -extern int __copy_instruction(u8 *dest, u8 *src, u8 *real, struct insn *insn); +extern int __copy_instruction(u8 *dest, u8 *src, u8 *real, struct insn *insn, + struct kprobe **kp); /* Generate a relative-jump/call instruction */ extern void synthesize_reljump(void *dest, void *from, void *to); diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c index 4d63826f6c04..ae6611fdb19a 100644 --- a/arch/x86/kernel/kprobes/core.c +++ b/arch/x86/kernel/kprobes/core.c @@ -395,10 +395,10 @@ kprobe_opcode_t *arch_adjust_kprobe_addr(unsigned long addr, unsigned long offse * instruction, displacement must be adjust by @real, not @dest. * This returns the length of copied instruction, or 0 if it has an error. */ -int __copy_instruction(u8 *dest, u8 *src, u8 *real, struct insn *insn) +int __copy_instruction(u8 *dest, u8 *src, u8 *real, struct insn *insn, struct kprobe **kp) { kprobe_opcode_t buf[MAX_INSN_SIZE]; - unsigned long recovered_insn = recover_probed_instruction(buf, (unsigned long)src, NULL); + unsigned long recovered_insn = recover_probed_instruction(buf, (unsigned long)src, kp); int ret; if (!recovered_insn || !insn) @@ -735,7 +735,7 @@ static int arch_copy_kprobe(struct kprobe *p) int ret, len; /* Copy an instruction with recovering if other optprobe modifies it.*/ - len = __copy_instruction(buf, p->addr, p->ainsn.insn, &insn); + len = __copy_instruction(buf, p->addr, p->ainsn.insn, &insn, NULL); if (!len) return -EINVAL; diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c index 9f0af24155ba..058b32564ea0 100644 --- a/arch/x86/kernel/kprobes/opt.c +++ b/arch/x86/kernel/kprobes/opt.c @@ -201,14 +201,19 @@ NOKPROBE_SYMBOL(optimized_callback); static int copy_optimized_instructions(u8 *dest, u8 *src, u8 *real) { + struct kprobe_iter iter; + unsigned long addr; + struct kprobe *kp; struct insn insn; int len = 0, ret; - while (len < JMP32_INSN_SIZE) { - ret = __copy_instruction(dest + len, src + len, real + len, &insn); + addr = (unsigned long)src; + for_each_addr_kprobe(iter, kp, addr, (unsigned long)src + JMP32_INSN_SIZE - 1) { + ret = __copy_instruction(dest + len, src + len, real + len, &insn, &kp); if (!ret || !can_boost(&insn, src + len)) return -EINVAL; len += ret; + addr += ret; } /* Check whether the address range is reserved */ if (ftrace_text_reserved(src, src + len - 1) || -- 2.43.0