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:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user