If ptrace_stop() sets TASK_TRACED and then detects we should not stop,
it can race with utrace_do_stop() which can see TASK_TRACED and add
TASK_UTRACED. In this case we should stop for utrace needs.
Signed-off-by: Oleg Nesterov <oleg(a)redhat.com>
---
kernel/signal.c | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/kernel/signal.c b/kernel/signal.c
index e06f795..9348da6 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1916,6 +1916,14 @@ static void ptrace_stop(int exit_code, int why, int clear_code,
siginfo_t *info)
if (clear_code)
current->exit_code = 0;
read_unlock(&tasklist_lock);
+
+ /*
+ * It is possible that __TASK_UTRACED was added by utrace
+ * while we were __TASK_TRACED and before we take ->siglock
+ * for wake_up_quiescent(), we need to block in this case.
+ * Otherwise this is unnecessary but absolutely harmless.
+ */
+ schedule();
}
utrace_end_stop();
--
1.5.5.1