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 cc0782ecbf1..fa5d3aca1b9 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 e76cc1dc6be..0b5fdd17374 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 1154e738f4c..07f9bb21a69 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 f3b93395582..33c9322e7ed 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 30e5b2f3927..790813bdbe4 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 99940bedfd8..522a029785d 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 8004400e6ca..b7972a887a4 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 a0ecaff814b..c0daa38a03f 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 d8e778794c2..07c237cc2f1 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 f0d40325d90..16b23ef6c51 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 07c237cc2f1..ad5432a9494 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 0b5fdd17374..b543a837619 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 33c9322e7ed..173221b9f17 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 790813bdbe4..660ffdb7232 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 c0daa38a03f..134f70a07b8 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 00000000000..04ade82fc1e --- /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 ad5432a9494..2556053cbb6 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 16b23ef6c51..95951e63e0e 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 *);