diff --git a/[refs] b/[refs] index 86ddbf9d562a..388c4f64f9a7 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: b1b4c6799fb59e710454bfe0ab477cb8523a8667 +refs/heads/master: 4576145c1ecdaaea9ef8976a48335206aa1ebf91 diff --git a/trunk/include/linux/ptrace.h b/trunk/include/linux/ptrace.h index 98b93ca4db06..1a2b0cb55535 100644 --- a/trunk/include/linux/ptrace.h +++ b/trunk/include/linux/ptrace.h @@ -94,6 +94,7 @@ extern void ptrace_notify(int exit_code); extern void __ptrace_link(struct task_struct *child, struct task_struct *new_parent); extern void __ptrace_unlink(struct task_struct *child); +extern int __ptrace_detach(struct task_struct *tracer, struct task_struct *p); extern void ptrace_fork(struct task_struct *task, unsigned long clone_flags); #define PTRACE_MODE_READ 1 #define PTRACE_MODE_ATTACH 2 diff --git a/trunk/kernel/ptrace.c b/trunk/kernel/ptrace.c index f62a568e84ec..ee553b6ad125 100644 --- a/trunk/kernel/ptrace.c +++ b/trunk/kernel/ptrace.c @@ -237,6 +237,8 @@ int ptrace_attach(struct task_struct *task) int ptrace_detach(struct task_struct *child, unsigned int data) { + int dead = 0; + if (!valid_signal(data)) return -EIO; @@ -244,18 +246,21 @@ int ptrace_detach(struct task_struct *child, unsigned int data) ptrace_disable(child); clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - /* protect against de_thread()->release_task() */ write_lock_irq(&tasklist_lock); + /* protect against de_thread()->release_task() */ if (child->ptrace) { child->exit_code = data; - __ptrace_unlink(child); + dead = __ptrace_detach(current, child); if (!child->exit_state) wake_up_process(child); } write_unlock_irq(&tasklist_lock); + if (unlikely(dead)) + release_task(child); + return 0; }