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)
if ( ! (task->ptrace & PT_DTRACE) )
return(0);
task->ptrace &= ~PT_DTRACE;
if (task->thread.singlestep_syscall)
return(0);
......
......@@ -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, long addr, long data)
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, long addr, long data)
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, long addr, long data)
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, long addr, long data)
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 *regs, int entryexit)
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
*/
......
......@@ -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
* 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);
}
......
......@@ -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);
}
......
......@@ -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);
}
......
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