[PATCH 58] do_ptrace_notify_stop: fix the race with SIGKILL
Oleg Nesterov
oleg at redhat.com
Sat Oct 3 01:57:49 UTC 2009
do_ptrace_notify_stop()->do_notify_parent_cldstop() is not safe
when called by tracer.
By the time we take tasklist the tracee can be SIGKILL'ed and
released by our sub-thread. In this case it is wrong to notify
its ->real_parent.
If ->real_parent has exited, then do_notify_parent_cldstop()
can use the freed/unmapped/resused/ task_struct.
Check task_ptrace(tracee) under tasklist_lock.
---
kernel/ptrace.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
--- PU/kernel/ptrace.c~58_NOTIFY_FIX_RACE 2009-10-02 23:19:41.000000000 +0200
+++ PU/kernel/ptrace.c 2009-10-02 23:34:57.000000000 +0200
@@ -831,14 +831,15 @@ static void do_ptrace_notify_stop(struct
WARN_ON(!context->ev_code);
context->ev_code = 0;
- // XXX: !!!!!!!! UNSAFE when called by tracer !!!!!!!!!!!!!
read_lock(&tasklist_lock);
/*
* Don't want to allow preemption here, because
* sys_ptrace() needs this task to be inactive.
*/
preempt_disable();
- do_notify_parent_cldstop(tracee, CLD_TRAPPED);
+ /* It can be killed and then released by our subthread */
+ if (task_ptrace(tracee))
+ do_notify_parent_cldstop(tracee, CLD_TRAPPED);
read_unlock(&tasklist_lock);
preempt_enable_no_resched();
}
More information about the utrace-devel
mailing list