* fine given that LGPL-2.1-or-later downgrades to GPL if needed.
*/
-#include "bpf-dlopen.h" /* IWYU pragma: keep */
+#include "bpf-util.h" /* IWYU pragma: keep */
/* libbpf is used via dlopen(), so rename symbols */
#define bpf_object__attach_skeleton sym_bpf_object__attach_skeleton
# Keeping it out of bpf_programs_by_name also keeps it out of the
# clang-tidy per-source test loop, which would otherwise fall back
# to a BPF compile_commands.json entry (no -Isrc/shared) and fail
- # to resolve bpf-dlopen.h.
+ # to resolve bpf-util.h.
configure_file(
input : 'bpf-skel-wrapper.h.in',
output : name + '-skel.h',
#if BPF_FRAMEWORK
/* libbpf, clang, llvm and bpftool compile time dependencies are satisfied */
-#include "bpf-dlopen.h"
+#include "bpf-util.h"
#include "bpf-link.h"
#include "bind-iface-skel.h"
#if BPF_FRAMEWORK
/* libbpf, clang and llc compile time dependencies are satisfied */
-#include "bpf-dlopen.h"
+#include "bpf-util.h"
#include "bpf-link.h"
#include "restrict-fs-skel.h"
};
#if BPF_FRAMEWORK && HAVE_LSM_INTEGRITY_TYPE
-#include "bpf-dlopen.h"
+#include "bpf-util.h"
#include "bpf-link.h"
#include "restrict-fsaccess-skel.h"
#if BPF_FRAMEWORK
/* libbpf, clang and llc compile time dependencies are satisfied */
-#include "bpf-dlopen.h"
+#include "bpf-util.h"
#include "bpf-link.h"
#include "restrict-ifaces-skel.h"
#if BPF_FRAMEWORK
/* libbpf, clang, llvm and bpftool compile time dependencies are satisfied */
-#include "bpf-dlopen.h"
+#include "bpf-util.h"
#include "bpf-link.h"
#include "socket-bind-api.bpf.h"
#include "socket-bind-skel.h"
#include "ask-password-api.h"
#include "barrier.h"
#include "bitfield.h"
-#include "bpf-dlopen.h"
+#include "bpf-util.h"
#include "bpf-restrict-fs.h"
#include "btrfs-util.h"
#include "capability-util.h"
#include "sd-messages.h"
#include "af-list.h"
-#include "bpf-dlopen.h"
+#include "bpf-util.h"
#include "conf-parser.h"
#include "alloc-util.h"
#include "cgroup-util.h"
#include "sd-daemon.h"
-#include "bpf-dlopen.h"
+#include "bpf-util.h"
#if HAVE_VMLINUX_H
#include "bpf-link.h"
#include "userns-restrict-skel.h"
#include "userns-restrict-skel.h"
#endif
-#include "bpf-dlopen.h"
+#include "bpf-util.h"
#include "bpf-link.h"
#include "fd-util.h"
#include "log.h"
+++ /dev/null
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#pragma once
-
-#include <bpf/libbpf.h>
-
-/* 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 struct bpf_map* (*sym_bpf_object__next_map)(const struct bpf_object *obj, const struct bpf_map *map);
-
-/* 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);
-
-/* 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 */);
-}
+++ /dev/null
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-
-#include "sd-dlopen.h"
-
-#include "bpf-dlopen.h"
-#include "dlfcn-util.h"
-#include "errno-util.h"
-#include "initrd-util.h"
-#include "log.h"
-
-#if HAVE_LIBBPF
-
-/* libbpf changed types of function prototypes around, so we need to disable some type checking for older
- * libbpf. We consider everything older than 0.7 too old for accurate type checks. */
-#if defined(__LIBBPF_CURRENT_VERSION_GEQ)
-#if __LIBBPF_CURRENT_VERSION_GEQ(0, 7)
-#define MODERN_LIBBPF 1
-#endif
-#endif
-#if !defined(MODERN_LIBBPF)
-#define MODERN_LIBBPF 0
-#endif
-
-static void *bpf_dl = NULL;
-
-static DLSYM_PROTOTYPE(libbpf_get_error) = NULL;
-
-DLSYM_PROTOTYPE(bpf_link__destroy) = NULL;
-DLSYM_PROTOTYPE(bpf_link__fd) = NULL;
-DLSYM_PROTOTYPE(bpf_link__open) = NULL;
-DLSYM_PROTOTYPE(bpf_link__pin) = NULL;
-DLSYM_PROTOTYPE(bpf_map__fd) = NULL;
-DLSYM_PROTOTYPE(bpf_map__name) = NULL;
-DLSYM_PROTOTYPE(bpf_map__set_inner_map_fd) = NULL;
-DLSYM_PROTOTYPE(bpf_map__set_max_entries) = NULL;
-DLSYM_PROTOTYPE(bpf_map__set_pin_path) = NULL;
-DLSYM_PROTOTYPE(bpf_map_delete_elem) = NULL;
-DLSYM_PROTOTYPE(bpf_map_get_fd_by_id) = NULL;
-DLSYM_PROTOTYPE(bpf_map_lookup_elem) = NULL;
-DLSYM_PROTOTYPE(bpf_map_update_elem) = NULL;
-DLSYM_PROTOTYPE(bpf_obj_get_info_by_fd) = NULL;
-DLSYM_PROTOTYPE(bpf_object__attach_skeleton) = NULL;
-DLSYM_PROTOTYPE(bpf_object__destroy_skeleton) = NULL;
-DLSYM_PROTOTYPE(bpf_object__detach_skeleton) = NULL;
-DLSYM_PROTOTYPE(bpf_object__load_skeleton) = NULL;
-DLSYM_PROTOTYPE(bpf_object__name) = NULL;
-DLSYM_PROTOTYPE(bpf_object__open_skeleton) = NULL;
-DLSYM_PROTOTYPE(bpf_object__pin_maps) = NULL;
-DLSYM_PROTOTYPE(bpf_program__attach) = NULL;
-DLSYM_PROTOTYPE(bpf_program__attach_cgroup) = NULL;
-DLSYM_PROTOTYPE(bpf_program__attach_lsm) = NULL;
-DLSYM_PROTOTYPE(bpf_program__name) = NULL;
-DLSYM_PROTOTYPE(bpf_program__set_autoload) = NULL;
-DLSYM_PROTOTYPE(libbpf_set_print) = NULL;
-DLSYM_PROTOTYPE(ring_buffer__epoll_fd) = NULL;
-DLSYM_PROTOTYPE(ring_buffer__free) = NULL;
-DLSYM_PROTOTYPE(ring_buffer__new) = NULL;
-DLSYM_PROTOTYPE(ring_buffer__poll) = NULL;
-
-/* new symbols available from libbpf 0.7.0 */
-int (*sym_bpf_map_create)(enum bpf_map_type, const char *, __u32, __u32, __u32, const struct bpf_map_create_opts *);
-struct bpf_map* (*sym_bpf_object__next_map)(const struct bpf_object *obj, const struct bpf_map *map);
-
-/* 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);
-
-_printf_(2,0)
-static int bpf_print_func(enum libbpf_print_level level, const char *fmt, va_list ap) {
-#if !LOG_TRACE
- /* libbpf logs a lot of details at its debug level, which we don't need to see. */
- if (level == LIBBPF_DEBUG)
- return 0;
-#endif
- /* All other levels are downgraded to LOG_DEBUG */
-
- /* errno is used here, on the assumption that if the log message uses %m, errno will be set to
- * something useful. Otherwise, it shouldn't matter, we may pass 0 or some bogus value. */
- return log_internalv(LOG_DEBUG, errno, NULL, 0, NULL, fmt, ap);
-}
-
-int dlopen_bpf(int log_level) {
- static int cached = 0;
- int r;
-
- if (cached != 0)
- return cached;
-
- SD_ELF_NOTE_DLOPEN(
- "bpf",
- "Support firewalling and sandboxing with BPF",
- SD_ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
- "libbpf.so.1", "libbpf.so.0");
-
- DISABLE_WARNING_DEPRECATED_DECLARATIONS;
-
- _cleanup_(dlclosep) void *dl = NULL;
- r = dlopen_safe("libbpf.so.1", &dl, /* reterr_dlerror= */ NULL);
- if (r < 0) {
- /* 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 */
- const char *dle = NULL;
- r = dlopen_safe("libbpf.so.0", &dl, &dle);
- if (r < 0) {
- log_full_errno(in_initrd() ? LOG_DEBUG : log_level, r,
- "Neither libbpf.so.1 nor libbpf.so.0 are installed, cgroup BPF features disabled: %s", dle ?: STRERROR(r));
- return (cached = -EOPNOTSUPP); /* turn into recognizable error */
- }
-
- log_debug("Loaded 'libbpf.so.0' via dlopen()");
-
- /* symbols deprecated in 1.0 we use as compat */
- r = dlsym_many_or_warn(
- dl, LOG_DEBUG,
-#if MODERN_LIBBPF
- /* Don't exist anymore in new libbpf, hence cannot type check them */
- DLSYM_ARG_FORCE(bpf_create_map)
-#else
- DLSYM_ARG(bpf_create_map)
-#endif
- );
-
- /* NB: we don't try to load bpf_object__next_map() on old versions */
- } else {
- log_debug("Loaded 'libbpf.so.1' via dlopen()");
-
- /* symbols available from 0.7.0 */
- r = dlsym_many_or_warn(
- dl, LOG_DEBUG,
-#if MODERN_LIBBPF
- DLSYM_ARG(bpf_map_create),
- DLSYM_ARG(bpf_object__next_map)
-#else
- /* These symbols did not exist in old libbpf, hence we cannot type check them */
- DLSYM_ARG_FORCE(bpf_map_create),
- DLSYM_ARG_FORCE(bpf_object__next_map)
-#endif
- );
- }
- if (r < 0)
- return cached = log_full_errno(log_level, r, "Failed to load libbpf symbols, cgroup BPF features disabled: %m");
-
- r = dlsym_many_or_warn(
- dl, LOG_DEBUG,
- DLSYM_ARG(bpf_link__destroy),
- DLSYM_ARG(bpf_link__fd),
- DLSYM_ARG(bpf_link__open),
- DLSYM_ARG(bpf_link__pin),
- DLSYM_ARG(bpf_map__fd),
- DLSYM_ARG(bpf_map__name),
- DLSYM_ARG(bpf_map__set_inner_map_fd),
- DLSYM_ARG(bpf_map__set_max_entries),
- DLSYM_ARG(bpf_map__set_pin_path),
- DLSYM_ARG(bpf_map_delete_elem),
- DLSYM_ARG(bpf_map_get_fd_by_id),
- DLSYM_ARG(bpf_map_lookup_elem),
- DLSYM_ARG(bpf_map_update_elem),
- DLSYM_ARG(bpf_obj_get_info_by_fd),
- DLSYM_ARG(bpf_object__attach_skeleton),
- DLSYM_ARG(bpf_object__destroy_skeleton),
- DLSYM_ARG(bpf_object__detach_skeleton),
- DLSYM_ARG(bpf_object__load_skeleton),
- DLSYM_ARG(bpf_object__name),
- DLSYM_ARG(bpf_object__open_skeleton),
- DLSYM_ARG(bpf_object__pin_maps),
-#if MODERN_LIBBPF
- DLSYM_ARG(bpf_program__attach),
- DLSYM_ARG(bpf_program__attach_cgroup),
- DLSYM_ARG(bpf_program__attach_lsm),
-#else
- /* libbpf added a "const" to function parameters where it should not have, ignore this type incompatibility */
- DLSYM_ARG_FORCE(bpf_program__attach),
- DLSYM_ARG_FORCE(bpf_program__attach_cgroup),
- DLSYM_ARG_FORCE(bpf_program__attach_lsm),
-#endif
- DLSYM_ARG(bpf_program__name),
- DLSYM_ARG(bpf_program__set_autoload),
- DLSYM_ARG(libbpf_get_error),
- DLSYM_ARG(libbpf_set_print),
- DLSYM_ARG(ring_buffer__epoll_fd),
- DLSYM_ARG(ring_buffer__free),
- DLSYM_ARG(ring_buffer__new),
- DLSYM_ARG(ring_buffer__poll));
- if (r < 0)
- return cached = log_full_errno(log_level, r, "Failed to load libbpf symbols, cgroup BPF features disabled: %m");
-
- /* We set the print helper unconditionally. Otherwise libbpf will emit not useful log messages. */
- (void) sym_libbpf_set_print(bpf_print_func);
-
- REENABLE_WARNING;
-
- bpf_dl = TAKE_PTR(dl);
-
- return cached = true;
-}
-
-int bpf_get_error_translated(const void *ptr) {
- int r;
-
- r = sym_libbpf_get_error(ptr);
-
- switch (r) {
- case -524:
- /* Workaround for kernel bug, BPF returns an internal error instead of translating it, until
- * it is fixed:
- * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/errno.h?h=v6.9&id=a38297e3fb012ddfa7ce0321a7e5a8daeb1872b6#n27
- */
- return -EOPNOTSUPP;
- default:
- return r;
- }
-}
-
-#else
-
-int dlopen_bpf(int log_level) {
- return log_once_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
- "libbpf support is not compiled in, cgroup BPF features disabled.");
-}
-#endif
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include "bpf-dlopen.h"
+#include "bpf-util.h"
#include "bpf-link.h"
#include "serialize.h"
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "sd-dlopen.h"
+
+#include "bpf-util.h"
+#include "dlfcn-util.h"
+#include "initrd-util.h"
+#include "log.h"
+#include "strv.h"
+
+#if HAVE_LIBBPF
+
+/* libbpf changed types of function prototypes around, so we need to disable some type checking for older
+ * libbpf. We consider everything older than 0.7 too old for accurate type checks. */
+#if defined(__LIBBPF_CURRENT_VERSION_GEQ)
+#if __LIBBPF_CURRENT_VERSION_GEQ(0, 7)
+#define MODERN_LIBBPF 1
+#endif
+#endif
+#if !defined(MODERN_LIBBPF)
+#define MODERN_LIBBPF 0
+#endif
+
+static DLSYM_PROTOTYPE(libbpf_get_error) = NULL;
+
+DLSYM_PROTOTYPE(bpf_create_map) = NULL;
+DLSYM_PROTOTYPE(bpf_link__destroy) = NULL;
+DLSYM_PROTOTYPE(bpf_link__fd) = NULL;
+DLSYM_PROTOTYPE(bpf_link__open) = NULL;
+DLSYM_PROTOTYPE(bpf_link__pin) = NULL;
+DLSYM_PROTOTYPE(bpf_map__fd) = NULL;
+DLSYM_PROTOTYPE(bpf_map__name) = NULL;
+DLSYM_PROTOTYPE(bpf_map__set_inner_map_fd) = NULL;
+DLSYM_PROTOTYPE(bpf_map__set_max_entries) = NULL;
+DLSYM_PROTOTYPE(bpf_map__set_pin_path) = NULL;
+DLSYM_PROTOTYPE(bpf_map_create) = NULL;
+DLSYM_PROTOTYPE(bpf_map_delete_elem) = NULL;
+DLSYM_PROTOTYPE(bpf_map_get_fd_by_id) = NULL;
+DLSYM_PROTOTYPE(bpf_map_lookup_elem) = NULL;
+DLSYM_PROTOTYPE(bpf_map_update_elem) = NULL;
+DLSYM_PROTOTYPE(bpf_obj_get_info_by_fd) = NULL;
+DLSYM_PROTOTYPE(bpf_object__attach_skeleton) = NULL;
+DLSYM_PROTOTYPE(bpf_object__destroy_skeleton) = NULL;
+DLSYM_PROTOTYPE(bpf_object__detach_skeleton) = NULL;
+DLSYM_PROTOTYPE(bpf_object__load_skeleton) = NULL;
+DLSYM_PROTOTYPE(bpf_object__name) = NULL;
+DLSYM_PROTOTYPE(bpf_object__next_map) = NULL;
+DLSYM_PROTOTYPE(bpf_object__open_skeleton) = NULL;
+DLSYM_PROTOTYPE(bpf_object__pin_maps) = NULL;
+DLSYM_PROTOTYPE(bpf_program__attach) = NULL;
+DLSYM_PROTOTYPE(bpf_program__attach_cgroup) = NULL;
+DLSYM_PROTOTYPE(bpf_program__attach_lsm) = NULL;
+DLSYM_PROTOTYPE(bpf_program__name) = NULL;
+DLSYM_PROTOTYPE(bpf_program__set_autoload) = NULL;
+static int missing_bpf_token_create(int bpffs_fd, struct bpf_token_create_opts *opts) {
+ return -ENOSYS;
+}
+DLSYM_PROTOTYPE(bpf_token_create) = missing_bpf_token_create;
+DLSYM_PROTOTYPE(libbpf_set_print) = NULL;
+DLSYM_PROTOTYPE(ring_buffer__epoll_fd) = NULL;
+DLSYM_PROTOTYPE(ring_buffer__free) = NULL;
+DLSYM_PROTOTYPE(ring_buffer__new) = NULL;
+DLSYM_PROTOTYPE(ring_buffer__poll) = NULL;
+
+_printf_(2,0)
+static int bpf_print_func(enum libbpf_print_level level, const char *fmt, va_list ap) {
+#if !LOG_TRACE
+ /* libbpf logs a lot of details at its debug level, which we don't need to see. */
+ if (level == LIBBPF_DEBUG)
+ return 0;
+#endif
+ /* All other levels are downgraded to LOG_DEBUG */
+
+ /* errno is used here, on the assumption that if the log message uses %m, errno will be set to
+ * something useful. Otherwise, it shouldn't matter, we may pass 0 or some bogus value. */
+ return log_internalv(LOG_DEBUG, errno, NULL, 0, NULL, fmt, ap);
+}
+
+int dlopen_bpf(int log_level) {
+ static void *bpf_dl = NULL;
+ int r;
+
+ SD_ELF_NOTE_DLOPEN(
+ "bpf",
+ "Support firewalling and sandboxing with BPF",
+ SD_ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
+ "libbpf.so.1", "libbpf.so.0");
+
+ DISABLE_WARNING_DEPRECATED_DECLARATIONS;
+
+ FOREACH_STRING(soname, "libbpf.so.1", "libbpf.so.0") {
+ r = dlopen_many_sym_or_warn(
+ &bpf_dl, soname, LOG_DEBUG,
+ DLSYM_ARG(bpf_link__destroy),
+ DLSYM_ARG(bpf_link__fd),
+ DLSYM_ARG(bpf_link__open),
+ DLSYM_ARG(bpf_link__pin),
+ DLSYM_ARG(bpf_map__fd),
+ DLSYM_ARG(bpf_map__name),
+ DLSYM_ARG(bpf_map__set_inner_map_fd),
+ DLSYM_ARG(bpf_map__set_max_entries),
+ DLSYM_ARG(bpf_map__set_pin_path),
+ DLSYM_ARG(bpf_map_delete_elem),
+ DLSYM_ARG(bpf_map_get_fd_by_id),
+ DLSYM_ARG(bpf_map_lookup_elem),
+ DLSYM_ARG(bpf_map_update_elem),
+ DLSYM_ARG(bpf_obj_get_info_by_fd),
+ DLSYM_ARG(bpf_object__attach_skeleton),
+ DLSYM_ARG(bpf_object__destroy_skeleton),
+ DLSYM_ARG(bpf_object__detach_skeleton),
+ DLSYM_ARG(bpf_object__load_skeleton),
+ DLSYM_ARG(bpf_object__name),
+ DLSYM_ARG(bpf_object__open_skeleton),
+ DLSYM_ARG(bpf_object__pin_maps),
+#if MODERN_LIBBPF
+ DLSYM_ARG(bpf_program__attach),
+ DLSYM_ARG(bpf_program__attach_cgroup),
+ DLSYM_ARG(bpf_program__attach_lsm),
+#else
+ /* libbpf added a "const" to function parameters where it should not have, ignore this type incompatibility */
+ DLSYM_ARG_FORCE(bpf_program__attach),
+ DLSYM_ARG_FORCE(bpf_program__attach_cgroup),
+ DLSYM_ARG_FORCE(bpf_program__attach_lsm),
+#endif
+ DLSYM_ARG(bpf_program__name),
+ DLSYM_ARG(bpf_program__set_autoload),
+ DLSYM_ARG(libbpf_get_error),
+ DLSYM_ARG(libbpf_set_print),
+ DLSYM_ARG(ring_buffer__epoll_fd),
+ DLSYM_ARG(ring_buffer__free),
+ DLSYM_ARG(ring_buffer__new),
+ DLSYM_ARG(ring_buffer__poll));
+ if (r >= 0)
+ break;
+ }
+ REENABLE_WARNING;
+ if (r < 0)
+ return log_full_errno(in_initrd() ? LOG_DEBUG : log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "Neither libbpf.so.1 nor libbpf.so.0 are installed, cgroup BPF features disabled.");
+
+ /* Version-specific symbols: bpf_create_map exists only in libbpf < 1.0; bpf_map_create and
+ * bpf_object__next_map only in 0.7+. bpf_token_create only in 1.5+. Unresolved prototypes keep
+ * their initializers (NULL, or a fallback returning -ENOSYS for bpf_token_create). */
+ DLSYM_OPTIONAL(bpf_dl, bpf_create_map);
+ DLSYM_OPTIONAL(bpf_dl, bpf_map_create);
+ DLSYM_OPTIONAL(bpf_dl, bpf_object__next_map);
+ DLSYM_OPTIONAL(bpf_dl, bpf_token_create);
+
+ /* We set the print helper unconditionally. Otherwise libbpf will emit not useful log messages. */
+ (void) sym_libbpf_set_print(bpf_print_func);
+
+ return 1;
+}
+
+int bpf_get_error_translated(const void *ptr) {
+ int r;
+
+ r = sym_libbpf_get_error(ptr);
+
+ switch (r) {
+ case -524:
+ /* Workaround for kernel bug, BPF returns an internal error instead of translating it, until
+ * it is fixed:
+ * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/errno.h?h=v6.9&id=a38297e3fb012ddfa7ce0321a7e5a8daeb1872b6#n27
+ */
+ return -EOPNOTSUPP;
+ default:
+ return r;
+ }
+}
+
+#else
+
+int dlopen_bpf(int log_level) {
+ return log_once_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "libbpf support is not compiled in, cgroup BPF features disabled.");
+}
+#endif
#include <bpf/bpf.h> /* IWYU pragma: export */
#include <bpf/libbpf.h> /* IWYU pragma: export */
-#include "bpf-compat.h" /* IWYU pragma: export */
#include "dlfcn-util.h"
#include "shared-forward.h"
+/* Always redeclare these so DLSYM_PROTOTYPE's typeof() resolves regardless of libbpf version;
+ * suppress the warning when the libbpf headers already declare them.
+ * - bpf_map_create, bpf_object__next_map: available since libbpf 0.7
+ * - bpf_token_create: available since libbpf 1.5
+ * - bpf_create_map: removed in libbpf 1.0
+ */
+DISABLE_WARNING_REDUNDANT_DECLS;
+/* NOLINTBEGIN(readability-redundant-declaration) */
+struct bpf_map_create_opts;
+struct bpf_token_create_opts;
+extern int bpf_create_map(enum bpf_map_type, int key_size, int value_size, int max_entries, __u32 map_flags);
+extern int bpf_map_create(enum bpf_map_type, const char *, __u32, __u32, __u32, const struct bpf_map_create_opts *);
+extern struct bpf_map* bpf_object__next_map(const struct bpf_object *obj, const struct bpf_map *map);
+extern int bpf_token_create(int bpffs_fd, struct bpf_token_create_opts *opts);
+/* NOLINTEND(readability-redundant-declaration) */
+REENABLE_WARNING;
+
+extern DLSYM_PROTOTYPE(bpf_create_map);
extern DLSYM_PROTOTYPE(bpf_link__destroy);
extern DLSYM_PROTOTYPE(bpf_link__fd);
extern DLSYM_PROTOTYPE(bpf_link__open);
extern DLSYM_PROTOTYPE(bpf_map__set_inner_map_fd);
extern DLSYM_PROTOTYPE(bpf_map__set_max_entries);
extern DLSYM_PROTOTYPE(bpf_map__set_pin_path);
+extern DLSYM_PROTOTYPE(bpf_map_create);
extern DLSYM_PROTOTYPE(bpf_map_delete_elem);
extern DLSYM_PROTOTYPE(bpf_map_get_fd_by_id);
extern DLSYM_PROTOTYPE(bpf_map_lookup_elem);
extern DLSYM_PROTOTYPE(bpf_object__detach_skeleton);
extern DLSYM_PROTOTYPE(bpf_object__load_skeleton);
extern DLSYM_PROTOTYPE(bpf_object__name);
+extern DLSYM_PROTOTYPE(bpf_object__next_map);
extern DLSYM_PROTOTYPE(bpf_object__open_skeleton);
extern DLSYM_PROTOTYPE(bpf_object__pin_maps);
extern DLSYM_PROTOTYPE(bpf_program__attach);
extern DLSYM_PROTOTYPE(bpf_program__attach_lsm);
extern DLSYM_PROTOTYPE(bpf_program__name);
extern DLSYM_PROTOTYPE(bpf_program__set_autoload);
+extern DLSYM_PROTOTYPE(bpf_token_create);
extern DLSYM_PROTOTYPE(libbpf_set_print);
extern DLSYM_PROTOTYPE(ring_buffer__epoll_fd);
extern DLSYM_PROTOTYPE(ring_buffer__free);
extern DLSYM_PROTOTYPE(ring_buffer__new);
extern DLSYM_PROTOTYPE(ring_buffer__poll);
+/* Helper that uses the available variant behind the 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 */);
+}
+
/* libbpf sometimes returns error codes that make sense only in the kernel, like 524 for EOPNOTSUPP. Use
* this helper instead of libbpf_get_error() to ensure some of the known ones are translated into errnos
* we understand. */
'boot-entry.c',
'boot-timestamps.c',
'bootspec.c',
- 'bpf-dlopen.c',
'bpf-program.c',
+ 'bpf-util.c',
'bridge-util.c',
'btrfs-util.c',
'bus-get-properties.c',
},
core_test_template + {
'sources' : files('test-bpf-token.c'),
- 'dependencies' : common_test_dependencies + libbpf,
+ 'dependencies' : common_test_dependencies + libbpf_cflags,
'conditions' : ['BPF_FRAMEWORK'],
'type' : 'manual',
},
}
#if BPF_FRAMEWORK && HAVE_LSM_INTEGRITY_TYPE
-#include "bpf-dlopen.h"
+#include "bpf-util.h"
#include "restrict-fsaccess-skel.h"
static struct restrict_fsaccess_bpf *restrict_fsaccess_bpf_free(struct restrict_fsaccess_bpf *obj) {
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include <bpf/bpf.h>
#include <fcntl.h>
+#include "bpf-util.h"
#include "fd-util.h"
#include "main-func.h"
-#include "tests.h" /* NOLINT(misc-include-cleaner): this is needed conditionally */
+#include "tests.h"
static int run(int argc, char *argv[]) {
-#if defined(LIBBPF_MAJOR_VERSION) && (LIBBPF_MAJOR_VERSION > 1 || (LIBBPF_MAJOR_VERSION == 1 && LIBBPF_MINOR_VERSION >= 5))
- _cleanup_close_ int bpffs_fd = open("/sys/fs/bpf", O_RDONLY);
+#if HAVE_LIBBPF
+ int r;
+
+ r = dlopen_bpf(LOG_ERR);
+ if (r < 0)
+ return r;
+
+ _cleanup_close_ int bpffs_fd = open("/sys/fs/bpf", O_CLOEXEC|O_RDONLY);
if (bpffs_fd < 0)
return log_error_errno(errno, "Failed to open '/sys/fs/bpf': %m");
- _cleanup_close_ int token_fd = bpf_token_create(bpffs_fd, /* opts= */ NULL);
+ _cleanup_close_ int token_fd = sym_bpf_token_create(bpffs_fd, /* opts= */ NULL);
+ if (token_fd == -ENOSYS)
+ return log_tests_skipped("bpf_token_create() unavailable (libbpf too old or kernel lacks BPF_TOKEN_CREATE support)");
if (token_fd < 0)
- return log_error_errno(errno, "Failed to create bpf token: %m");
+ return log_error_errno(token_fd, "Failed to create bpf token: %m");
log_info("Successfully created token fd.");
return 0;
#else
- return log_tests_skipped("libbpf is older than v1.5");
+ return log_tests_skipped("BPF framework support is disabled");
#endif
}
#include "acl-util.h"
#include "apparmor-util.h"
#include "blkid-util.h"
-#include "bpf-dlopen.h"
+#include "bpf-util.h"
#include "compress.h"
#include "crypto-util.h"
#include "cryptsetup-util.h"