Re: [PATCH 1/2] cgroup: fix spurious SIGKILL of CLONE_INTO_CGROUP children
From: Daniel Golle
Date: Mon Sep 21 2026 - 13:14:20 EST
On Fri, Aug 28, 2026 at 09:52:51PM +0000, Etienne Perot wrote:
> 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).
We hit this in OpenWrt and reached the same conclusion independently
before finding your patch, so here is a second data point from a real
workload.
The symptom is that re-creating an OCI container fails. procd's service
supervisor writes cgroup.kill to /sys/fs/cgroup/services/<service>/<name>
when a jailed instance exits, and leaves the directory in place. The next
generation of the same instance is started into that same leaf and execs
ujail, which clone3()s the container init with CLONE_INTO_CGROUP into a
freshly created cgroup under /sys/fs/cgroup/containers/. The container
init is SIGKILLed before it executes a single instruction, and every
subsequent attempt fails identically for as long as the services leaf
lives.
Instrumenting the child confirmed it never reaches its first statement
after clone3(). What isolated it was that rmdir() of the services leaf
followed immediately by mkdir() of the same path at the same mode makes
the failure disappear, while an unrelated cgroup operation in the same
window does not, and while the leaf's attributes are byte for byte
identical to a freshly created one. That pointed at per-cgroup state
exposed in no file, and the snapshot site then explained it: on 6.18.52
the capture is at cgroup.c:6740 while kargs->cgrp is only assigned at
:6803, so the else branch is always taken and cgroup_post_fork() ends up
comparing two independent counters.
Backporting this patch to 6.18.52 fixes it. With no userspace change at
all, and with the killed cgroup still deliberately left in place, three
consecutive create attempts that previously failed now succeed:
before: create rc=251, container spuriously left running (3/3)
after: create rc=0, container correctly left created (3/3)
Your selftest in 2/2 reproduces it on the same machine, and behaves
exactly as your commit message says:
6.18.52 without 1/2: ok 1 test_cgkill_simple
ok 2 test_cgkill_tree
ok 3 test_cgkill_forkbomb
not ok 4 test_cgkill_clone_into_killed
6.18.52 with 1/2: ok 1 test_cgkill_simple
ok 2 test_cgkill_tree
ok 3 test_cgkill_forkbomb
ok 4 test_cgkill_clone_into_killed
Tested on x86_64, kernel 6.18.52, with procd/ujail as the OCI runtime;
the two kernels differ only by 1/2.
Reviewed-by: Daniel Golle <daniel@xxxxxxxxxxxxxx>
Tested-by: Daniel Golle <daniel@xxxxxxxxxxxxxx>
One request about stable, and apologies if this is simply a matter of
timing. The patch is in mainline from v7.3-rc2 and carries Cc: stable,
but as of 6.18.53 it is not in linux-6.18.y yet. Given that the failure
is silent from userspace, the child dies with no diagnostic and kill_seq
is visible nowhere, it would be worth queueing for 6.18.y and the other
branches carrying b69bb476dee9 ahead of the usual post-release sweep.
We are carrying it as a local backport in the meantime.
Thanks for tracking this down.