shared, bpf: add bpf link serialization
core: serialize socket_bind bpf links
This commit is contained in:
+49
-1
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user