ptrace_untrace: fix the SIGNAL_STOP_STOPPED check
authorOleg Nesterov <oleg@redhat.com>
Thu, 2 Apr 2009 23:58:23 +0000 (16:58 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 3 Apr 2009 02:05:00 +0000 (19:05 -0700)
This bug is ancient too. ptrace_untrace() must not resume the task
if the group stop in progress, we should set TASK_STOPPED instead.

Unfortunately, we still have problems here:

- if the process/thread was traced, SIGNAL_STOP_STOPPED
  does not necessary means this thread group is stopped.

- ptrace breaks the bookkeeping of ->group_stop_count.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Cc: Jerome Marchand <jmarchan@redhat.com>
Cc: Roland McGrath <roland@redhat.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
kernel/ptrace.c

index 296e8105863af4e18742314855156c248ba6048f..5105f5a6a2ce3d843affaed6130ef5eb873db87f 100644 (file)
@@ -60,11 +60,15 @@ static void ptrace_untrace(struct task_struct *child)
 {
        spin_lock(&child->sighand->siglock);
        if (task_is_traced(child)) {
-               if (child->signal->flags & SIGNAL_STOP_STOPPED) {
+               /*
+                * If the group stop is completed or in progress,
+                * this thread was already counted as stopped.
+                */
+               if (child->signal->flags & SIGNAL_STOP_STOPPED ||
+                   child->signal->group_stop_count)
                        __set_task_state(child, TASK_STOPPED);
-               } else {
+               else
                        signal_wake_up(child, 1);
-               }
        }
        spin_unlock(&child->sighand->siglock);
 }