diff options
Diffstat (limited to '')
-rw-r--r-- | src/core/socket-bind.c | 50 | ||||
-rw-r--r-- | src/core/socket-bind.h | 7 | ||||
-rw-r--r-- | src/core/unit-serialize.c | 20 | ||||
-rw-r--r-- | src/core/unit.c | 2 | ||||
-rw-r--r-- | src/core/unit.h | 1 | ||||
-rw-r--r-- | src/shared/bpf-link.c | 16 | ||||
-rw-r--r-- | src/shared/bpf-link.h | 4 |
7 files changed, 99 insertions, 1 deletions
diff --git a/src/core/socket-bind.c b/src/core/socket-bind.c index f03bed5888..ed6c36c11f 100644 --- a/src/core/socket-bind.c +++ b/src/core/socket-bind.c @@ -132,7 +132,25 @@ int socket_bind_supported(void) { return can_link_bpf_program(obj->progs.sd_bind4); } -int socket_bind_install(Unit *u) { +int socket_bind_add_initial_link_fd(Unit *u, int fd) { + int r; + + assert(u); + + if (!u->initial_socket_bind_link_fds) { + u->initial_socket_bind_link_fds = fdset_new(); + if (!u->initial_socket_bind_link_fds) + return log_oom(); + } + + r = fdset_put(u->initial_socket_bind_link_fds, fd); + if (r < 0) + return log_unit_error_errno(u, r, "Failed to put socket-bind BPF link fd %d to initial fdset", fd); + + return 0; +} + +static int socket_bind_install_impl(Unit *u) { _cleanup_(bpf_link_freep) struct bpf_link *ipv4 = NULL, *ipv6 = NULL; _cleanup_(socket_bind_bpf_freep) struct socket_bind_bpf *obj = NULL; _cleanup_free_ char *cgroup_path = NULL; @@ -177,14 +195,44 @@ int socket_bind_install(Unit *u) { return 0; } + +int socket_bind_install(Unit *u) { + int r = socket_bind_install_impl(u); + if (r == -ENOMEM) + return r; + + fdset_close(u->initial_socket_bind_link_fds); + + return r; +} + +int serialize_socket_bind(Unit *u, FILE *f, FDSet *fds) { + int r; + + assert(u); + + r = serialize_bpf_link(f, fds, "ipv4-socket-bind-bpf-link", u->ipv4_socket_bind_link); + if (r < 0) + return r; + + return serialize_bpf_link(f, fds, "ipv6-socket-bind-bpf-link", u->ipv6_socket_bind_link); +} + #else /* ! BPF_FRAMEWORK */ int socket_bind_supported(void) { return 0; } +int socket_bind_add_initial_link_fd(Unit *u, int fd) { + return 0; +} + int socket_bind_install(Unit *u) { log_unit_debug(u, "Failed to install socket bind: BPF framework is not supported"); return 0; } +int serialize_socket_bind(Unit *u, FILE *f, FDSet *fds) { + return 0; +} #endif diff --git a/src/core/socket-bind.h b/src/core/socket-bind.h index 58b73579ac..2a6e71a9b9 100644 --- a/src/core/socket-bind.h +++ b/src/core/socket-bind.h @@ -1,8 +1,15 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once +#include "fdset.h" #include "unit.h" int socket_bind_supported(void); +/* Add BPF link fd created before daemon-reload or daemon-reexec. + * FDs will be closed at the end of socket_bind_install. */ +int socket_bind_add_initial_link_fd(Unit *u, int fd); + int socket_bind_install(Unit *u); + +int serialize_socket_bind(Unit *u, FILE *f, FDSet *fds); diff --git a/src/core/unit-serialize.c b/src/core/unit-serialize.c index 3f099248ce..509210ad5e 100644 --- a/src/core/unit-serialize.c +++ b/src/core/unit-serialize.c @@ -7,6 +7,7 @@ #include "format-util.h" #include "parse-util.h" #include "serialize.h" +#include "socket-bind.h" #include "string-table.h" #include "unit-serialize.h" #include "user-util.h" @@ -151,6 +152,8 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) { (void) serialize_cgroup_mask(f, "cgroup-enabled-mask", u->cgroup_enabled_mask); (void) serialize_cgroup_mask(f, "cgroup-invalidated-mask", u->cgroup_invalidated_mask); + (void) serialize_socket_bind(u, f, fds); + if (uid_is_valid(u->ref_uid)) (void) serialize_item_format(f, "ref-uid", UID_FMT, u->ref_uid); if (gid_is_valid(u->ref_gid)) @@ -362,6 +365,23 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { else if (MATCH_DESERIALIZE_IMMEDIATE("cgroup-invalidated-mask", l, v, cg_mask_from_string, u->cgroup_invalidated_mask)) continue; + else if (STR_IN_SET(l, "ipv4-socket-bind-bpf-link-fd", "ipv6-socket-bind-bpf-link-fd")) { + int fd; + + if (safe_atoi(v, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) + log_unit_debug(u, "Failed to parse %s value: %s, ignoring.", l, v); + else { + if (fdset_remove(fds, fd) < 0) { + log_unit_debug(u, "Failed to remove %s value=%d from fdset", l, fd); + + continue; + } + + (void) socket_bind_add_initial_link_fd(u, fd); + } + continue; + } + else if (streq(l, "ref-uid")) { uid_t uid; diff --git a/src/core/unit.c b/src/core/unit.c index e8c0631429..6ef90eea0e 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -667,6 +667,8 @@ Unit* unit_free(Unit *u) { if (u->on_console) manager_unref_console(u->manager); + + fdset_free(u->initial_socket_bind_link_fds); #if BPF_FRAMEWORK bpf_link_free(u->ipv4_socket_bind_link); bpf_link_free(u->ipv6_socket_bind_link); diff --git a/src/core/unit.h b/src/core/unit.h index a124376b78..5bc1237ce0 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -309,6 +309,7 @@ typedef struct Unit { * attached to unit cgroup by provided program fd and attach type. */ Hashmap *bpf_foreign_by_key; + FDSet *initial_socket_bind_link_fds; #if BPF_FRAMEWORK /* BPF links to BPF programs attached to cgroup/bind{4|6} hooks and * responsible for allowing or denying a unit to bind(2) to a socket diff --git a/src/shared/bpf-link.c b/src/shared/bpf-link.c index 94d1a8c7ac..f718cb7d2d 100644 --- a/src/shared/bpf-link.c +++ b/src/shared/bpf-link.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #include "bpf-link.h" +#include "serialize.h" bool can_link_bpf_program(struct bpf_program *prog) { _cleanup_(bpf_link_freep) struct bpf_link *link = NULL; @@ -14,6 +15,21 @@ bool can_link_bpf_program(struct bpf_program *prog) { return libbpf_get_error(link) == -EBADF; } +int serialize_bpf_link(FILE *f, FDSet *fds, const char *key, struct bpf_link *link) { + int fd; + + assert(key); + + if (!link) + return -ENOENT; + + if (libbpf_get_error(link) != 0) + return -EINVAL; + + fd = bpf_link__fd(link); + return serialize_fd(f, fds, key, fd); +} + struct bpf_link *bpf_link_free(struct bpf_link *link) { /* bpf_link__destroy handles link == NULL case */ (void) bpf_link__destroy(link); diff --git a/src/shared/bpf-link.h b/src/shared/bpf-link.h index 7d529ad2cd..095465b07c 100644 --- a/src/shared/bpf-link.h +++ b/src/shared/bpf-link.h @@ -3,10 +3,14 @@ #pragma once #include <bpf/libbpf.h> +#include <stdio.h> +#include "fdset.h" #include "macro.h" bool can_link_bpf_program(struct bpf_program *prog); +int serialize_bpf_link(FILE *f, FDSet *fds, const char *key, struct bpf_link *link); + struct bpf_link *bpf_link_free(struct bpf_link *p); DEFINE_TRIVIAL_CLEANUP_FUNC(struct bpf_link *, bpf_link_free); |