
From: Jeff Dike <jdike@addtoit.com>

From: Bodo Stroesser - Set PTRACE_DTRACE and singlestep_syscall correctly. 
Pass out TRACESYSGOOD and make sure the parent gets notified in
ptrace_syscall.

Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/arch/um/kernel/process_kern.c      |    2 --
 25-akpm/arch/um/kernel/ptrace.c            |   24 +++++++++++++++++++-----
 25-akpm/arch/um/kernel/signal_kern.c       |    6 +++---
 25-akpm/arch/um/kernel/skas/syscall_kern.c |    5 -----
 25-akpm/arch/um/kernel/tt/syscall_kern.c   |    5 -----
 5 files changed, 22 insertions(+), 20 deletions(-)

diff -puN arch/um/kernel/process_kern.c~uml-set-dtrace-correctly arch/um/kernel/process_kern.c
--- 25/arch/um/kernel/process_kern.c~uml-set-dtrace-correctly	2004-11-04 20:41:43.588384968 -0800
+++ 25-akpm/arch/um/kernel/process_kern.c	2004-11-04 20:41:43.598383448 -0800
@@ -462,8 +462,6 @@ int singlestepping(void * t)
 	if ( ! (task->ptrace & PT_DTRACE) )
 		return(0);
 
-	task->ptrace &= ~PT_DTRACE;
-
 	if (task->thread.singlestep_syscall)
 		return(0);
 
diff -puN arch/um/kernel/ptrace.c~uml-set-dtrace-correctly arch/um/kernel/ptrace.c
--- 25/arch/um/kernel/ptrace.c~uml-set-dtrace-correctly	2004-11-04 20:41:43.589384816 -0800
+++ 25-akpm/arch/um/kernel/ptrace.c	2004-11-04 20:41:43.598383448 -0800
@@ -22,6 +22,8 @@
  */
 void ptrace_disable(struct task_struct *child)
 { 
+	child->ptrace &= ~PT_DTRACE;
+	child->thread.singlestep_syscall = 0;
 }
 
 int sys_ptrace(long request, long pid, long addr, long data)
@@ -139,6 +141,9 @@ int sys_ptrace(long request, long pid, l
 		ret = -EIO;
 		if ((unsigned long) data > _NSIG)
 			break;
+
+		child->ptrace &= ~PT_DTRACE;
+		child->thread.singlestep_syscall = 0;
 		if (request == PTRACE_SYSCALL) {
 			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 		}
@@ -160,6 +165,9 @@ int sys_ptrace(long request, long pid, l
 		ret = 0;
 		if (child->exit_state == EXIT_ZOMBIE)	/* already dead */
 			break;
+
+		child->ptrace &= ~PT_DTRACE;
+		child->thread.singlestep_syscall = 0;
 		child->exit_code = SIGKILL;
 		wake_up_process(child);
 		break;
@@ -171,6 +179,7 @@ int sys_ptrace(long request, long pid, l
 			break;
 		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 		child->ptrace |= PT_DTRACE;
+		child->thread.singlestep_syscall = 0;
 		child->exit_code = data;
 		/* give it a chance to run. */
 		wake_up_process(child);
@@ -299,6 +308,9 @@ int sys_ptrace(long request, long pid, l
 
 void syscall_trace(union uml_pt_regs *regs, int entryexit)
 {
+	int is_singlestep = (current->ptrace & PT_DTRACE) && entryexit;
+	int tracesysgood;
+
 	if (unlikely(current->audit_context)) {
 		if (!entryexit)
 			audit_syscall_entry(current, regs->orig_eax,
@@ -308,18 +320,20 @@ void syscall_trace(union uml_pt_regs *re
 			audit_syscall_exit(current, regs->eax);
 	}
 
-	if (!test_thread_flag(TIF_SYSCALL_TRACE))
+	if (!test_thread_flag(TIF_SYSCALL_TRACE) && !is_singlestep)
 		return;
 	if (!(current->ptrace & PT_PTRACED))
 		return;
 
 	/* the 0x80 provides a way for the tracing parent to distinguish
 	   between a syscall stop and SIGTRAP delivery */
-	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-				 ? 0x80 : 0));
+	tracesysgood = (current->ptrace & PT_TRACESYSGOOD) && !is_singlestep;
+	ptrace_notify(SIGTRAP | (tracesysgood ? 0x80 : 0));
+
+	/* force do_signal() --> is_syscall() */
+	set_thread_flag(TIF_SIGPENDING);
 
-	/*
-	 * this isn't the same as continuing with a signal, but it will do
+	/* this isn't the same as continuing with a signal, but it will do
 	 * for normal use.  strace only continues with a signal if the
 	 * stopping signal is not SIGTRAP.  -brl
 	 */
diff -puN arch/um/kernel/signal_kern.c~uml-set-dtrace-correctly arch/um/kernel/signal_kern.c
--- 25/arch/um/kernel/signal_kern.c~uml-set-dtrace-correctly	2004-11-04 20:41:43.591384512 -0800
+++ 25-akpm/arch/um/kernel/signal_kern.c	2004-11-04 20:41:43.599383296 -0800
@@ -152,9 +152,9 @@ static int kern_do_signal(struct pt_regs
 	 * on the host.  The tracing thread will check this flag and 
 	 * PTRACE_SYSCALL if necessary.
 	 */
-	if((current->ptrace & PT_DTRACE) && 
-	   is_syscall(PT_REGS_IP(&current->thread.regs)))
-		current->thread.singlestep_syscall = 1;
+	if(current->ptrace & PT_DTRACE)
+		current->thread.singlestep_syscall =
+			is_syscall(PT_REGS_IP(&current->thread.regs));
 	return(0);
 }
 
diff -puN arch/um/kernel/skas/syscall_kern.c~uml-set-dtrace-correctly arch/um/kernel/skas/syscall_kern.c
--- 25/arch/um/kernel/skas/syscall_kern.c~uml-set-dtrace-correctly	2004-11-04 20:41:43.592384360 -0800
+++ 25-akpm/arch/um/kernel/skas/syscall_kern.c	2004-11-04 20:41:43.599383296 -0800
@@ -28,11 +28,6 @@ long execute_syscall_skas(void *r)
 		res = -ENOSYS;
 	else res = EXECUTE_SYSCALL(syscall, regs);
 
-	if(current->thread.singlestep_syscall){
-		current->thread.singlestep_syscall = 0;
-		force_sig(SIGTRAP, current);
-	}
-
 	return(res);
 }
 
diff -puN arch/um/kernel/tt/syscall_kern.c~uml-set-dtrace-correctly arch/um/kernel/tt/syscall_kern.c
--- 25/arch/um/kernel/tt/syscall_kern.c~uml-set-dtrace-correctly	2004-11-04 20:41:43.594384056 -0800
+++ 25-akpm/arch/um/kernel/tt/syscall_kern.c	2004-11-04 20:41:43.600383144 -0800
@@ -123,11 +123,6 @@ long execute_syscall_tt(void *r)
 
 	set_fs(USER_DS);
 
-	if(current->thread.singlestep_syscall){
-		current->thread.singlestep_syscall = 0;
-		force_sig(SIGTRAP, current);
-	}
-
 	return(res);
 }
 
_
