diff options
| -rw-r--r-- | arch/x86/include/asm/uprobes.h | 3 | ||||
| -rw-r--r-- | arch/x86/kernel/uprobes.c | 19 |
2 files changed, 14 insertions, 8 deletions
diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h index cee58624cb30..d561ff5a3d4d 100644 --- a/arch/x86/include/asm/uprobes.h +++ b/arch/x86/include/asm/uprobes.h | |||
| @@ -46,8 +46,7 @@ struct arch_uprobe_task { | |||
| 46 | #ifdef CONFIG_X86_64 | 46 | #ifdef CONFIG_X86_64 |
| 47 | unsigned long saved_scratch_register; | 47 | unsigned long saved_scratch_register; |
| 48 | #endif | 48 | #endif |
| 49 | #define UPROBE_CLEAR_TF (1 << 0) | 49 | unsigned int saved_tf; |
| 50 | unsigned int restore_flags; | ||
| 51 | }; | 50 | }; |
| 52 | 51 | ||
| 53 | extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr); | 52 | extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr); |
diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c index 3b4aae68efe0..7e993d1f1992 100644 --- a/arch/x86/kernel/uprobes.c +++ b/arch/x86/kernel/uprobes.c | |||
| @@ -653,7 +653,7 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) | |||
| 653 | * Skip these instructions as per the currently known x86 ISA. | 653 | * Skip these instructions as per the currently known x86 ISA. |
| 654 | * 0x66* { 0x90 | 0x0f 0x1f | 0x0f 0x19 | 0x87 0xc0 } | 654 | * 0x66* { 0x90 | 0x0f 0x1f | 0x0f 0x19 | 0x87 0xc0 } |
| 655 | */ | 655 | */ |
| 656 | bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) | 656 | static bool __skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) |
| 657 | { | 657 | { |
| 658 | int i; | 658 | int i; |
| 659 | 659 | ||
| @@ -681,16 +681,21 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) | |||
| 681 | return false; | 681 | return false; |
| 682 | } | 682 | } |
| 683 | 683 | ||
| 684 | bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) | ||
| 685 | { | ||
| 686 | bool ret = __skip_sstep(auprobe, regs); | ||
| 687 | if (ret && (regs->flags & X86_EFLAGS_TF)) | ||
| 688 | send_sig(SIGTRAP, current, 0); | ||
| 689 | return ret; | ||
| 690 | } | ||
| 691 | |||
| 684 | void arch_uprobe_enable_step(struct arch_uprobe *auprobe) | 692 | void arch_uprobe_enable_step(struct arch_uprobe *auprobe) |
| 685 | { | 693 | { |
| 686 | struct task_struct *task = current; | 694 | struct task_struct *task = current; |
| 687 | struct arch_uprobe_task *autask = &task->utask->autask; | 695 | struct arch_uprobe_task *autask = &task->utask->autask; |
| 688 | struct pt_regs *regs = task_pt_regs(task); | 696 | struct pt_regs *regs = task_pt_regs(task); |
| 689 | 697 | ||
| 690 | autask->restore_flags = 0; | 698 | autask->saved_tf = !!(regs->flags & X86_EFLAGS_TF); |
| 691 | if (!(regs->flags & X86_EFLAGS_TF) && | ||
| 692 | !(auprobe->fixups & UPROBE_FIX_SETF)) | ||
| 693 | autask->restore_flags |= UPROBE_CLEAR_TF; | ||
| 694 | 699 | ||
| 695 | regs->flags |= X86_EFLAGS_TF; | 700 | regs->flags |= X86_EFLAGS_TF; |
| 696 | if (test_tsk_thread_flag(task, TIF_BLOCKSTEP)) | 701 | if (test_tsk_thread_flag(task, TIF_BLOCKSTEP)) |
| @@ -707,6 +712,8 @@ void arch_uprobe_disable_step(struct arch_uprobe *auprobe) | |||
| 707 | * SIGTRAP if we do not clear TF. We need to examine the opcode to | 712 | * SIGTRAP if we do not clear TF. We need to examine the opcode to |
| 708 | * make it right. | 713 | * make it right. |
| 709 | */ | 714 | */ |
| 710 | if (autask->restore_flags & UPROBE_CLEAR_TF) | 715 | if (autask->saved_tf) |
| 716 | send_sig(SIGTRAP, task, 0); | ||
| 717 | else if (!(auprobe->fixups & UPROBE_FIX_SETF)) | ||
| 711 | regs->flags &= ~X86_EFLAGS_TF; | 718 | regs->flags &= ~X86_EFLAGS_TF; |
| 712 | } | 719 | } |
