From e2490f73849181d840bdbb6265b8df2bb0111062 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Fri, 9 Sep 2022 10:27:57 +0200 Subject: [PATCH 1/4] Bump libbpf version to 0.7 We already depend on the skeleton APIs introduced in libbpf 0.7 so let's bump our minimum version to reflect that. We don't enforce bpf compilation on mkosi anymore since not all distros have sufficiently up-to-date libbpf available. --- README | 2 +- meson.build | 2 +- mkosi.build | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README b/README index cc0782ecbf..fa5d3aca1b 100644 --- a/README +++ b/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) diff --git a/meson.build b/meson.build index e76cc1dc6b..0b5fdd1737 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.2.0' +libbpf_version_requirement = '>= 0.7.0' if bpf_compiler == 'gcc' libbpf_version_requirement = '>= 1.0.0' endif diff --git a/mkosi.build b/mkosi.build index 1154e738f4..07f9bb21a6 100755 --- a/mkosi.build +++ b/mkosi.build @@ -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" From 6b8085db68aef9ce7ea3f628a059ce80eaa3d9f3 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Wed, 31 Aug 2022 11:59:52 +0200 Subject: [PATCH 2/4] libbpf: Remove use of deprecated APIs --- src/core/bpf-lsm.c | 11 ++++++----- src/core/bpf-socket-bind.c | 6 +++--- src/core/bpf/restrict_fs/restrict-fs.bpf.c | 2 +- src/core/bpf/socket_bind/socket-bind.bpf.c | 2 +- src/core/restrict-ifaces.c | 4 ++-- src/shared/bpf-dlopen.c | 12 ++++++------ src/shared/bpf-dlopen.h | 6 +++--- 7 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/core/bpf-lsm.c b/src/core/bpf-lsm.c index f3b9339558..33c9322e7e 100644 --- a/src/core/bpf-lsm.c +++ b/src/core/bpf-lsm.c @@ -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 = sym_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 = sym_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"); diff --git a/src/core/bpf-socket-bind.c b/src/core/bpf-socket-bind.c index 30e5b2f392..790813bdbe 100644 --- a/src/core/bpf-socket-bind.c +++ b/src/core/bpf-socket-bind.c @@ -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 (!sym_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/bpf/restrict_fs/restrict-fs.bpf.c b/src/core/bpf/restrict_fs/restrict-fs.bpf.c index 99940bedfd..522a029785 100644 --- a/src/core/bpf/restrict_fs/restrict-fs.bpf.c +++ b/src/core/bpf/restrict_fs/restrict-fs.bpf.c @@ -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); diff --git a/src/core/bpf/socket_bind/socket-bind.bpf.c b/src/core/bpf/socket_bind/socket-bind.bpf.c index 8004400e6c..b7972a887a 100644 --- a/src/core/bpf/socket_bind/socket-bind.bpf.c +++ b/src/core/bpf/socket_bind/socket-bind.bpf.c @@ -18,7 +18,7 @@ #include /* - * 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); diff --git a/src/core/restrict-ifaces.c b/src/core/restrict-ifaces.c index a0ecaff814..c0daa38a03 100644 --- a/src/core/restrict-ifaces.c +++ b/src/core/restrict-ifaces.c @@ -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 (!sym_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-dlopen.c b/src/shared/bpf-dlopen.c index d8e778794c..07c237cc2f 100644 --- a/src/shared/bpf-dlopen.c +++ b/src/shared/bpf-dlopen.c @@ -13,8 +13,8 @@ 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,7 +23,7 @@ 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 *); @@ -51,8 +51,8 @@ int dlopen_bpf(void) { 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_create), + 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,10 +61,10 @@ 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), + DLSYM_ARG(libbpf_probe_bpf_prog_type), DLSYM_ARG(libbpf_set_print), DLSYM_ARG(libbpf_get_error)); if (r < 0) diff --git a/src/shared/bpf-dlopen.h b/src/shared/bpf-dlopen.h index f0d40325d9..16b23ef6c5 100644 --- a/src/shared/bpf-dlopen.h +++ b/src/shared/bpf-dlopen.h @@ -12,8 +12,8 @@ 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_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 *); extern int (*sym_bpf_map__set_inner_map_fd)(struct bpf_map *, int); @@ -24,8 +24,8 @@ 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 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 *); From 5a967e28873816806a8f1e7c6c7d1ac28369f8b9 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Fri, 9 Sep 2022 10:38:03 +0200 Subject: [PATCH 3/4] Try to load libbpf.so.1 as well libbpf had a soname bump. Our usage of libbpf is compatible with both libbpf.so.0 and libbpf.so.1, so let's try to load from both. --- src/shared/bpf-dlopen.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/shared/bpf-dlopen.c b/src/shared/bpf-dlopen.c index 07c237cc2f..ad5432a949 100644 --- a/src/shared/bpf-dlopen.c +++ b/src/shared/bpf-dlopen.c @@ -3,6 +3,7 @@ #include "dlfcn-util.h" #include "bpf-dlopen.h" #include "log.h" +#include "strv.h" #if HAVE_LIBBPF static void *bpf_dl = NULL; @@ -45,8 +46,9 @@ static int bpf_print_func(enum libbpf_print_level level, const char *fmt, va_lis int dlopen_bpf(void) { int r; - r = dlopen_many_sym_or_warn( - &bpf_dl, "libbpf.so.0", LOG_DEBUG, + FOREACH_STRING(f, "libbpf.so.1", "libbpf.so.0") { + r = dlopen_many_sym_or_warn( + &bpf_dl, f, LOG_DEBUG, DLSYM_ARG(bpf_link__destroy), DLSYM_ARG(bpf_link__fd), DLSYM_ARG(bpf_map__fd), @@ -67,6 +69,9 @@ int dlopen_bpf(void) { 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; From 87e462f71361a47b154865dc14032a27580dd4cb Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Fri, 30 Sep 2022 19:25:18 +0900 Subject: [PATCH 4/4] libbpf: add compat helpers for libbpf down to 0.1.0 - new symbols are available from libbpf 0.6.0 so could be used with libbpf.so.0, but we're sure the old symbols will be there and this simplifies code - detection at runtime should always work, regardless of whether systemd has been compiled with older or newer libbpf and runs with older or newer libbpf --- meson.build | 2 +- src/core/bpf-lsm.c | 4 +-- src/core/bpf-socket-bind.c | 2 +- src/core/restrict-ifaces.c | 2 +- src/shared/bpf-compat.h | 54 ++++++++++++++++++++++++++++++++++++++ src/shared/bpf-dlopen.c | 39 ++++++++++++++++++++------- src/shared/bpf-dlopen.h | 4 +-- 7 files changed, 90 insertions(+), 17 deletions(-) create mode 100644 src/shared/bpf-compat.h 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 #include +#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 *);