]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core/cgroup: fix bpf-bind-iface serialization
authorMike Yuan <me@yhndnzj.com>
Wed, 24 Dec 2025 18:20:48 +0000 (19:20 +0100)
committerMike Yuan <me@yhndnzj.com>
Sat, 27 Dec 2025 22:44:53 +0000 (23:44 +0100)
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.

src/core/bpf-bind-iface.c
src/core/cgroup.c
src/core/cgroup.h

index ea439d307ba1d29123c565f5b946787254ce4c38..6b11e83543f00d0d313d30a90ec8dfb7f69b9f6d 100644 (file)
@@ -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 */
index 3e37f0444d5fcb7fc37b790fd04183c652002647..a9dde6ce9d2a13e3a5cf56ab1da4fbc6d0e3ada5 100644 (file)
@@ -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;
index de091605d42690e6b91f8b8b5874f979ceb1984e..4f1a77392f31567c47e344ea7aa214d9b1a5ab83 100644 (file)
@@ -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);