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;
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
/* 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);
#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"
(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))
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;
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);
* 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
/* 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;
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);
#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);