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@redhat.com --- kernel/signal.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/kernel/signal.c b/kernel/signal.c index 0d1675a..249760f 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1908,6 +1908,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();