mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-21 20:13:58 +08:00
__group_complete_signal(): fix coredump with group stop race
When __group_complete_signal() sees sig_kernel_coredump() signal, it starts the group stop, but sets ->group_exit_task = t in a hope that "t" will actually dequeue this signal and invoke do_coredump(). However, by the time "t" enters get_signal_to_deliver() it is possible that the signal was blocked/ignored or we have another pending !SIG_KERNEL_COREDUMP_MASK signal which will be dequeued first. This means the task could be stopped but not killed. Remove this code from __group_complete_signal(). Note also this patch removes the bogus signal_wake_up(t, 1). This thread can't be STOPPED/TRACED, note the corresponding check in wants_signal(). Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru> Cc: Davide Libenzi <davidel@xmailserver.org> Cc: Ingo Molnar <mingo@elte.hu> Cc: Robin Holt <holt@sgi.com> Cc: Roland McGrath <roland@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
bdff746a39
commit
198466b41d
@ -911,27 +911,6 @@ __group_complete_signal(int sig, struct task_struct *p)
|
||||
} while_each_thread(p, t);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* There will be a core dump. We make all threads other
|
||||
* than the chosen one go into a group stop so that nothing
|
||||
* happens until it gets scheduled, takes the signal off
|
||||
* the shared queue, and does the core dump. This is a
|
||||
* little more complicated than strictly necessary, but it
|
||||
* keeps the signal state that winds up in the core dump
|
||||
* unchanged from the death state, e.g. which thread had
|
||||
* the core-dump signal unblocked.
|
||||
*/
|
||||
rm_from_queue(SIG_KERNEL_STOP_MASK, &t->pending);
|
||||
rm_from_queue(SIG_KERNEL_STOP_MASK, &p->signal->shared_pending);
|
||||
p->signal->group_stop_count = 0;
|
||||
p->signal->group_exit_task = t;
|
||||
p = t;
|
||||
do {
|
||||
p->signal->group_stop_count++;
|
||||
signal_wake_up(t, t == p);
|
||||
} while_each_thread(p, t);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1762,15 +1741,6 @@ static int handle_group_stop(void)
|
||||
{
|
||||
int stop_count;
|
||||
|
||||
if (current->signal->group_exit_task == current) {
|
||||
/*
|
||||
* Group stop is so we can do a core dump,
|
||||
* We are the initiating thread, so get on with it.
|
||||
*/
|
||||
current->signal->group_exit_task = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (current->signal->flags & SIGNAL_GROUP_EXIT)
|
||||
/*
|
||||
* Group stop is so another thread can do a core dump,
|
||||
|
Loading…
Reference in New Issue
Block a user