fork: fix copy_process(CLONE_PARENT) race with the exiting ->real_parent

current->group_leader->exit_signal may change during copy_process() if
current->real_parent exits.

Move the assignment inside tasklist_lock to avoid the race.

Signed-off-by: Eddy Wu <eddy_wu@trendmicro.com>
Acked-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Eddy Wu 2020-11-07 14:47:22 +08:00 committed by Linus Torvalds
parent 9dbc1c03ee
commit b4e00444ca

View File

@ -2167,14 +2167,9 @@ static __latent_entropy struct task_struct *copy_process(
/* ok, now we should be set up.. */ /* ok, now we should be set up.. */
p->pid = pid_nr(pid); p->pid = pid_nr(pid);
if (clone_flags & CLONE_THREAD) { if (clone_flags & CLONE_THREAD) {
p->exit_signal = -1;
p->group_leader = current->group_leader; p->group_leader = current->group_leader;
p->tgid = current->tgid; p->tgid = current->tgid;
} else { } else {
if (clone_flags & CLONE_PARENT)
p->exit_signal = current->group_leader->exit_signal;
else
p->exit_signal = args->exit_signal;
p->group_leader = p; p->group_leader = p;
p->tgid = p->pid; p->tgid = p->pid;
} }
@ -2218,9 +2213,14 @@ static __latent_entropy struct task_struct *copy_process(
if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) { if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) {
p->real_parent = current->real_parent; p->real_parent = current->real_parent;
p->parent_exec_id = current->parent_exec_id; p->parent_exec_id = current->parent_exec_id;
if (clone_flags & CLONE_THREAD)
p->exit_signal = -1;
else
p->exit_signal = current->group_leader->exit_signal;
} else { } else {
p->real_parent = current; p->real_parent = current;
p->parent_exec_id = current->self_exec_id; p->parent_exec_id = current->self_exec_id;
p->exit_signal = args->exit_signal;
} }
klp_copy_process(p); klp_copy_process(p);