aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/kernel/signal.c4
-rw-r--r--arch/powerpc/kernel/uprobes.c6
-rw-r--r--arch/x86/kernel/uprobes.c54
3 files changed, 26 insertions, 38 deletions
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c
index a2dc75793bd5..3b997118df50 100644
--- a/arch/powerpc/kernel/signal.c
+++ b/arch/powerpc/kernel/signal.c
@@ -158,10 +158,8 @@ static int do_signal(struct pt_regs *regs)
158 158
159void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) 159void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
160{ 160{
161 if (thread_info_flags & _TIF_UPROBE) { 161 if (thread_info_flags & _TIF_UPROBE)
162 clear_thread_flag(TIF_UPROBE);
163 uprobe_notify_resume(regs); 162 uprobe_notify_resume(regs);
164 }
165 163
166 if (thread_info_flags & _TIF_SIGPENDING) 164 if (thread_info_flags & _TIF_SIGPENDING)
167 do_signal(regs); 165 do_signal(regs);
diff --git a/arch/powerpc/kernel/uprobes.c b/arch/powerpc/kernel/uprobes.c
index d2d46d1014f8..bc77834dbf43 100644
--- a/arch/powerpc/kernel/uprobes.c
+++ b/arch/powerpc/kernel/uprobes.c
@@ -64,6 +64,8 @@ int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
64 autask->saved_trap_nr = current->thread.trap_nr; 64 autask->saved_trap_nr = current->thread.trap_nr;
65 current->thread.trap_nr = UPROBE_TRAP_NR; 65 current->thread.trap_nr = UPROBE_TRAP_NR;
66 regs->nip = current->utask->xol_vaddr; 66 regs->nip = current->utask->xol_vaddr;
67
68 user_enable_single_step(current);
67 return 0; 69 return 0;
68} 70}
69 71
@@ -119,6 +121,8 @@ int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
119 * to be executed. 121 * to be executed.
120 */ 122 */
121 regs->nip = utask->vaddr + MAX_UINSN_BYTES; 123 regs->nip = utask->vaddr + MAX_UINSN_BYTES;
124
125 user_disable_single_step(current);
122 return 0; 126 return 0;
123} 127}
124 128
@@ -162,6 +166,8 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
162 166
163 current->thread.trap_nr = utask->autask.saved_trap_nr; 167 current->thread.trap_nr = utask->autask.saved_trap_nr;
164 instruction_pointer_set(regs, utask->vaddr); 168 instruction_pointer_set(regs, utask->vaddr);
169
170 user_disable_single_step(current);
165} 171}
166 172
167/* 173/*
diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c
index aafa5557b396..c71025b67462 100644
--- a/arch/x86/kernel/uprobes.c
+++ b/arch/x86/kernel/uprobes.c
@@ -478,6 +478,11 @@ int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
478 regs->ip = current->utask->xol_vaddr; 478 regs->ip = current->utask->xol_vaddr;
479 pre_xol_rip_insn(auprobe, regs, autask); 479 pre_xol_rip_insn(auprobe, regs, autask);
480 480
481 autask->saved_tf = !!(regs->flags & X86_EFLAGS_TF);
482 regs->flags |= X86_EFLAGS_TF;
483 if (test_tsk_thread_flag(current, TIF_BLOCKSTEP))
484 set_task_blockstep(current, false);
485
481 return 0; 486 return 0;
482} 487}
483 488
@@ -603,6 +608,16 @@ int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
603 if (auprobe->fixups & UPROBE_FIX_CALL) 608 if (auprobe->fixups & UPROBE_FIX_CALL)
604 result = adjust_ret_addr(regs->sp, correction); 609 result = adjust_ret_addr(regs->sp, correction);
605 610
611 /*
612 * arch_uprobe_pre_xol() doesn't save the state of TIF_BLOCKSTEP
613 * so we can get an extra SIGTRAP if we do not clear TF. We need
614 * to examine the opcode to make it right.
615 */
616 if (utask->autask.saved_tf)
617 send_sig(SIGTRAP, current, 0);
618 else if (!(auprobe->fixups & UPROBE_FIX_SETF))
619 regs->flags &= ~X86_EFLAGS_TF;
620
606 return result; 621 return result;
607} 622}
608 623
@@ -647,6 +662,10 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
647 current->thread.trap_nr = utask->autask.saved_trap_nr; 662 current->thread.trap_nr = utask->autask.saved_trap_nr;
648 handle_riprel_post_xol(auprobe, regs, NULL); 663 handle_riprel_post_xol(auprobe, regs, NULL);
649 instruction_pointer_set(regs, utask->vaddr); 664 instruction_pointer_set(regs, utask->vaddr);
665
666 /* clear TF if it was set by us in arch_uprobe_pre_xol() */
667 if (!utask->autask.saved_tf)
668 regs->flags &= ~X86_EFLAGS_TF;
650} 669}
651 670
652/* 671/*
@@ -676,38 +695,3 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
676 send_sig(SIGTRAP, current, 0); 695 send_sig(SIGTRAP, current, 0);
677 return ret; 696 return ret;
678} 697}
679
680void arch_uprobe_enable_step(struct arch_uprobe *auprobe)
681{
682 struct task_struct *task = current;
683 struct arch_uprobe_task *autask = &task->utask->autask;
684 struct pt_regs *regs = task_pt_regs(task);
685
686 autask->saved_tf = !!(regs->flags & X86_EFLAGS_TF);
687
688 regs->flags |= X86_EFLAGS_TF;
689 if (test_tsk_thread_flag(task, TIF_BLOCKSTEP))
690 set_task_blockstep(task, false);
691}
692
693void arch_uprobe_disable_step(struct arch_uprobe *auprobe)
694{
695 struct task_struct *task = current;
696 struct arch_uprobe_task *autask = &task->utask->autask;
697 bool trapped = (task->utask->state == UTASK_SSTEP_TRAPPED);
698 struct pt_regs *regs = task_pt_regs(task);
699 /*
700 * The state of TIF_BLOCKSTEP was not saved so we can get an extra
701 * SIGTRAP if we do not clear TF. We need to examine the opcode to
702 * make it right.
703 */
704 if (unlikely(trapped)) {
705 if (!autask->saved_tf)
706 regs->flags &= ~X86_EFLAGS_TF;
707 } else {
708 if (autask->saved_tf)
709 send_sig(SIGTRAP, task, 0);
710 else if (!(auprobe->fixups & UPROBE_FIX_SETF))
711 regs->flags &= ~X86_EFLAGS_TF;
712 }
713}