core: set pids.max=0 before sending SIGKILL to cgroup

When doing the final SIGKILL when stopping units ensure no more
processes can be created by setting pids.max=0 in the cgroup.
This commit is contained in:
Luca Boccassi
2026-06-20 10:53:04 +01:00
parent 075036f205
commit 23b0bd230b
+53
View File
@@ -5032,6 +5032,35 @@ static int unit_kill_context_one(
return !is_alien;
}
typedef struct PidsMaxRestore {
const char *cgroup_path;
uint64_t max;
Unit *unit;
} PidsMaxRestore;
static void pids_max_restore(PidsMaxRestore *p) {
int r;
assert(p);
assert(p->unit);
if (!p->cgroup_path)
return;
char value[DECIMAL_STR_MAX(uint64_t) + 1] = "max";
if (p->max != CGROUP_LIMIT_MAX)
xsprintf(value, "%" PRIu64, p->max);
r = cg_set_attribute(p->cgroup_path, "pids.max", value);
if (r < 0)
log_unit_warning_errno(p->unit,
r,
"Failed to restore pids.max to %s for control group %s, ignoring: %m",
value, empty_to_root(p->cgroup_path));
p->cgroup_path = NULL;
}
int unit_kill_context(Unit *u, KillOperation k) {
bool wait_for_exit = false, send_sighup;
cg_kill_log_func_t log_func = NULL;
@@ -5068,8 +5097,32 @@ int unit_kill_context(Unit *u, KillOperation k) {
CGroupRuntime *crt = unit_get_cgroup_runtime(u);
if (crt && crt->cgroup_path &&
(c->kill_mode == KILL_CONTROL_GROUP || (c->kill_mode == KILL_MIXED && k == KILL_KILL))) {
_cleanup_(pids_max_restore) PidsMaxRestore state = {
.unit = u,
};
_cleanup_set_free_ Set *pid_set = NULL;
/* Stop more processes from being spawned when zapping the cgroup. Restore previous state
* before returning. */
if (sig == SIGKILL) {
r = cg_get_attribute_as_uint64(crt->cgroup_path, "pids.max", &state.max);
if (r < 0)
log_unit_warning_errno(u,
r,
"Failed to read pids.max for control group %s, ignoring: %m",
empty_to_root(crt->cgroup_path));
else {
r = cg_set_attribute(crt->cgroup_path, "pids.max", "0");
if (r < 0)
log_unit_warning_errno(u,
r,
"Failed to set pids.max to 0 for control group %s, ignoring: %m",
empty_to_root(crt->cgroup_path));
else
state.cgroup_path = crt->cgroup_path;
}
}
/* Exclude the main/control pids from being killed via the cgroup */
r = unit_pid_set(u, &pid_set);
if (r < 0)