aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMasami Hiramatsu <mhiramat@kernel.org>2017-03-29 01:00:25 -0400
committerIngo Molnar <mingo@kernel.org>2017-04-12 03:23:45 -0400
commit804dec5bda9b4fcdab5f67fe61db4a0498af5221 (patch)
tree21c03ef2a8d261208348be56333abfb9b9d036ab
parent17880e4d5777df4770081ecf0750471cda57f86b (diff)
kprobes/x86: Do not modify singlestep buffer while resuming
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: Masami 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@devbox Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/kernel/kprobes/core.c42
1 files changed, 20 insertions, 22 deletions
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index 6327f95832a0..a654054eae7e 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -399,23 +399,36 @@ int __copy_instruction(u8 *dest, u8 *src)
399 return length; 399 return length;
400} 400}
401 401
402/* Prepare reljump right after instruction to boost */
403static void prepare_boost(struct kprobe *p, int length)
404{
405 if (can_boost(p->ainsn.insn, p->addr) &&
406 MAX_INSN_SIZE - length >= RELATIVEJUMP_SIZE) {
407 /*
408 * These instructions can be executed directly if it
409 * jumps back to correct address.
410 */
411 synthesize_reljump(p->ainsn.insn + length, p->addr + length);
412 p->ainsn.boostable = 1;
413 } else {
414 p->ainsn.boostable = -1;
415 }
416}
417
402static int arch_copy_kprobe(struct kprobe *p) 418static int arch_copy_kprobe(struct kprobe *p)
403{ 419{
404 int ret; 420 int len;
405 421
406 /* Copy an instruction with recovering if other optprobe modifies it.*/ 422 /* Copy an instruction with recovering if other optprobe modifies it.*/
407 ret = __copy_instruction(p->ainsn.insn, p->addr); 423 len = __copy_instruction(p->ainsn.insn, p->addr);
408 if (!ret) 424 if (!len)
409 return -EINVAL; 425 return -EINVAL;
410 426
411 /* 427 /*
412 * __copy_instruction can modify the displacement of the instruction, 428 * __copy_instruction can modify the displacement of the instruction,
413 * but it doesn't affect boostable check. 429 * but it doesn't affect boostable check.
414 */ 430 */
415 if (can_boost(p->ainsn.insn, p->addr)) 431 prepare_boost(p, len);
416 p->ainsn.boostable = 0;
417 else
418 p->ainsn.boostable = -1;
419 432
420 /* Check whether the instruction modifies Interrupt Flag or not */ 433 /* Check whether the instruction modifies Interrupt Flag or not */
421 p->ainsn.if_modifier = is_IF_modifier(p->ainsn.insn); 434 p->ainsn.if_modifier = is_IF_modifier(p->ainsn.insn);
@@ -878,21 +891,6 @@ static void resume_execution(struct kprobe *p, struct pt_regs *regs,
878 break; 891 break;
879 } 892 }
880 893
881 if (p->ainsn.boostable == 0) {
882 if ((regs->ip > copy_ip) &&
883 (regs->ip - copy_ip) + 5 < MAX_INSN_SIZE) {
884 /*
885 * These instructions can be executed directly if it
886 * jumps back to correct address.
887 */
888 synthesize_reljump((void *)regs->ip,
889 (void *)orig_ip + (regs->ip - copy_ip));
890 p->ainsn.boostable = 1;
891 } else {
892 p->ainsn.boostable = -1;
893 }
894 }
895
896 regs->ip += orig_ip - copy_ip; 894 regs->ip += orig_ip - copy_ip;
897 895
898no_change: 896no_change: