From: Jeff Dike 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 Signed-off-by: Andrew Morton --- 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(¤t->thread.regs))) - current->thread.singlestep_syscall = 1; + if(current->ptrace & PT_DTRACE) + current->thread.singlestep_syscall = + is_syscall(PT_REGS_IP(¤t->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); } _