summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--meson.build2
-rw-r--r--src/core/bpf-lsm.c4
-rw-r--r--src/core/bpf-socket-bind.c2
-rw-r--r--src/core/restrict-ifaces.c2
-rw-r--r--src/shared/bpf-compat.h54
-rw-r--r--src/shared/bpf-dlopen.c39
-rw-r--r--src/shared/bpf-dlopen.h4
7 files changed, 90 insertions, 17 deletions
diff --git a/meson.build b/meson.build
index 0b5fdd1737..b543a83761 100644
--- a/meson.build
+++ b/meson.build
@@ -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.7.0'
+libbpf_version_requirement = '>= 0.1.0'
if bpf_compiler == 'gcc'
libbpf_version_requirement = '>= 1.0.0'
endif
diff --git a/src/core/bpf-lsm.c b/src/core/bpf-lsm.c
index 33c9322e7e..173221b9f1 100644
--- a/src/core/bpf-lsm.c
+++ b/src/core/bpf-lsm.c
@@ -72,7 +72,7 @@ static int prepare_restrict_fs_bpf(struct restrict_fs_bpf **ret_obj) {
sym_bpf_map__name(obj->maps.cgroup_hash));
/* Dummy map to satisfy the verifier */
- inner_map_fd = sym_bpf_map_create(BPF_MAP_TYPE_HASH, NULL, sizeof(uint32_t), sizeof(uint32_t), 128U, NULL);
+ 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,7 +202,7 @@ 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_map_create(
+ int inner_map_fd = compat_bpf_map_create(
BPF_MAP_TYPE_HASH,
NULL,
sizeof(uint32_t),
diff --git a/src/core/bpf-socket-bind.c b/src/core/bpf-socket-bind.c
index 790813bdbe..660ffdb723 100644
--- a/src/core/bpf-socket-bind.c
+++ b/src/core/bpf-socket-bind.c
@@ -120,7 +120,7 @@ int bpf_socket_bind_supported(void) {
if (!cgroup_bpf_supported())
return false;
- if (!sym_libbpf_probe_bpf_prog_type(BPF_PROG_TYPE_CGROUP_SOCK_ADDR, /*opts=*/NULL)) {
+ 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;
}
diff --git a/src/core/restrict-ifaces.c b/src/core/restrict-ifaces.c
index c0daa38a03..134f70a07b 100644
--- a/src/core/restrict-ifaces.c
+++ b/src/core/restrict-ifaces.c
@@ -83,7 +83,7 @@ int restrict_network_interfaces_supported(void) {
if (!cgroup_bpf_supported())
return (supported = false);
- if (!sym_libbpf_probe_bpf_prog_type(BPF_PROG_TYPE_CGROUP_SKB, /*opts=*/NULL)) {
+ 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);
}
diff --git a/src/shared/bpf-compat.h b/src/shared/bpf-compat.h
new file mode 100644
index 0000000000..04ade82fc1
--- /dev/null
+++ b/src/shared/bpf-compat.h
@@ -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);
+}
diff --git a/src/shared/bpf-dlopen.c b/src/shared/bpf-dlopen.c
index ad5432a949..2556053cbb 100644
--- a/src/shared/bpf-dlopen.c
+++ b/src/shared/bpf-dlopen.c
@@ -6,8 +6,6 @@
#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 *);
@@ -29,6 +27,10 @@ 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
@@ -44,16 +46,37 @@ static int bpf_print_func(enum libbpf_print_level level, const char *fmt, va_lis
}
int dlopen_bpf(void) {
+ void *dl;
int r;
- FOREACH_STRING(f, "libbpf.so.1", "libbpf.so.0") {
- r = dlopen_many_sym_or_warn(
- &bpf_dl, f, 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_map_create),
DLSYM_ARG(bpf_map__set_max_entries),
DLSYM_ARG(bpf_map_update_elem),
DLSYM_ARG(bpf_map_delete_elem),
@@ -66,12 +89,8 @@ int dlopen_bpf(void) {
DLSYM_ARG(bpf_program__attach_cgroup),
DLSYM_ARG(bpf_program__attach_lsm),
DLSYM_ARG(bpf_program__name),
- DLSYM_ARG(libbpf_probe_bpf_prog_type),
DLSYM_ARG(libbpf_set_print),
DLSYM_ARG(libbpf_get_error));
- if (r >= 0)
- break;
- }
if (r < 0)
return r;
diff --git a/src/shared/bpf-dlopen.h b/src/shared/bpf-dlopen.h
index 16b23ef6c5..95951e63e0 100644
--- a/src/shared/bpf-dlopen.h
+++ b/src/shared/bpf-dlopen.h
@@ -6,13 +6,14 @@
#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_map_create)(enum bpf_map_type, const char *, __u32, __u32, __u32, const struct bpf_map_create_opts *);
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 *);
@@ -25,7 +26,6 @@ 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 const char* (*sym_bpf_program__name)(const struct bpf_program *);
-extern bool (*sym_libbpf_probe_bpf_prog_type)(enum bpf_prog_type, const void *);
extern libbpf_print_fn_t (*sym_libbpf_set_print)(libbpf_print_fn_t);
extern long (*sym_libbpf_get_error)(const void *);