diff options
Diffstat (limited to 'arch/x86/kernel/uprobes.c')
-rw-r--r-- | arch/x86/kernel/uprobes.c | 19 |
1 files changed, 13 insertions, 6 deletions
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 | } |