From 8ac16654bcff1a056ea1b629897133b6e5ea4c98 Mon Sep 17 00:00:00 2001 From: Chris Down Date: Mon, 5 Oct 2026 13:42:33 +0200 Subject: [PATCH] core: Don't leak BPF links when realizing a cgroup again cgroup_context_apply() attaches the BPF programs again whenever the cgroup is realised again, for example, if someone does set-property or daemon-relaod. As it is now, their installers overwrite the links of the previous installation without freeing them, so the previous programs stay attached until the cgroup is removed, and keep enforcing whatever settings they were loaded with. For example, a unit with SocketBindDeny=any that is allowed to bind to a port with "systemctl set-property foo.service SocketBindAllow=tcp:1234" still cannot do so once its cgroup is realised again, as the previous program keeps denying it. Whoops! To fix this let's free the previous links once the new ones are attached. (cherry picked from commit 2f11fb19b7292339632e9b396fcab12729cde1ff) --- src/core/bpf-bind-iface.c | 2 +- src/core/bpf-restrict-ifaces.c | 4 ++-- src/core/bpf-socket-bind.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/core/bpf-bind-iface.c b/src/core/bpf-bind-iface.c index 1ba643a116..f3391c2a6a 100644 --- a/src/core/bpf-bind-iface.c +++ b/src/core/bpf-bind-iface.c @@ -103,7 +103,7 @@ static int bind_network_interface_install_impl(Unit *u, CGroupRuntime *crt) { return log_unit_error_errno(u, r, "bind-interface: Failed to create cgroup link: %m"); /* Store the link in CGroupRuntime */ - crt->bpf_bind_network_interface_link = TAKE_PTR(link); + free_and_replace_full(crt->bpf_bind_network_interface_link, link, bpf_link_free); log_unit_debug(u, "bind-interface: Successfully installed VRF binding for interface '%s' (ifindex=%d)", cc->bind_network_interface, ifindex); diff --git a/src/core/bpf-restrict-ifaces.c b/src/core/bpf-restrict-ifaces.c index e30d15cd25..ce6c2ec9b3 100644 --- a/src/core/bpf-restrict-ifaces.c +++ b/src/core/bpf-restrict-ifaces.c @@ -138,8 +138,8 @@ static int restrict_ifaces_install_impl(Unit *u, CGroupRuntime *crt) { if (r != 0) return log_unit_error_errno(u, r, "restrict-interfaces: Failed to create egress cgroup link: %m"); - crt->restrict_ifaces_ingress_bpf_link = TAKE_PTR(ingress_link); - crt->restrict_ifaces_egress_bpf_link = TAKE_PTR(egress_link); + free_and_replace_full(crt->restrict_ifaces_ingress_bpf_link, ingress_link, bpf_link_free); + free_and_replace_full(crt->restrict_ifaces_egress_bpf_link, egress_link, bpf_link_free); return 0; } diff --git a/src/core/bpf-socket-bind.c b/src/core/bpf-socket-bind.c index b4bf37b41e..797fb170f5 100644 --- a/src/core/bpf-socket-bind.c +++ b/src/core/bpf-socket-bind.c @@ -206,8 +206,8 @@ static int socket_bind_install_impl(Unit *u) { return log_unit_error_errno(u, r, "bpf-socket-bind: Failed to link '%s' cgroup-bpf program: %m", sym_bpf_program__name(obj->progs.sd_bind6)); - crt->ipv4_socket_bind_link = TAKE_PTR(ipv4); - crt->ipv6_socket_bind_link = TAKE_PTR(ipv6); + free_and_replace_full(crt->ipv4_socket_bind_link, ipv4, bpf_link_free); + free_and_replace_full(crt->ipv6_socket_bind_link, ipv6, bpf_link_free); return 0; }