Commit 0da0570b authored by Jeff Dike's avatar Jeff Dike Committed by Linus Torvalds

[PATCH] uml: set DTRACE correctly

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: default avatarJeff Dike <jdike@addtoit.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent f0104457
...@@ -462,8 +462,6 @@ int singlestepping(void * t) ...@@ -462,8 +462,6 @@ int singlestepping(void * t)
if ( ! (task->ptrace & PT_DTRACE) ) if ( ! (task->ptrace & PT_DTRACE) )
return(0); return(0);
task->ptrace &= ~PT_DTRACE;
if (task->thread.singlestep_syscall) if (task->thread.singlestep_syscall)
return(0); return(0);
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
*/ */
void ptrace_disable(struct task_struct *child) 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) int sys_ptrace(long request, long pid, long addr, long data)
...@@ -139,6 +141,9 @@ int sys_ptrace(long request, long pid, long addr, long data) ...@@ -139,6 +141,9 @@ int sys_ptrace(long request, long pid, long addr, long data)
ret = -EIO; ret = -EIO;
if ((unsigned long) data > _NSIG) if ((unsigned long) data > _NSIG)
break; break;
child->ptrace &= ~PT_DTRACE;
child->thread.singlestep_syscall = 0;
if (request == PTRACE_SYSCALL) { if (request == PTRACE_SYSCALL) {
set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
} }
...@@ -160,6 +165,9 @@ int sys_ptrace(long request, long pid, long addr, long data) ...@@ -160,6 +165,9 @@ int sys_ptrace(long request, long pid, long addr, long data)
ret = 0; ret = 0;
if (child->exit_state == EXIT_ZOMBIE) /* already dead */ if (child->exit_state == EXIT_ZOMBIE) /* already dead */
break; break;
child->ptrace &= ~PT_DTRACE;
child->thread.singlestep_syscall = 0;
child->exit_code = SIGKILL; child->exit_code = SIGKILL;
wake_up_process(child); wake_up_process(child);
break; break;
...@@ -171,6 +179,7 @@ int sys_ptrace(long request, long pid, long addr, long data) ...@@ -171,6 +179,7 @@ int sys_ptrace(long request, long pid, long addr, long data)
break; break;
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
child->ptrace |= PT_DTRACE; child->ptrace |= PT_DTRACE;
child->thread.singlestep_syscall = 0;
child->exit_code = data; child->exit_code = data;
/* give it a chance to run. */ /* give it a chance to run. */
wake_up_process(child); wake_up_process(child);
...@@ -299,6 +308,9 @@ int sys_ptrace(long request, long pid, long addr, long data) ...@@ -299,6 +308,9 @@ int sys_ptrace(long request, long pid, long addr, long data)
void syscall_trace(union uml_pt_regs *regs, int entryexit) 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 (unlikely(current->audit_context)) {
if (!entryexit) if (!entryexit)
audit_syscall_entry(current, regs->orig_eax, audit_syscall_entry(current, regs->orig_eax,
...@@ -308,18 +320,20 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit) ...@@ -308,18 +320,20 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit)
audit_syscall_exit(current, regs->eax); audit_syscall_exit(current, regs->eax);
} }
if (!test_thread_flag(TIF_SYSCALL_TRACE)) if (!test_thread_flag(TIF_SYSCALL_TRACE) && !is_singlestep)
return; return;
if (!(current->ptrace & PT_PTRACED)) if (!(current->ptrace & PT_PTRACED))
return; return;
/* the 0x80 provides a way for the tracing parent to distinguish /* the 0x80 provides a way for the tracing parent to distinguish
between a syscall stop and SIGTRAP delivery */ between a syscall stop and SIGTRAP delivery */
ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) tracesysgood = (current->ptrace & PT_TRACESYSGOOD) && !is_singlestep;
? 0x80 : 0)); 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 * for normal use. strace only continues with a signal if the
* stopping signal is not SIGTRAP. -brl * stopping signal is not SIGTRAP. -brl
*/ */
......
...@@ -152,9 +152,9 @@ static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset) ...@@ -152,9 +152,9 @@ static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset)
* on the host. The tracing thread will check this flag and * on the host. The tracing thread will check this flag and
* PTRACE_SYSCALL if necessary. * PTRACE_SYSCALL if necessary.
*/ */
if((current->ptrace & PT_DTRACE) && if(current->ptrace & PT_DTRACE)
is_syscall(PT_REGS_IP(&current->thread.regs))) current->thread.singlestep_syscall =
current->thread.singlestep_syscall = 1; is_syscall(PT_REGS_IP(&current->thread.regs));
return(0); return(0);
} }
......
...@@ -28,11 +28,6 @@ long execute_syscall_skas(void *r) ...@@ -28,11 +28,6 @@ long execute_syscall_skas(void *r)
res = -ENOSYS; res = -ENOSYS;
else res = EXECUTE_SYSCALL(syscall, regs); else res = EXECUTE_SYSCALL(syscall, regs);
if(current->thread.singlestep_syscall){
current->thread.singlestep_syscall = 0;
force_sig(SIGTRAP, current);
}
return(res); return(res);
} }
......
...@@ -123,11 +123,6 @@ long execute_syscall_tt(void *r) ...@@ -123,11 +123,6 @@ long execute_syscall_tt(void *r)
set_fs(USER_DS); set_fs(USER_DS);
if(current->thread.singlestep_syscall){
current->thread.singlestep_syscall = 0;
force_sig(SIGTRAP, current);
}
return(res); return(res);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment