aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/kernel/uprobes.c27
1 files changed, 11 insertions, 16 deletions
diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c
index 5bcce852628a..d2792e884d54 100644
--- a/arch/x86/kernel/uprobes.c
+++ b/arch/x86/kernel/uprobes.c
@@ -424,10 +424,9 @@ static int default_post_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs
424 long correction = (long)(utask->vaddr - utask->xol_vaddr); 424 long correction = (long)(utask->vaddr - utask->xol_vaddr);
425 425
426 handle_riprel_post_xol(auprobe, regs, &correction); 426 handle_riprel_post_xol(auprobe, regs, &correction);
427 if (auprobe->def.fixups & UPROBE_FIX_IP) 427 if (auprobe->def.fixups & UPROBE_FIX_IP) {
428 regs->ip += correction; 428 regs->ip += correction;
429 429 } else if (auprobe->def.fixups & UPROBE_FIX_CALL) {
430 if (auprobe->def.fixups & UPROBE_FIX_CALL) {
431 regs->sp += sizeof_long(); 430 regs->sp += sizeof_long();
432 if (push_ret_address(regs, utask->vaddr + auprobe->def.ilen)) 431 if (push_ret_address(regs, utask->vaddr + auprobe->def.ilen))
433 return -ERESTART; 432 return -ERESTART;
@@ -623,7 +622,7 @@ static int branch_setup_xol_ops(struct arch_uprobe *auprobe, struct insn *insn)
623int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long addr) 622int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long addr)
624{ 623{
625 struct insn insn; 624 struct insn insn;
626 bool fix_ip = true, fix_call = false; 625 u8 fix_ip_or_call = UPROBE_FIX_IP;
627 int ret; 626 int ret;
628 627
629 ret = uprobe_init_insn(auprobe, &insn, is_64bit_mm(mm)); 628 ret = uprobe_init_insn(auprobe, &insn, is_64bit_mm(mm));
@@ -647,21 +646,20 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm,
647 case 0xcb: 646 case 0xcb:
648 case 0xc2: 647 case 0xc2:
649 case 0xca: 648 case 0xca:
650 fix_ip = false; 649 case 0xea: /* jmp absolute -- ip is correct */
650 fix_ip_or_call = 0;
651 break; 651 break;
652 case 0x9a: /* call absolute - Fix return addr, not ip */ 652 case 0x9a: /* call absolute - Fix return addr, not ip */
653 fix_call = true; 653 fix_ip_or_call = UPROBE_FIX_CALL;
654 fix_ip = false;
655 break;
656 case 0xea: /* jmp absolute -- ip is correct */
657 fix_ip = false;
658 break; 654 break;
659 case 0xff: 655 case 0xff:
660 switch (MODRM_REG(&insn)) { 656 switch (MODRM_REG(&insn)) {
661 case 2: case 3: /* call or lcall, indirect */ 657 case 2: case 3: /* call or lcall, indirect */
662 fix_call = true; 658 fix_ip_or_call = UPROBE_FIX_CALL;
659 break;
663 case 4: case 5: /* jmp or ljmp, indirect */ 660 case 4: case 5: /* jmp or ljmp, indirect */
664 fix_ip = false; 661 fix_ip_or_call = 0;
662 break;
665 } 663 }
666 /* fall through */ 664 /* fall through */
667 default: 665 default:
@@ -669,10 +667,7 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm,
669 } 667 }
670 668
671 auprobe->def.ilen = insn.length; 669 auprobe->def.ilen = insn.length;
672 if (fix_ip) 670 auprobe->def.fixups |= fix_ip_or_call;
673 auprobe->def.fixups |= UPROBE_FIX_IP;
674 if (fix_call)
675 auprobe->def.fixups |= UPROBE_FIX_CALL;
676 671
677 auprobe->ops = &default_xol_ops; 672 auprobe->ops = &default_xol_ops;
678 return 0; 673 return 0;