[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