mirror of
https://github.com/torvalds/linux.git
synced 2026-09-11 20:13:02 +02:00
cgroup: fix spurious SIGKILL of CLONE_INTO_CGROUP children
Since commitb69bb476de("cgroup: fix race between fork and cgroup.kill"), the fork path snapshots the kill_seq of the child's future cgroup into kargs->kill_seq, and cgroup_post_fork() SIGKILLs the child if that cgroup's kill_seq has changed in the meantime, to catch forks racing with a cgroup.kill sweep. For CLONE_INTO_CGROUP, however, the snapshot in cgroup_css_set_fork() is taken before the target cgroup has been resolved: kargs->cgrp is always NULL at this point (it is only set at the end of the function). So the "if (kargs->cgrp)" branch is dead code and the snapshot always records the kill_seq of the parent's cgroup. cgroup_post_fork() then compares it with the kill_seq of the target cgroup, so the child gets SIGKILLed whenever the two cgroups have been killed a different number of times. As a result, once cgroup.kill has been written to a cgroup, every child subsequently cloned into it with clone3(CLONE_INTO_CGROUP) is killed on the spot, for as long as the cgroup exists: kill_seq is not exposed to userspace and never resets. Re-snapshot kill_seq from the target cgroup once it has been resolved, and drop the dead branch at the early snapshot site. This does not reopen the race fixed byb69bb476de. For CLONE_INTO_CGROUP, everything from the snapshot to the check in cgroup_post_fork() runs with cgroup_mutex held, and kill_seq is only ever incremented under cgroup_mutex. tj: Updated the comment above kill_seq to reflect the new serialization rules as suggested by Shakeel Butt. Fixes:b69bb476de("cgroup: fix race between fork and cgroup.kill") Cc: stable@vger.kernel.org Cc: Shakeel Butt <shakeel.butt@linux.dev> Assisted-by: LLM Signed-off-by: Etienne Perot <eperot@google.com> Signed-off-by: Tejun Heo <tj@kernel.org>
This commit is contained in:
parent
87d347a8c8
commit
8e35992021
|
|
@ -527,7 +527,10 @@ struct cgroup {
|
|||
|
||||
int nr_threaded_children; /* # of live threaded child cgroups */
|
||||
|
||||
/* sequence number for cgroup.kill, serialized by css_set_lock. */
|
||||
/*
|
||||
* Sequence number for cgroup.kill. Incremented with both cgroup_mutex
|
||||
* and css_set_lock held. Readers hold either one.
|
||||
*/
|
||||
unsigned int kill_seq;
|
||||
|
||||
struct kernfs_node *kn; /* cgroup kernfs entry */
|
||||
|
|
|
|||
|
|
@ -6777,10 +6777,7 @@ static int cgroup_css_set_fork(struct kernel_clone_args *kargs)
|
|||
spin_lock_irq(&css_set_lock);
|
||||
cset = task_css_set(current);
|
||||
get_css_set(cset);
|
||||
if (kargs->cgrp)
|
||||
kargs->kill_seq = kargs->cgrp->kill_seq;
|
||||
else
|
||||
kargs->kill_seq = cset->dfl_cgrp->kill_seq;
|
||||
kargs->kill_seq = cset->dfl_cgrp->kill_seq;
|
||||
spin_unlock_irq(&css_set_lock);
|
||||
|
||||
if (!(kargs->flags & CLONE_INTO_CGROUP)) {
|
||||
|
|
@ -6844,6 +6841,7 @@ static int cgroup_css_set_fork(struct kernel_clone_args *kargs)
|
|||
|
||||
put_css_set(cset);
|
||||
kargs->cgrp = dst_cgrp;
|
||||
kargs->kill_seq = dst_cgrp->kill_seq;
|
||||
return ret;
|
||||
|
||||
err:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user