From: Mike Yuan Date: Wed, 24 Dec 2025 18:20:48 +0000 (+0100) Subject: core/cgroup: fix bpf-bind-iface serialization X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5af2df38df92abbe16272d96533d5e7ab39c938b;p=thirdparty%2Fsystemd.git core/cgroup: fix bpf-bind-iface serialization Follow-up for c1c787651b34c0a0f1082b9d32cf47ea3abe0af2 The commit added serialization, but deserialization wasn't in place. Follow the usual practice of pinning the bpf link fd until we install the new instance. --- diff --git a/src/core/bpf-bind-iface.c b/src/core/bpf-bind-iface.c index ea439d307ba..6b11e83543f 100644 --- a/src/core/bpf-bind-iface.c +++ b/src/core/bpf-bind-iface.c @@ -49,25 +49,18 @@ int bpf_bind_network_interface_supported(void) { return (supported = bpf_can_link_program(obj->progs.sd_bind_interface)); } -int bpf_bind_network_interface_install(Unit *u) { +static int bind_network_interface_install_impl(Unit *u, CGroupRuntime *crt) { _cleanup_(bpf_link_freep) struct bpf_link *link = NULL; _cleanup_(bind_iface_bpf_freep) struct bind_iface_bpf *obj = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _cleanup_free_ char *cgroup_path = NULL; _cleanup_close_ int cgroup_fd = -EBADF; - CGroupContext *cc; - CGroupRuntime *crt; int r, ifindex; assert(u); + assert(crt); - cc = unit_get_cgroup_context(u); - if (!cc) - return 0; - - crt = unit_get_cgroup_runtime(u); - if (!crt) - return 0; + CGroupContext *cc = ASSERT_PTR(unit_get_cgroup_context(u)); if (isempty(cc->bind_network_interface)) return 0; @@ -118,6 +111,21 @@ int bpf_bind_network_interface_install(Unit *u) { return 0; } +int bpf_bind_network_interface_install(Unit *u) { + CGroupRuntime *crt; + int r; + + assert(u); + + crt = unit_get_cgroup_runtime(u); + if (!crt) + return 0; + + r = bind_network_interface_install_impl(u, crt); + crt->initial_bind_network_interface_link_fd = safe_close(crt->initial_bind_network_interface_link_fd); + return r; +} + int bpf_bind_network_interface_serialize(Unit *u, FILE *f, FDSet *fds) { CGroupRuntime *crt; @@ -127,7 +135,7 @@ int bpf_bind_network_interface_serialize(Unit *u, FILE *f, FDSet *fds) { if (!crt) return 0; - return bpf_serialize_link(f, fds, "bind-interface-fd", crt->bpf_bind_network_interface_link); + return bpf_serialize_link(f, fds, "bind-iface-bpf-fd", crt->bpf_bind_network_interface_link); } #else /* ! BPF_FRAMEWORK */ diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 3e37f0444d5..a9dde6ce9d2 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -4199,6 +4199,8 @@ CGroupRuntime* cgroup_runtime_new(void) { .ipv4_deny_map_fd = -EBADF, .ipv6_deny_map_fd = -EBADF, + .initial_bind_network_interface_link_fd = -EBADF, + .cgroup_invalidated_mask = _CGROUP_MASK_ALL, .deserialized_cgroup_realized = -1, @@ -4233,6 +4235,7 @@ CGroupRuntime* cgroup_runtime_free(CGroupRuntime *crt) { #endif fdset_free(crt->initial_restrict_ifaces_link_fds); + safe_close(crt->initial_bind_network_interface_link_fd); bpf_firewall_close(crt); @@ -4516,6 +4519,21 @@ int cgroup_runtime_deserialize_one(Unit *u, const char *key, const char *value, return 1; } + if (streq(key, "bind-iface-bpf-fd")) { + _cleanup_close_ int fd = -EBADF; + + fd = deserialize_fd(fds, value); + if (fd >= 0) { + CGroupRuntime *crt = unit_setup_cgroup_runtime(u); + if (!crt) + log_oom_debug(); + else + close_and_replace(crt->initial_bind_network_interface_link_fd, fd); + } + + return 1; + } + CGroupMemoryAccountingMetric mm = memory_accounting_metric_field_last_from_string(key); if (mm >= 0) { uint64_t c; diff --git a/src/core/cgroup.h b/src/core/cgroup.h index de091605d42..4f1a77392f3 100644 --- a/src/core/cgroup.h +++ b/src/core/cgroup.h @@ -325,6 +325,13 @@ typedef struct CGroupRuntime { struct bpf_link *restrict_ifaces_egress_bpf_link; #endif +#if BPF_FRAMEWORK + /* BPF link to BPF programs attached to cgroup/sock_create hooks and + * responsible for binding created sockets to a given VRF interface. */ + struct bpf_link *bpf_bind_network_interface_link; +#endif + int initial_bind_network_interface_link_fd; + bool cgroup_members_mask_valid:1; /* Reset cgroup accounting next time we fork something off */ @@ -334,12 +341,6 @@ typedef struct CGroupRuntime { bool warned_clamping_cpu_quota_period:1; int deserialized_cgroup_realized; /* tristate, for backwards compat */ - -#if BPF_FRAMEWORK - /* BPF link to BPF programs attached to cgroup/sock_create hooks and - * responsible for binding created sockets to a given VRF interface. */ - struct bpf_link *bpf_bind_network_interface_link; -#endif } CGroupRuntime; uint64_t cgroup_context_cpu_weight(CGroupContext *c, ManagerState state);