Commit 5ac07564 authored by Masami Hiramatsu's avatar Masami Hiramatsu Committed by Greg Kroah-Hartman

kprobes/x86: Do not modify singlestep buffer while resuming

commit 804dec5b upstream.

Do not modify singlestep execution buffer (kprobe.ainsn.insn)
while resuming from single-stepping, instead, modifies
the buffer to add a jump back instruction at preparing
buffer.
Signed-off-by: default avatarMasami Hiramatsu <mhiramat@kernel.org>
Cc: Ananth N Mavinakayanahalli <ananth@linux.vnet.ibm.com>
Cc: Andrey Ryabinin <aryabinin@virtuozzo.com>
Cc: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: David S . Miller <davem@davemloft.net>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ye Xiaolong <xiaolong.ye@intel.com>
Link: http://lkml.kernel.org/r/149076361560.22469.1610155860343077495.stgit@devboxSigned-off-by: default avatarIngo Molnar <mingo@kernel.org>
Reviewed-by: default avatar"Steven Rostedt (VMware)" <rostedt@goodmis.org>
Signed-off-by: default avatarAlexey Makhalov <amakhalov@vmware.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 21e9341e
...@@ -411,25 +411,38 @@ void free_insn_page(void *page) ...@@ -411,25 +411,38 @@ void free_insn_page(void *page)
module_memfree(page); module_memfree(page);
} }
/* Prepare reljump right after instruction to boost */
static void prepare_boost(struct kprobe *p, int length)
{
if (can_boost(p->ainsn.insn, p->addr) &&
MAX_INSN_SIZE - length >= RELATIVEJUMP_SIZE) {
/*
* These instructions can be executed directly if it
* jumps back to correct address.
*/
synthesize_reljump(p->ainsn.insn + length, p->addr + length);
p->ainsn.boostable = 1;
} else {
p->ainsn.boostable = -1;
}
}
static int arch_copy_kprobe(struct kprobe *p) static int arch_copy_kprobe(struct kprobe *p)
{ {
int ret; int len;
set_memory_rw((unsigned long)p->ainsn.insn & PAGE_MASK, 1); set_memory_rw((unsigned long)p->ainsn.insn & PAGE_MASK, 1);
/* Copy an instruction with recovering if other optprobe modifies it.*/ /* Copy an instruction with recovering if other optprobe modifies it.*/
ret = __copy_instruction(p->ainsn.insn, p->addr); len = __copy_instruction(p->ainsn.insn, p->addr);
if (!ret) if (!len)
return -EINVAL; return -EINVAL;
/* /*
* __copy_instruction can modify the displacement of the instruction, * __copy_instruction can modify the displacement of the instruction,
* but it doesn't affect boostable check. * but it doesn't affect boostable check.
*/ */
if (can_boost(p->ainsn.insn, p->addr)) prepare_boost(p, len);
p->ainsn.boostable = 0;
else
p->ainsn.boostable = -1;
set_memory_ro((unsigned long)p->ainsn.insn & PAGE_MASK, 1); set_memory_ro((unsigned long)p->ainsn.insn & PAGE_MASK, 1);
...@@ -894,21 +907,6 @@ static void resume_execution(struct kprobe *p, struct pt_regs *regs, ...@@ -894,21 +907,6 @@ static void resume_execution(struct kprobe *p, struct pt_regs *regs,
break; break;
} }
if (p->ainsn.boostable == 0) {
if ((regs->ip > copy_ip) &&
(regs->ip - copy_ip) + 5 < MAX_INSN_SIZE) {
/*
* These instructions can be executed directly if it
* jumps back to correct address.
*/
synthesize_reljump((void *)regs->ip,
(void *)orig_ip + (regs->ip - copy_ip));
p->ainsn.boostable = 1;
} else {
p->ainsn.boostable = -1;
}
}
regs->ip += orig_ip - copy_ip; regs->ip += orig_ip - copy_ip;
no_change: no_change:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment