static void cgroup_context_apply(
Unit *u,
CGroupMask apply_mask,
- bool apply_bpf,
ManagerState state) {
const char *path;
assert(u);
/* Nothing to do? Exit early! */
- if (apply_mask == 0 && !apply_bpf)
+ if (apply_mask == 0)
return;
/* Some cgroup attributes are not supported on the root cgroup, hence silently ignore */
}
}
- if (apply_bpf)
+ if (apply_mask & CGROUP_MASK_BPF_FIREWALL)
cgroup_apply_firewall(u);
}
return mask;
}
+CGroupMask unit_get_bpf_mask(Unit *u) {
+ CGroupMask mask = 0;
+
+ if (unit_get_needs_bpf_firewall(u))
+ mask |= CGROUP_MASK_BPF_FIREWALL;
+
+ return mask;
+}
+
CGroupMask unit_get_own_mask(Unit *u) {
CGroupContext *c;
if (!c)
return 0;
- return cgroup_context_get_mask(c) | unit_get_delegate_mask(u);
+ return cgroup_context_get_mask(c) | unit_get_bpf_mask(u) | unit_get_delegate_mask(u);
}
CGroupMask unit_get_delegate_mask(Unit *u) {
return mask;
}
-bool unit_get_needs_bpf(Unit *u) {
+bool unit_get_needs_bpf_firewall(Unit *u) {
CGroupContext *c;
Unit *p;
assert(u);
static int unit_create_cgroup(
Unit *u,
CGroupMask target_mask,
- CGroupMask enable_mask,
- bool needs_bpf) {
+ CGroupMask enable_mask) {
CGroupContext *c;
int r;
u->cgroup_realized = true;
u->cgroup_realized_mask = target_mask;
u->cgroup_enabled_mask = enable_mask;
- u->cgroup_bpf_state = needs_bpf ? UNIT_CGROUP_BPF_ON : UNIT_CGROUP_BPF_OFF;
if (u->type != UNIT_SLICE && !unit_cgroup_delegate(u)) {
static bool unit_has_mask_realized(
Unit *u,
CGroupMask target_mask,
- CGroupMask enable_mask,
- bool needs_bpf) {
+ CGroupMask enable_mask) {
assert(u);
return u->cgroup_realized &&
u->cgroup_realized_mask == target_mask &&
u->cgroup_enabled_mask == enable_mask &&
- ((needs_bpf && u->cgroup_bpf_state == UNIT_CGROUP_BPF_ON) ||
- (!needs_bpf && u->cgroup_bpf_state == UNIT_CGROUP_BPF_OFF));
+ u->cgroup_invalidated_mask == 0;
}
static void unit_add_to_cgroup_realize_queue(Unit *u) {
* Returns 0 on success and < 0 on failure. */
static int unit_realize_cgroup_now(Unit *u, ManagerState state) {
CGroupMask target_mask, enable_mask;
- bool needs_bpf, apply_bpf;
int r;
assert(u);
target_mask = unit_get_target_mask(u);
enable_mask = unit_get_enable_mask(u);
- needs_bpf = unit_get_needs_bpf(u);
- if (unit_has_mask_realized(u, target_mask, enable_mask, needs_bpf))
+ if (unit_has_mask_realized(u, target_mask, enable_mask))
return 0;
- /* Make sure we apply the BPF filters either when one is configured, or if none is configured but previously
- * the state was anything but off. This way, if a unit with a BPF filter applied is reconfigured to lose it
- * this will trickle down properly to cgroupfs. */
- apply_bpf = needs_bpf || u->cgroup_bpf_state != UNIT_CGROUP_BPF_OFF;
-
/* First, realize parents */
if (UNIT_ISSET(u->slice)) {
r = unit_realize_cgroup_now(UNIT_DEREF(u->slice), state);
}
/* And then do the real work */
- r = unit_create_cgroup(u, target_mask, enable_mask, needs_bpf);
+ r = unit_create_cgroup(u, target_mask, enable_mask);
if (r < 0)
return r;
/* Finally, apply the necessary attributes. */
- cgroup_context_apply(u, target_mask, apply_bpf, state);
+ cgroup_context_apply(u, target_mask, state);
cgroup_xattr_apply(u);
return 0;
* any changes. */
if (unit_has_mask_realized(m,
unit_get_target_mask(m),
- unit_get_enable_mask(m),
- unit_get_needs_bpf(m)))
+ unit_get_enable_mask(m)))
continue;
unit_add_to_cgroup_realize_queue(m);
}
}
+static int cg_bpf_mask_supported(CGroupMask *ret) {
+ CGroupMask mask = 0;
+ int r;
+
+ /* BPF-based firewall */
+ r = bpf_firewall_supported();
+ if (r > 0)
+ mask |= CGROUP_MASK_BPF_FIREWALL;
+
+ *ret = mask;
+ return 0;
+}
+
int manager_setup_cgroup(Manager *m) {
_cleanup_free_ char *path = NULL;
const char *scope_path;
CGroupController c;
int r, all_unified;
+ CGroupMask mask;
char *e;
assert(m);
if (!all_unified && m->test_run_flags == 0)
(void) cg_set_attribute("memory", "/", "memory.use_hierarchy", "1");
- /* 8. Figure out which controllers are supported, and log about it */
+ /* 8. Figure out which controllers are supported */
r = cg_mask_supported(&m->cgroup_supported);
if (r < 0)
return log_error_errno(r, "Failed to determine supported controllers: %m");
+
+ /* 9. Figure out which bpf-based pseudo-controllers are supported */
+ r = cg_bpf_mask_supported(&mask);
+ if (r < 0)
+ return log_error_errno(r, "Failed to determine supported bpf-based pseudo-controllers: %m");
+ m->cgroup_supported |= mask;
+
+ /* 10. Log which controllers are supported */
for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++)
log_debug("Controller '%s' supported: %s", cgroup_controller_to_string(c), yes_no(m->cgroup_supported & CGROUP_CONTROLLER_TO_MASK(c)));
if (!UNIT_HAS_CGROUP_CONTEXT(u))
return;
- if (u->cgroup_bpf_state == UNIT_CGROUP_BPF_INVALIDATED) /* NOP? */
+ if (u->cgroup_invalidated_mask & CGROUP_MASK_BPF_FIREWALL) /* NOP? */
return;
- u->cgroup_bpf_state = UNIT_CGROUP_BPF_INVALIDATED;
+ u->cgroup_invalidated_mask |= CGROUP_MASK_BPF_FIREWALL;
unit_add_to_cgroup_realize_queue(u);
/* If we are a slice unit, we also need to put compile a new BPF program for all our children, as the IP access
u->ref_uid = UID_INVALID;
u->ref_gid = GID_INVALID;
u->cpu_usage_last = NSEC_INFINITY;
- u->cgroup_bpf_state = UNIT_CGROUP_BPF_INVALIDATED;
+ u->cgroup_invalidated_mask |= CGROUP_MASK_BPF_FIREWALL;
u->ip_accounting_ingress_map_fd = -1;
u->ip_accounting_egress_map_fd = -1;
unit_serialize_item(u, f, "cgroup-realized", yes_no(u->cgroup_realized));
(void) unit_serialize_cgroup_mask(f, "cgroup-realized-mask", u->cgroup_realized_mask);
(void) unit_serialize_cgroup_mask(f, "cgroup-enabled-mask", u->cgroup_enabled_mask);
- unit_serialize_item_format(u, f, "cgroup-bpf-realized", "%i", u->cgroup_bpf_state);
+ (void) unit_serialize_cgroup_mask(f, "cgroup-invalidated-mask", u->cgroup_invalidated_mask);
if (uid_is_valid(u->ref_uid))
unit_serialize_item_format(u, f, "ref-uid", UID_FMT, u->ref_uid);
log_unit_debug(u, "Failed to parse cgroup-enabled-mask %s, ignoring.", v);
continue;
- } else if (streq(l, "cgroup-bpf-realized")) {
- int i;
+ } else if (streq(l, "cgroup-invalidated-mask")) {
- r = safe_atoi(v, &i);
+ r = cg_mask_from_string(v, &u->cgroup_invalidated_mask);
if (r < 0)
- log_unit_debug(u, "Failed to parse cgroup BPF state %s, ignoring.", v);
- else
- u->cgroup_bpf_state =
- i < 0 ? UNIT_CGROUP_BPF_INVALIDATED :
- i > 0 ? UNIT_CGROUP_BPF_ON :
- UNIT_CGROUP_BPF_OFF;
-
+ log_unit_debug(u, "Failed to parse cgroup-invalidated-mask %s, ignoring.", v);
continue;
} else if (streq(l, "ref-uid")) {