shared, bpf: add bpf link serialization

core: serialize socket_bind bpf links
This commit is contained in:
Julia Kartseva
2021-04-26 16:26:24 -07:00
parent 8dd210ab66
commit 3d027d4d60
7 changed files with 99 additions and 1 deletions
+49 -1
View File
@@ -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
+7
View File
@@ -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);
+20
View File
@@ -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;
+2
View File
@@ -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);
+1
View File
@@ -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
+16
View File
@@ -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);
+4
View File
@@ -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);