Home Home > GIT Browse > SLE12-SP3
diff options
authorEric W. Biederman <ebiederm@xmission.com>2019-02-11 23:27:42 -0600
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-02-20 10:13:23 +0100
commit492647b22f997a4ad1b7db790a55c3c3b80fec4b (patch)
parent7212e37cbdf99f48e4a6c689a42f4bda1ae69001 (diff)
signal: Restore the stop PTRACE_EVENT_EXIT
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 <oleg@redhat.com> Reported-by: Oleg Nesterov <oleg@redhat.com> Reported-by: Ivan Delalande <colona@arista.com> Cc: stable@vger.kernel.org Fixes: 35634ffa1751 ("signal: Always notice exiting tasks") Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 files changed, 5 insertions, 2 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index e464a2ef4ff5..96e8c3cbfa38 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -2241,9 +2241,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(&current->pending.signal, SIGKILL);
+ recalc_sigpending();
goto fatal;
+ }
for (;;) {
struct k_sigaction *ka;