I blindly copied this code from ptrace_resume() but it is wrong.
task_is_stopped() can never be true, and we must not use ->sighand
directly. Since the tracee should be TRACED or killed we do not
check tracee->state at all.

Fixes a couple of tests...

---

 kernel/ptrace.c |   18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

--- PU/kernel/ptrace.c~29_WAKEUP_COMPAT_BUG     2009-09-12 00:13:34.000000000 
+0200
+++ PU/kernel/ptrace.c  2009-09-12 00:59:10.000000000 +0200
@@ -320,12 +320,13 @@ static void ptrace_wake_up(struct utrace
                                struct task_struct *tracee,
                                enum utrace_resume_action action)
 {
+       unsigned long flags;
+
        /* preserve the compatibility bug */
-       if (task_is_stopped(tracee)) {
-               spin_lock_irq(&tracee->sighand->siglock);
-               tracee->signal->flags &= ~SIGNAL_STOP_STOPPED;
-               spin_unlock_irq(&tracee->sighand->siglock);
-       }
+       if (!lock_task_sighand(tracee, &flags))
+               return;
+       tracee->signal->flags &= ~SIGNAL_STOP_STOPPED;
+       unlock_task_sighand(tracee, &flags);
 
        // XXX: FIXME!!! racy.
        tracee->exit_code = 0;
@@ -1134,10 +1135,11 @@ static int ptrace_resume(struct task_str
                        do_notify_parent_cldstop(child, CLD_TRAPPED);
                        read_unlock(&tasklist_lock);
                } else {
-                       if (task_is_stopped(child)) {
-                               spin_lock_irq(&child->sighand->siglock);
+                       unsigned long flags;
+
+                       if (lock_task_sighand(child, &flags)) {
                                child->signal->flags &= ~SIGNAL_STOP_STOPPED;
-                               spin_unlock_irq(&child->sighand->siglock);
+                               unlock_task_sighand(child, &flags);
                        }
 
                        /*

Reply via email to