From: Eric W. Biederman Date: Tue, 12 Feb 2019 05:27:42 +0000 (-0600) Subject: signal: Restore the stop PTRACE_EVENT_EXIT X-Git-Tag: Ubuntu-4.15.0-61.68~3238 X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=70fc9b3b48da4ec14e69d375cbb0ba78914acb51;p=mirror_ubuntu-bionic-kernel.git signal: Restore the stop PTRACE_EVENT_EXIT BugLink: https://bugs.launchpad.net/bugs/1837813 commit cf43a757fd49442bc38f76088b70c2299eed2c2f upstream. In the middle of do_exit() there is there is a call "ptrace_event(PTRACE_EVENT_EXIT, code);" That call places the process in TACKED_TRACED aka "(TASK_WAKEKILL | __TASK_TRACED)" and waits for for the debugger to release the task or SIGKILL to be delivered. Skipping past dequeue_signal when we know a fatal signal has already been delivered resulted in SIGKILL remaining pending and TIF_SIGPENDING remaining set. This in turn caused the scheduler to not sleep in PTACE_EVENT_EXIT as it figured a fatal signal was pending. This also caused ptrace_freeze_traced in ptrace_check_attach to fail because it left a per thread SIGKILL pending which is what fatal_signal_pending tests for. This difference in signal state caused strace to report strace: Exit of unknown pid NNNNN ignored Therefore update the signal handling state like dequeue_signal would when removing a per thread SIGKILL, by removing SIGKILL from the per thread signal mask and clearing TIF_SIGPENDING. Acked-by: Oleg Nesterov Reported-by: Oleg Nesterov Reported-by: Ivan Delalande Cc: stable@vger.kernel.org Fixes: 35634ffa1751 ("signal: Always notice exiting tasks") Signed-off-by: "Eric W. Biederman" Signed-off-by: Greg Kroah-Hartman Signed-off-by: Connor Kuehl Signed-off-by: Khalid Elmously --- diff --git a/kernel/signal.c b/kernel/signal.c index 70b936c064ba..eab385c966fa 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -2268,9 +2268,12 @@ relock: } /* Has this task already been marked for death? */ - ksig->info.si_signo = signr = SIGKILL; - if (signal_group_exit(signal)) + if (signal_group_exit(signal)) { + ksig->info.si_signo = signr = SIGKILL; + sigdelset(¤t->pending.signal, SIGKILL); + recalc_sigpending(); goto fatal; + } for (;;) { struct k_sigaction *ka;