mirror of
https://github.com/torvalds/linux.git
synced 2024-12-26 21:02:19 +00:00
ptrace: ptrace_detach() can no longer race with SIGKILL
ptrace_detach() re-checks ->ptrace under tasklist lock and calls
release_task() if __ptrace_detach() returns true. This was needed because
the __TASK_TRACED tracee could be killed/untraced, and it could even pass
exit_notify() before we take tasklist_lock.
But this is no longer possible after 9899d11f65
"ptrace: ensure
arch_ptrace/ptrace_request can never race with SIGKILL". We can turn
these checks into WARN_ON() and remove release_task().
While at it, document the setting of child->exit_code.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Cc: Pavel Labath <labath@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
b72c186999
commit
64a4096c5c
@ -456,8 +456,6 @@ static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p)
|
||||
|
||||
static int ptrace_detach(struct task_struct *child, unsigned int data)
|
||||
{
|
||||
bool dead = false;
|
||||
|
||||
if (!valid_signal(data))
|
||||
return -EIO;
|
||||
|
||||
@ -467,18 +465,19 @@ static int ptrace_detach(struct task_struct *child, unsigned int data)
|
||||
|
||||
write_lock_irq(&tasklist_lock);
|
||||
/*
|
||||
* This child can be already killed. Make sure de_thread() or
|
||||
* our sub-thread doing do_wait() didn't do release_task() yet.
|
||||
* We rely on ptrace_freeze_traced(). It can't be killed and
|
||||
* untraced by another thread, it can't be a zombie.
|
||||
*/
|
||||
if (child->ptrace) {
|
||||
child->exit_code = data;
|
||||
dead = __ptrace_detach(current, child);
|
||||
}
|
||||
WARN_ON(!child->ptrace || child->exit_state);
|
||||
/*
|
||||
* tasklist_lock avoids the race with wait_task_stopped(), see
|
||||
* the comment in ptrace_resume().
|
||||
*/
|
||||
child->exit_code = data;
|
||||
__ptrace_detach(current, child);
|
||||
write_unlock_irq(&tasklist_lock);
|
||||
|
||||
proc_ptrace_connector(child, PTRACE_DETACH);
|
||||
if (unlikely(dead))
|
||||
release_task(child);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user