aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/uprobes.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/uprobes.c')
-rw-r--r--arch/x86/kernel/uprobes.c19
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 */
656bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) 656static 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
684bool 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
684void arch_uprobe_enable_step(struct arch_uprobe *auprobe) 692void 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}