mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	signal: Restore the stop PTRACE_EVENT_EXIT
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: 35634ffa17 ("signal: Always notice exiting tasks")
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
			
			
This commit is contained in:
		
							parent
							
								
									7146db3317
								
							
						
					
					
						commit
						cf43a757fd
					
				
					 1 changed files with 5 additions and 2 deletions
				
			
		| 
						 | 
					@ -2436,9 +2436,12 @@ bool get_signal(struct ksignal *ksig)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Has this task already been marked for death? */
 | 
						/* Has this task already been marked for death? */
 | 
				
			||||||
 | 
						if (signal_group_exit(signal)) {
 | 
				
			||||||
		ksig->info.si_signo = signr = SIGKILL;
 | 
							ksig->info.si_signo = signr = SIGKILL;
 | 
				
			||||||
	if (signal_group_exit(signal))
 | 
							sigdelset(¤t->pending.signal, SIGKILL);
 | 
				
			||||||
 | 
							recalc_sigpending();
 | 
				
			||||||
		goto fatal;
 | 
							goto fatal;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (;;) {
 | 
						for (;;) {
 | 
				
			||||||
		struct k_sigaction *ka;
 | 
							struct k_sigaction *ka;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue