Currently ptrace_detach does UTRACE_DETACH then ptrace_unlink().

This is not right, UTRACE_DETACH wakes up the tracee. It can stop/die
after that, but since it is still task_ptrace() this can confuse its
->real_parent.

We can't solve this if we add __wake_up_parent(->real_parent). So change
the order.

And move most of the code into the new helper, ptrace_do_detach(). It
will be use by exit_ptrace().

---

 kernel/ptrace.c |   36 +++++++++++++++++++++++-------------
 1 file changed, 23 insertions(+), 13 deletions(-)

--- PU/kernel/ptrace.c~12_REWORK_DETACH 2009-08-22 20:06:42.000000000 +0200
+++ PU/kernel/ptrace.c  2009-08-22 20:08:23.000000000 +0200
@@ -740,28 +740,38 @@ static bool __ptrace_detach(struct task_
        return false;
 }
 
-int ptrace_detach(struct task_struct *child, unsigned int data)
+static void ptrace_do_detach(struct task_struct *tracee, unsigned int data)
 {
-       bool dead = false;
-
-       if (!valid_signal(data))
-               return -EIO;
-
-       ptrace_detach_task(child, data);
+       bool traced, dead;
 
        write_lock_irq(&tasklist_lock);
        /*
-        * This child can be already killed. Make sure de_thread() or
+        * This tracee can be already killed. Make sure de_thread() or
         * our sub-thread doing do_wait() didn't do release_task() yet.
         */
-       if (child->ptrace) {
-               child->exit_code = data;
-               dead = __ptrace_detach(current, child);
+       traced = tracee->ptrace;
+       if (likely(traced)) {
+               tracee->exit_code = data;
+               dead = __ptrace_detach(current, tracee);
        }
        write_unlock_irq(&tasklist_lock);
 
-       if (unlikely(dead))
-               release_task(child);
+       if (unlikely(!traced))
+               return;
+       if (unlikely(dead)) {
+               release_task(tracee);
+               return;
+       }
+
+       ptrace_detach_task(tracee, data);
+}
+
+int ptrace_detach(struct task_struct *child, unsigned int data)
+{
+       if (!valid_signal(data))
+               return -EIO;
+
+       ptrace_do_detach(child, data);
 
        return 0;
 }

Reply via email to