mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-03-10 00:58:20 +03:00
Merge pull request #24511 from martinetd/bpf1
libbpf: Add libbpf 1.0.0 compat
This commit is contained in:
commit
c76691d708
2
README
2
README
@ -181,7 +181,7 @@ REQUIREMENTS:
|
||||
libcryptsetup (optional), >= 2.3.0 required for signed Verity images support
|
||||
libaudit (optional)
|
||||
libacl (optional)
|
||||
libbpf >= 0.2.0 (optional)
|
||||
libbpf >= 0.7.0 (optional)
|
||||
libfdisk >= 2.32 (from util-linux) (optional)
|
||||
libselinux (optional)
|
||||
liblzma (optional)
|
||||
|
@ -1050,7 +1050,7 @@ want_bpf_framework = get_option('bpf-framework')
|
||||
bpf_compiler = get_option('bpf-compiler')
|
||||
bpf_framework_required = want_bpf_framework == 'true'
|
||||
|
||||
libbpf_version_requirement = '>= 0.2.0'
|
||||
libbpf_version_requirement = '>= 0.1.0'
|
||||
if bpf_compiler == 'gcc'
|
||||
libbpf_version_requirement = '>= 1.0.0'
|
||||
endif
|
||||
|
@ -149,7 +149,7 @@ if [ ! -f "$BUILDDIR"/build.ninja ] ; then
|
||||
-D gnu-efi=true \
|
||||
-D kernel-install=true \
|
||||
-D analyze=true \
|
||||
-D bpf-framework=true
|
||||
-D bpf-framework=auto
|
||||
fi
|
||||
|
||||
cd "$BUILDDIR"
|
||||
|
@ -65,14 +65,14 @@ static int prepare_restrict_fs_bpf(struct restrict_fs_bpf **ret_obj) {
|
||||
return log_error_errno(errno, "bpf-lsm: Failed to open BPF object: %m");
|
||||
|
||||
/* TODO Maybe choose a number based on runtime information? */
|
||||
r = sym_bpf_map__resize(obj->maps.cgroup_hash, CGROUP_HASH_SIZE_MAX);
|
||||
r = sym_bpf_map__set_max_entries(obj->maps.cgroup_hash, CGROUP_HASH_SIZE_MAX);
|
||||
assert(r <= 0);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "bpf-lsm: Failed to resize BPF map '%s': %m",
|
||||
sym_bpf_map__name(obj->maps.cgroup_hash));
|
||||
|
||||
/* Dummy map to satisfy the verifier */
|
||||
inner_map_fd = sym_bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(uint32_t), sizeof(uint32_t), 128, 0);
|
||||
inner_map_fd = compat_bpf_map_create(BPF_MAP_TYPE_HASH, NULL, sizeof(uint32_t), sizeof(uint32_t), 128U, NULL);
|
||||
if (inner_map_fd < 0)
|
||||
return log_error_errno(errno, "bpf-lsm: Failed to create BPF map: %m");
|
||||
|
||||
@ -202,12 +202,13 @@ int lsm_bpf_unit_restrict_filesystems(Unit *u, const Set *filesystems, bool allo
|
||||
return log_unit_error_errno(u, SYNTHETIC_ERRNO(EINVAL),
|
||||
"bpf-lsm: BPF LSM object is not installed, has setup failed?");
|
||||
|
||||
int inner_map_fd = sym_bpf_create_map(
|
||||
int inner_map_fd = compat_bpf_map_create(
|
||||
BPF_MAP_TYPE_HASH,
|
||||
NULL,
|
||||
sizeof(uint32_t),
|
||||
sizeof(uint32_t),
|
||||
128, /* Should be enough for all filesystem types */
|
||||
0);
|
||||
128U, /* Should be enough for all filesystem types */
|
||||
NULL);
|
||||
if (inner_map_fd < 0)
|
||||
return log_unit_error_errno(u, errno, "bpf-lsm: Failed to create inner BPF map: %m");
|
||||
|
||||
|
@ -79,11 +79,11 @@ static int prepare_socket_bind_bpf(
|
||||
if (!obj)
|
||||
return log_unit_full_errno(u, u ? LOG_ERR : LOG_DEBUG, errno, "bpf-socket-bind: Failed to open BPF object: %m");
|
||||
|
||||
if (sym_bpf_map__resize(obj->maps.sd_bind_allow, MAX(allow_count, 1u)) != 0)
|
||||
if (sym_bpf_map__set_max_entries(obj->maps.sd_bind_allow, MAX(allow_count, 1u)) != 0)
|
||||
return log_unit_full_errno(u, u ? LOG_ERR : LOG_WARNING, errno,
|
||||
"bpf-socket-bind: Failed to resize BPF map '%s': %m", sym_bpf_map__name(obj->maps.sd_bind_allow));
|
||||
|
||||
if (sym_bpf_map__resize(obj->maps.sd_bind_deny, MAX(deny_count, 1u)) != 0)
|
||||
if (sym_bpf_map__set_max_entries(obj->maps.sd_bind_deny, MAX(deny_count, 1u)) != 0)
|
||||
return log_unit_full_errno(u, u ? LOG_ERR : LOG_WARNING, errno,
|
||||
"bpf-socket-bind: Failed to resize BPF map '%s': %m", sym_bpf_map__name(obj->maps.sd_bind_deny));
|
||||
|
||||
@ -120,7 +120,7 @@ int bpf_socket_bind_supported(void) {
|
||||
if (!cgroup_bpf_supported())
|
||||
return false;
|
||||
|
||||
if (!sym_bpf_probe_prog_type(BPF_PROG_TYPE_CGROUP_SOCK_ADDR, /*ifindex=*/0)) {
|
||||
if (!compat_libbpf_probe_bpf_prog_type(BPF_PROG_TYPE_CGROUP_SOCK_ADDR, /*opts=*/NULL)) {
|
||||
log_debug("bpf-socket-bind: BPF program type cgroup_sock_addr is not supported");
|
||||
return false;
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ struct file {
|
||||
} __attribute__((preserve_access_index));
|
||||
|
||||
/*
|
||||
* max_entries is set from user space with the bpf_map__resize helper.
|
||||
* max_entries is set from user space with the bpf_map__set_max_entries helper.
|
||||
* */
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_HASH_OF_MAPS);
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
/*
|
||||
* max_entries is set from user space with bpf_map__resize helper.
|
||||
* max_entries is set from user space with bpf_map__set_max_entries helper.
|
||||
*/
|
||||
struct socket_bind_map_t {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY);
|
||||
|
@ -36,7 +36,7 @@ static int prepare_restrict_ifaces_bpf(
|
||||
if (!obj)
|
||||
return log_unit_full_errno(u, u ? LOG_ERR : LOG_DEBUG, errno, "restrict-interfaces: Failed to open BPF object: %m");
|
||||
|
||||
r = sym_bpf_map__resize(obj->maps.sd_restrictif, MAX(set_size(restrict_network_interfaces), 1u));
|
||||
r = sym_bpf_map__set_max_entries(obj->maps.sd_restrictif, MAX(set_size(restrict_network_interfaces), 1u));
|
||||
if (r != 0)
|
||||
return log_unit_full_errno(u, u ? LOG_ERR : LOG_WARNING, r,
|
||||
"restrict-interfaces: Failed to resize BPF map '%s': %m",
|
||||
@ -83,7 +83,7 @@ int restrict_network_interfaces_supported(void) {
|
||||
if (!cgroup_bpf_supported())
|
||||
return (supported = false);
|
||||
|
||||
if (!sym_bpf_probe_prog_type(BPF_PROG_TYPE_CGROUP_SKB, /*ifindex=*/0)) {
|
||||
if (!compat_libbpf_probe_bpf_prog_type(BPF_PROG_TYPE_CGROUP_SKB, /*opts=*/NULL)) {
|
||||
log_debug("restrict-interfaces: BPF program type cgroup_skb is not supported");
|
||||
return (supported = false);
|
||||
}
|
||||
|
54
src/shared/bpf-compat.h
Normal file
54
src/shared/bpf-compat.h
Normal file
@ -0,0 +1,54 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
/* libbpf has been moving quickly.
|
||||
* They added new symbols in the 0.x versions and shortly after removed
|
||||
* deprecated symbols in 1.0.
|
||||
* We only need bpf_map_create and libbpf_probe_bpf_prog_type so we work
|
||||
* around the incompatibility here by:
|
||||
* - declaring both symbols, and looking for either depending on the libbpf
|
||||
* so version we found
|
||||
* - having helpers that automatically use the appropriate version behind the
|
||||
* new API for easy cleanup later
|
||||
*
|
||||
* The advantage of doing this instead of only looking for the symbols declared at
|
||||
* compile time is that we can then load either the old or the new symbols at runtime
|
||||
* regardless of the version we were compiled with */
|
||||
|
||||
|
||||
/* declare the struct for libbpf <= 0.6.0 -- it causes no harm on newer versions */
|
||||
struct bpf_map_create_opts;
|
||||
|
||||
/* new symbols available from 0.7.0.
|
||||
* We need the symbols here:
|
||||
* - after bpf_map_create_opts struct has been defined for older libbpf
|
||||
* - before the compat static inline helpers that use them.
|
||||
* When removing this file move these back to bpf-dlopen.h */
|
||||
extern int (*sym_bpf_map_create)(enum bpf_map_type, const char *, __u32, __u32, __u32, const struct bpf_map_create_opts *);
|
||||
extern bool (*sym_libbpf_probe_bpf_prog_type)(enum bpf_prog_type, const void *);
|
||||
|
||||
/* compat symbols removed in libbpf 1.0 */
|
||||
extern int (*sym_bpf_create_map)(enum bpf_map_type, int key_size, int value_size, int max_entries, __u32 map_flags);
|
||||
extern bool (*sym_bpf_probe_prog_type)(enum bpf_prog_type, __u32);
|
||||
|
||||
/* helpers to use the available variant behind new API */
|
||||
static inline int compat_bpf_map_create(enum bpf_map_type map_type,
|
||||
const char *map_name,
|
||||
__u32 key_size,
|
||||
__u32 value_size,
|
||||
__u32 max_entries,
|
||||
const struct bpf_map_create_opts *opts) {
|
||||
if (sym_bpf_map_create)
|
||||
return sym_bpf_map_create(map_type, map_name, key_size,
|
||||
value_size, max_entries, opts);
|
||||
|
||||
return sym_bpf_create_map(map_type, key_size, value_size, max_entries,
|
||||
0 /* opts->map_flags, but opts is always NULL for us so skip build dependency on the type */);
|
||||
}
|
||||
|
||||
static inline int compat_libbpf_probe_bpf_prog_type(enum bpf_prog_type prog_type, const void *opts) {
|
||||
if (sym_libbpf_probe_bpf_prog_type)
|
||||
return sym_libbpf_probe_bpf_prog_type(prog_type, opts);
|
||||
|
||||
return sym_bpf_probe_prog_type(prog_type, 0);
|
||||
}
|
@ -3,18 +3,17 @@
|
||||
#include "dlfcn-util.h"
|
||||
#include "bpf-dlopen.h"
|
||||
#include "log.h"
|
||||
#include "strv.h"
|
||||
|
||||
#if HAVE_LIBBPF
|
||||
static void *bpf_dl = NULL;
|
||||
|
||||
struct bpf_link* (*sym_bpf_program__attach_cgroup)(struct bpf_program *, int);
|
||||
struct bpf_link* (*sym_bpf_program__attach_lsm)(struct bpf_program *);
|
||||
int (*sym_bpf_link__fd)(const struct bpf_link *);
|
||||
int (*sym_bpf_link__destroy)(struct bpf_link *);
|
||||
int (*sym_bpf_map__fd)(const struct bpf_map *);
|
||||
const char* (*sym_bpf_map__name)(const struct bpf_map *);
|
||||
int (*sym_bpf_create_map)(enum bpf_map_type, int key_size, int value_size, int max_entries, __u32 map_flags);
|
||||
int (*sym_bpf_map__resize)(struct bpf_map *, __u32);
|
||||
int (*sym_bpf_map_create)(enum bpf_map_type, const char *, __u32, __u32, __u32, const struct bpf_map_create_opts *);
|
||||
int (*sym_bpf_map__set_max_entries)(struct bpf_map *, __u32);
|
||||
int (*sym_bpf_map_update_elem)(int, const void *, const void *, __u64);
|
||||
int (*sym_bpf_map_delete_elem)(int, const void *);
|
||||
int (*sym_bpf_map__set_inner_map_fd)(struct bpf_map *, int);
|
||||
@ -23,11 +22,15 @@ int (*sym_bpf_object__load_skeleton)(struct bpf_object_skeleton *);
|
||||
int (*sym_bpf_object__attach_skeleton)(struct bpf_object_skeleton *);
|
||||
void (*sym_bpf_object__detach_skeleton)(struct bpf_object_skeleton *);
|
||||
void (*sym_bpf_object__destroy_skeleton)(struct bpf_object_skeleton *);
|
||||
bool (*sym_bpf_probe_prog_type)(enum bpf_prog_type, __u32);
|
||||
bool (*sym_libbpf_probe_bpf_prog_type)(enum bpf_prog_type, const void *);
|
||||
const char* (*sym_bpf_program__name)(const struct bpf_program *);
|
||||
libbpf_print_fn_t (*sym_libbpf_set_print)(libbpf_print_fn_t);
|
||||
long (*sym_libbpf_get_error)(const void *);
|
||||
|
||||
/* compat symbols removed in libbpf 1.0 */
|
||||
int (*sym_bpf_create_map)(enum bpf_map_type, int key_size, int value_size, int max_entries, __u32 map_flags);
|
||||
bool (*sym_bpf_probe_prog_type)(enum bpf_prog_type, __u32);
|
||||
|
||||
_printf_(2,0)
|
||||
static int bpf_print_func(enum libbpf_print_level level, const char *fmt, va_list ap) {
|
||||
#if !LOG_TRACE
|
||||
@ -43,16 +46,38 @@ static int bpf_print_func(enum libbpf_print_level level, const char *fmt, va_lis
|
||||
}
|
||||
|
||||
int dlopen_bpf(void) {
|
||||
void *dl;
|
||||
int r;
|
||||
|
||||
r = dlopen_many_sym_or_warn(
|
||||
&bpf_dl, "libbpf.so.0", LOG_DEBUG,
|
||||
dl = dlopen("libbpf.so.1", RTLD_LAZY);
|
||||
if (!dl) {
|
||||
/* libbpf < 1.0.0 (we rely on 0.1.0+) provide most symbols we care about, but
|
||||
* unfortunately not all until 0.7.0. See bpf-compat.h for more details.
|
||||
* Once we consider we can assume 0.7+ is present we can just use the same symbol
|
||||
* list for both files, and when we assume 1.0+ is present we can remove this dlopen */
|
||||
dl = dlopen("libbpf.so.0", RTLD_LAZY);
|
||||
if (!dl)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"neither libbpf.so.1 nor libbpf.so.0 are installed: %s", dlerror());
|
||||
|
||||
/* symbols deprecated in 1.0 we use as compat */
|
||||
r = dlsym_many_or_warn(dl, LOG_DEBUG,
|
||||
DLSYM_ARG(bpf_create_map),
|
||||
DLSYM_ARG(bpf_probe_prog_type));
|
||||
} else {
|
||||
/* symbols available from 0.7.0 */
|
||||
r = dlsym_many_or_warn(dl, LOG_DEBUG,
|
||||
DLSYM_ARG(bpf_map_create),
|
||||
DLSYM_ARG(libbpf_probe_bpf_prog_type));
|
||||
}
|
||||
|
||||
r = dlsym_many_or_warn(
|
||||
dl, LOG_DEBUG,
|
||||
DLSYM_ARG(bpf_link__destroy),
|
||||
DLSYM_ARG(bpf_link__fd),
|
||||
DLSYM_ARG(bpf_map__fd),
|
||||
DLSYM_ARG(bpf_map__name),
|
||||
DLSYM_ARG(bpf_create_map),
|
||||
DLSYM_ARG(bpf_map__resize),
|
||||
DLSYM_ARG(bpf_map__set_max_entries),
|
||||
DLSYM_ARG(bpf_map_update_elem),
|
||||
DLSYM_ARG(bpf_map_delete_elem),
|
||||
DLSYM_ARG(bpf_map__set_inner_map_fd),
|
||||
@ -61,7 +86,6 @@ int dlopen_bpf(void) {
|
||||
DLSYM_ARG(bpf_object__attach_skeleton),
|
||||
DLSYM_ARG(bpf_object__detach_skeleton),
|
||||
DLSYM_ARG(bpf_object__destroy_skeleton),
|
||||
DLSYM_ARG(bpf_probe_prog_type),
|
||||
DLSYM_ARG(bpf_program__attach_cgroup),
|
||||
DLSYM_ARG(bpf_program__attach_lsm),
|
||||
DLSYM_ARG(bpf_program__name),
|
||||
|
@ -6,14 +6,15 @@
|
||||
#include <bpf/bpf.h>
|
||||
#include <bpf/libbpf.h>
|
||||
|
||||
#include "bpf-compat.h"
|
||||
|
||||
extern struct bpf_link* (*sym_bpf_program__attach_cgroup)(struct bpf_program *, int);
|
||||
extern struct bpf_link* (*sym_bpf_program__attach_lsm)(struct bpf_program *);
|
||||
extern int (*sym_bpf_link__fd)(const struct bpf_link *);
|
||||
extern int (*sym_bpf_link__destroy)(struct bpf_link *);
|
||||
extern int (*sym_bpf_map__fd)(const struct bpf_map *);
|
||||
extern const char* (*sym_bpf_map__name)(const struct bpf_map *);
|
||||
extern int (*sym_bpf_create_map)(enum bpf_map_type, int key_size, int value_size, int max_entries, __u32 map_flags);
|
||||
extern int (*sym_bpf_map__resize)(struct bpf_map *, __u32);
|
||||
extern int (*sym_bpf_map__set_max_entries)(struct bpf_map *, __u32);
|
||||
extern int (*sym_bpf_map_update_elem)(int, const void *, const void *, __u64);
|
||||
extern int (*sym_bpf_map_delete_elem)(int, const void *);
|
||||
extern int (*sym_bpf_map__set_inner_map_fd)(struct bpf_map *, int);
|
||||
@ -24,7 +25,6 @@ extern int (*sym_bpf_object__load_skeleton)(struct bpf_object_skeleton *);
|
||||
extern int (*sym_bpf_object__attach_skeleton)(struct bpf_object_skeleton *);
|
||||
extern void (*sym_bpf_object__detach_skeleton)(struct bpf_object_skeleton *);
|
||||
extern void (*sym_bpf_object__destroy_skeleton)(struct bpf_object_skeleton *);
|
||||
extern bool (*sym_bpf_probe_prog_type)(enum bpf_prog_type, __u32);
|
||||
extern const char* (*sym_bpf_program__name)(const struct bpf_program *);
|
||||
extern libbpf_print_fn_t (*sym_libbpf_set_print)(libbpf_print_fn_t);
|
||||
extern long (*sym_libbpf_get_error)(const void *);
|
||||
|
Loading…
x
Reference in New Issue
Block a user