Commit 82b82272 authored by Oleg Nesterov's avatar Oleg Nesterov Committed by Ben Hutchings

exit_signal: fix the "parent has changed security domain" logic

commit b6e238dc upstream.

exit_notify() changes ->exit_signal if the parent already did exec.
This doesn't really work, we are not going to send the signal now
if there is another live thread or the exiting task is traced. The
parent can exec before the last dies or the tracer detaches.

Move this check into do_notify_parent() which actually sends the
signal.

The user-visible change is that we do not change ->exit_signal,
and thus the exiting task is still "clone children" for
do_wait()->eligible_child(__WCLONE). Hopefully this is fine, the
current logic is racy anyway.
Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
parent 3dc73190
...@@ -819,20 +819,6 @@ static void exit_notify(struct task_struct *tsk, int group_dead) ...@@ -819,20 +819,6 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
if (group_dead) if (group_dead)
kill_orphaned_pgrp(tsk->group_leader, NULL); kill_orphaned_pgrp(tsk->group_leader, NULL);
/* Let father know we died
*
* Thread signals are configurable, but you aren't going to use
* that to send signals to arbitrary processes.
* That stops right now.
*
* If the parent exec id doesn't match the exec id we saved
* when we started then we know the parent has changed security
* domain.
*/
if (thread_group_leader(tsk) && tsk->exit_signal != SIGCHLD &&
tsk->parent_exec_id != tsk->real_parent->self_exec_id)
tsk->exit_signal = SIGCHLD;
if (unlikely(tsk->ptrace)) { if (unlikely(tsk->ptrace)) {
int sig = thread_group_leader(tsk) && int sig = thread_group_leader(tsk) &&
thread_group_empty(tsk) && thread_group_empty(tsk) &&
......
...@@ -1610,6 +1610,15 @@ bool do_notify_parent(struct task_struct *tsk, int sig) ...@@ -1610,6 +1610,15 @@ bool do_notify_parent(struct task_struct *tsk, int sig)
BUG_ON(!tsk->ptrace && BUG_ON(!tsk->ptrace &&
(tsk->group_leader != tsk || !thread_group_empty(tsk))); (tsk->group_leader != tsk || !thread_group_empty(tsk)));
if (sig != SIGCHLD) {
/*
* This is only possible if parent == real_parent.
* Check if it has changed security domain.
*/
if (tsk->parent_exec_id != tsk->parent->self_exec_id)
sig = SIGCHLD;
}
info.si_signo = sig; info.si_signo = sig;
info.si_errno = 0; info.si_errno = 0;
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment