core/cgroup: fix potential bpf link fd leak during deserialization

Also add a comment explaining the deserialization mechanism, as requested
in https://github.com/systemd/systemd/pull/40202#discussion_r2649274628
This commit is contained in:
Mike Yuan
2025-12-27 20:51:05 +01:00
parent d90cfb7e30
commit e78f615763
+28 -18
View File
@@ -4459,34 +4459,24 @@ int cgroup_runtime_deserialize_one(Unit *u, const char *key, const char *value,
if (MATCH_DESERIALIZE_IMMEDIATE(u, "cgroup-invalidated-mask", key, value, cg_mask_from_string, cgroup_invalidated_mask))
return 1;
if (STR_IN_SET(key, "ipv4-socket-bind-bpf-link-fd", "ipv6-socket-bind-bpf-link-fd")) {
int fd;
fd = deserialize_fd(fds, value);
if (fd >= 0)
(void) bpf_socket_bind_add_initial_link_fd(u, fd);
return 1;
}
if (STR_IN_SET(key,
"ip-bpf-ingress-installed", "ip-bpf-egress-installed",
"bpf-device-control-installed",
"ip-bpf-ingress-installed", "ip-bpf-egress-installed",
"ip-bpf-custom-ingress-installed", "ip-bpf-custom-egress-installed")) {
CGroupRuntime *crt = unit_setup_cgroup_runtime(u);
if (!crt)
log_oom_debug();
else {
if (streq(key, "bpf-device-control-installed"))
(void) bpf_program_deserialize_attachment(value, fds, &crt->bpf_device_control_installed);
if (streq(key, "ip-bpf-ingress-installed"))
(void) bpf_program_deserialize_attachment(value, fds, &crt->ip_bpf_ingress_installed);
if (streq(key, "ip-bpf-egress-installed"))
(void) bpf_program_deserialize_attachment(value, fds, &crt->ip_bpf_egress_installed);
if (streq(key, "bpf-device-control-installed"))
(void) bpf_program_deserialize_attachment(value, fds, &crt->bpf_device_control_installed);
if (streq(key, "ip-bpf-custom-ingress-installed"))
(void) bpf_program_deserialize_attachment_set(value, fds, &crt->ip_bpf_custom_ingress_installed);
@@ -4497,12 +4487,32 @@ int cgroup_runtime_deserialize_one(Unit *u, const char *key, const char *value,
return 1;
}
if (streq(key, "restrict-ifaces-bpf-fd")) {
int fd;
/* We keep the previous bpf link fds stashed until we reattach anew, to close the window where
* the cgroup restrictions would otherwise be lifted. */
if (STR_IN_SET(key, "ipv4-socket-bind-bpf-link-fd", "ipv6-socket-bind-bpf-link-fd")) {
_cleanup_close_ int fd = -EBADF;
fd = deserialize_fd(fds, value);
if (fd >= 0)
(void) bpf_restrict_ifaces_add_initial_link_fd(u, fd);
if (fd >= 0) {
r = bpf_socket_bind_add_initial_link_fd(u, fd);
if (r >= 0)
TAKE_FD(fd);
}
return 1;
}
if (streq(key, "restrict-ifaces-bpf-fd")) {
_cleanup_close_ int fd = -EBADF;
fd = deserialize_fd(fds, value);
if (fd >= 0) {
r = bpf_restrict_ifaces_add_initial_link_fd(u, fd);
if (r >= 0)
TAKE_FD(fd);
}
return 1;
}