From: Oleg Nesterov Date: Mon, 26 Sep 2011 17:06:32 +0000 (+0200) Subject: ptrace: don't clear GROUP_STOP_SIGMASK on double-stop X-Git-Tag: firefly_0821_release~7541^2~2430 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=43742b14ffbe87453e96f4411389445fc707df57;p=firefly-linux-kernel-4.4.55.git ptrace: don't clear GROUP_STOP_SIGMASK on double-stop [This does not correspond to any specific patch in the upstream tree as it was fixed accidentally by rewriting the code in the 3.1 release] https://bugzilla.redhat.com/show_bug.cgi?id=740121 1. Luke Macken triggered WARN_ON(!(group_stop & GROUP_STOP_SIGMASK)) in do_signal_stop(). This is because do_signal_stop() clears GROUP_STOP_SIGMASK part unconditionally but doesn't update it if task_is_stopped(). 2. Looking at this problem I noticed that WARN_ON_ONCE(!ptrace) is not right, a stopped-but-resumed tracee can clone the untraced thread in the SIGNAL_STOP_STOPPED group, the new thread can start another group-stop. Remove this warning, we need more fixes to make it true. Reported-by: Luke Macken Signed-off-by: Oleg Nesterov Signed-off-by: Greg Kroah-Hartman --- diff --git a/kernel/signal.c b/kernel/signal.c index 415d85d6f6c6..43fee1cf50d0 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1894,21 +1894,19 @@ static int do_signal_stop(int signr) */ if (!(sig->flags & SIGNAL_STOP_STOPPED)) sig->group_exit_code = signr; - else - WARN_ON_ONCE(!task_ptrace(current)); current->group_stop &= ~GROUP_STOP_SIGMASK; current->group_stop |= signr | gstop; sig->group_stop_count = 1; for (t = next_thread(current); t != current; t = next_thread(t)) { - t->group_stop &= ~GROUP_STOP_SIGMASK; /* * Setting state to TASK_STOPPED for a group * stop is always done with the siglock held, * so this check has no races. */ if (!(t->flags & PF_EXITING) && !task_is_stopped(t)) { + t->group_stop &= ~GROUP_STOP_SIGMASK; t->group_stop |= signr | gstop; sig->group_stop_count++; signal_wake_up(t, 0);