aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/ptrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/ptrace.c')
-rw-r--r--arch/i386/kernel/ptrace.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
index 18642f05dde1..3196ba50fcd5 100644
--- a/arch/i386/kernel/ptrace.c
+++ b/arch/i386/kernel/ptrace.c
@@ -547,11 +547,17 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
547 wake_up_process(child); 547 wake_up_process(child);
548 break; 548 break;
549 549
550 case PTRACE_SYSEMU_SINGLESTEP: /* Same as SYSEMU, but singlestep if not syscall */
550 case PTRACE_SINGLESTEP: /* set the trap flag. */ 551 case PTRACE_SINGLESTEP: /* set the trap flag. */
551 ret = -EIO; 552 ret = -EIO;
552 if (!valid_signal(data)) 553 if (!valid_signal(data))
553 break; 554 break;
554 clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); 555
556 if (request == PTRACE_SYSEMU_SINGLESTEP)
557 set_tsk_thread_flag(child, TIF_SYSCALL_EMU);
558 else
559 clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
560
555 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); 561 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
556 set_singlestep(child); 562 set_singlestep(child);
557 child->exit_code = data; 563 child->exit_code = data;
@@ -686,7 +692,10 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code)
686__attribute__((regparm(3))) 692__attribute__((regparm(3)))
687int do_syscall_trace(struct pt_regs *regs, int entryexit) 693int do_syscall_trace(struct pt_regs *regs, int entryexit)
688{ 694{
689 int is_sysemu, is_singlestep, ret = 0; 695 int is_sysemu = test_thread_flag(TIF_SYSCALL_EMU), ret = 0;
696 /* With TIF_SYSCALL_EMU set we want to ignore TIF_SINGLESTEP */
697 int is_singlestep = !is_sysemu && test_thread_flag(TIF_SINGLESTEP);
698
690 /* do the secure computing check first */ 699 /* do the secure computing check first */
691 secure_computing(regs->orig_eax); 700 secure_computing(regs->orig_eax);
692 701
@@ -696,8 +705,11 @@ int do_syscall_trace(struct pt_regs *regs, int entryexit)
696 if (!(current->ptrace & PT_PTRACED)) 705 if (!(current->ptrace & PT_PTRACED))
697 goto out; 706 goto out;
698 707
699 is_sysemu = test_thread_flag(TIF_SYSCALL_EMU); 708 /* If a process stops on the 1st tracepoint with SYSCALL_TRACE
700 is_singlestep = test_thread_flag(TIF_SINGLESTEP); 709 * and then is resumed with SYSEMU_SINGLESTEP, it will come in
710 * here. We have to check this and return */
711 if (is_sysemu && entryexit)
712 return 0;
701 713
702 /* Fake a debug trap */ 714 /* Fake a debug trap */
703 if (is_singlestep) 715 if (is_singlestep)
@@ -728,6 +740,7 @@ int do_syscall_trace(struct pt_regs *regs, int entryexit)
728 if (ret == 0) 740 if (ret == 0)
729 return 0; 741 return 0;
730 742
743 regs->orig_eax = -1; /* force skip of syscall restarting */
731 if (unlikely(current->audit_context)) 744 if (unlikely(current->audit_context))
732 audit_syscall_exit(current, AUDITSC_RESULT(regs->eax), regs->eax); 745 audit_syscall_exit(current, AUDITSC_RESULT(regs->eax), regs->eax);
733 return 1; 746 return 1;