- **bpf-util: rename from bpf-dlopen, unify version-specific symbol handling** - **cryptsetup: dlopen libcryptsetup in tokens** - **tree-wide: dlopen libpam in pam plugins** - **test-bus-marshal: dlopen() glib and libdbus instead of linking directly** - **lock-util: Simplify timeout for lock_generic_with_timeout()** - **color-util: simplify hsv_to_rgb, fix rgb_to_hsv negative-hue wrap** - **tree-wide: Use our own macros instead of fabs()/fmax()/fmin()** - **locale-util: dlopen() libintl instead of linking against it** - **home: Use log2u64() over log2()** - **meson: drop libdl, threads, and librt dependencies** - **libc: Use dlsym() from a constructor instead of weak symbols** - **libc: Make sure C23 versions of strtol(), sscanf() are not used**
This commit is contained in:
@@ -1,49 +0,0 @@
|
||||
/* 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 */);
|
||||
}
|
||||
@@ -1,221 +0,0 @@
|
||||
/* 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
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "bpf-dlopen.h"
|
||||
#include "bpf-util.h"
|
||||
#include "bpf-link.h"
|
||||
#include "serialize.h"
|
||||
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
/* 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
|
||||
@@ -8,10 +8,27 @@
|
||||
#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);
|
||||
@@ -21,6 +38,7 @@ extern DLSYM_PROTOTYPE(bpf_map__name);
|
||||
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);
|
||||
@@ -33,6 +51,7 @@ extern DLSYM_PROTOTYPE(bpf_object__destroy_skeleton);
|
||||
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);
|
||||
@@ -40,12 +59,30 @@ extern DLSYM_PROTOTYPE(bpf_program__attach_cgroup);
|
||||
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. */
|
||||
+25
-19
@@ -11,8 +11,8 @@ void rgb_to_hsv(double r, double g, double b,
|
||||
assert(g >= 0 && g <= 1);
|
||||
assert(b >= 0 && b <= 1);
|
||||
|
||||
double max_color = fmax(r, fmax(g, b));
|
||||
double min_color = fmin(r, fmin(g, b));
|
||||
double max_color = MAX(r, MAX(g, b));
|
||||
double min_color = MIN(r, MIN(g, b));
|
||||
double delta = max_color - min_color;
|
||||
|
||||
if (ret_v)
|
||||
@@ -32,13 +32,15 @@ void rgb_to_hsv(double r, double g, double b,
|
||||
if (ret_h) {
|
||||
if (delta > 0) {
|
||||
if (r >= max_color)
|
||||
*ret_h = 60 * fmod((g - b) / delta, 6);
|
||||
*ret_h = 60 * (g - b) / delta;
|
||||
else if (g >= max_color)
|
||||
*ret_h = 60 * (((b - r) / delta) + 2);
|
||||
else if (b >= max_color)
|
||||
else /* b >= max_color */
|
||||
*ret_h = 60 * (((r - g) / delta) + 4);
|
||||
|
||||
*ret_h = fmod(*ret_h, 360);
|
||||
/* The r-max branch produces (-60, 60); fold the negative half up. */
|
||||
if (*ret_h < 0)
|
||||
*ret_h += 360;
|
||||
} else
|
||||
*ret_h = NAN;
|
||||
}
|
||||
@@ -49,29 +51,33 @@ void hsv_to_rgb(double h, double s, double v,
|
||||
|
||||
double c, x, m, r, g, b;
|
||||
|
||||
assert(h >= 0 && h <= 360);
|
||||
assert(s >= 0 && s <= 100);
|
||||
assert(v >= 0 && v <= 100);
|
||||
assert(ret_r);
|
||||
assert(ret_g);
|
||||
assert(ret_b);
|
||||
|
||||
h = fmod(h, 360);
|
||||
c = (s / 100.0) * (v / 100.0);
|
||||
x = c * (1 - fabs(fmod(h / 60.0, 2) - 1));
|
||||
m = (v / 100) - c;
|
||||
|
||||
if (h >= 0 && h < 60)
|
||||
r = c, g = x, b = 0.0;
|
||||
else if (h >= 60 && h < 120)
|
||||
r = x, g = c, b = 0.0;
|
||||
else if (h >= 120 && h < 180)
|
||||
r = 0.0, g = c, b = x;
|
||||
else if (h >= 180 && h < 240)
|
||||
r = 0.0, g = x, b = c;
|
||||
else if (h >= 240 && h < 300)
|
||||
r = x, g = 0.0, b = c;
|
||||
else
|
||||
r = c, g = 0.0, b = x;
|
||||
/* Split h into sector index k ∈ [0, 6] and fractional offset f ∈ [0, 1) within the sector.
|
||||
* Within each sector exactly one of {r, g, b} equals c, one equals 0, and the third (x)
|
||||
* ramps linearly between them — ascending in even sectors, descending in odd. h == 360 is
|
||||
* the cyclic boundary equivalent to h == 0, and maps to sector 0. */
|
||||
double seg = h / 60.0;
|
||||
int k = (int) seg % 6;
|
||||
double f = seg - (int) seg;
|
||||
x = c * (k & 1 ? 1.0 - f : f);
|
||||
|
||||
switch (k) {
|
||||
case 0: r = c; g = x; b = 0.0; break;
|
||||
case 1: r = x; g = c; b = 0.0; break;
|
||||
case 2: r = 0.0; g = c; b = x; break;
|
||||
case 3: r = 0.0; g = x; b = c; break;
|
||||
case 4: r = x; g = 0.0; b = c; break;
|
||||
default: r = c; g = 0.0; b = x; break;
|
||||
}
|
||||
|
||||
*ret_r = (uint8_t) ((r + m) * 255);
|
||||
*ret_g = (uint8_t) ((g + m) * 255);
|
||||
|
||||
@@ -45,6 +45,7 @@ DLSYM_PROTOTYPE(crypt_keyslot_destroy) = NULL;
|
||||
DLSYM_PROTOTYPE(crypt_keyslot_max) = NULL;
|
||||
DLSYM_PROTOTYPE(crypt_keyslot_status) = NULL;
|
||||
DLSYM_PROTOTYPE(crypt_load) = NULL;
|
||||
DLSYM_PROTOTYPE(crypt_logf) = NULL;
|
||||
DLSYM_PROTOTYPE(crypt_metadata_locking) = NULL;
|
||||
DLSYM_PROTOTYPE(crypt_persistent_flags_get) = NULL;
|
||||
DLSYM_PROTOTYPE(crypt_persistent_flags_set) = NULL;
|
||||
@@ -315,6 +316,7 @@ int dlopen_cryptsetup(int log_level) {
|
||||
DLSYM_ARG(crypt_keyslot_max),
|
||||
DLSYM_ARG(crypt_keyslot_status),
|
||||
DLSYM_ARG(crypt_load),
|
||||
DLSYM_ARG(crypt_logf),
|
||||
DLSYM_ARG(crypt_metadata_locking),
|
||||
DLSYM_ARG(crypt_persistent_flags_get),
|
||||
DLSYM_ARG(crypt_persistent_flags_set),
|
||||
|
||||
@@ -46,6 +46,7 @@ extern DLSYM_PROTOTYPE(crypt_keyslot_destroy);
|
||||
extern DLSYM_PROTOTYPE(crypt_keyslot_max);
|
||||
extern DLSYM_PROTOTYPE(crypt_keyslot_status);
|
||||
extern DLSYM_PROTOTYPE(crypt_load);
|
||||
extern DLSYM_PROTOTYPE(crypt_logf);
|
||||
extern DLSYM_PROTOTYPE(crypt_metadata_locking);
|
||||
extern DLSYM_PROTOTYPE(crypt_persistent_flags_get);
|
||||
extern DLSYM_PROTOTYPE(crypt_persistent_flags_set);
|
||||
|
||||
@@ -19,8 +19,8 @@ shared_sources = files(
|
||||
'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',
|
||||
@@ -383,8 +383,7 @@ shared_sources += [dns_type_from_name_inc, dns_type_to_name_inc]
|
||||
|
||||
libshared_name = 'systemd-shared-@0@'.format(shared_lib_tag)
|
||||
|
||||
libshared_deps = [threads,
|
||||
libacl_cflags,
|
||||
libshared_deps = [libacl_cflags,
|
||||
libapparmor_cflags,
|
||||
libarchive_cflags,
|
||||
libaudit_cflags,
|
||||
@@ -393,7 +392,6 @@ libshared_deps = [threads,
|
||||
libcrypt_cflags,
|
||||
libcryptsetup_cflags,
|
||||
libcurl_cflags,
|
||||
libdl,
|
||||
libdw_cflags,
|
||||
libelf_cflags,
|
||||
libfdisk_cflags,
|
||||
@@ -410,7 +408,6 @@ libshared_deps = [threads,
|
||||
libpcre2_cflags,
|
||||
libpwquality_cflags,
|
||||
libqrencode_cflags,
|
||||
librt,
|
||||
libseccomp_cflags,
|
||||
libselinux_cflags,
|
||||
libxenctrl_cflags,
|
||||
|
||||
@@ -25,10 +25,15 @@ static void *libpam_dl = NULL;
|
||||
DLSYM_PROTOTYPE(pam_acct_mgmt) = NULL;
|
||||
DLSYM_PROTOTYPE(pam_close_session) = NULL;
|
||||
DLSYM_PROTOTYPE(pam_end) = NULL;
|
||||
DLSYM_PROTOTYPE(pam_get_authtok_noverify) = NULL;
|
||||
DLSYM_PROTOTYPE(pam_get_authtok_verify) = NULL;
|
||||
DLSYM_PROTOTYPE(pam_get_data) = NULL;
|
||||
DLSYM_PROTOTYPE(pam_get_item) = NULL;
|
||||
DLSYM_PROTOTYPE(pam_get_user) = NULL;
|
||||
DLSYM_PROTOTYPE(pam_getenv) = NULL;
|
||||
DLSYM_PROTOTYPE(pam_getenvlist) = NULL;
|
||||
DLSYM_PROTOTYPE(pam_open_session) = NULL;
|
||||
DLSYM_PROTOTYPE(pam_prompt) = NULL;
|
||||
DLSYM_PROTOTYPE(pam_putenv) = NULL;
|
||||
DLSYM_PROTOTYPE(pam_set_data) = NULL;
|
||||
DLSYM_PROTOTYPE(pam_set_item) = NULL;
|
||||
@@ -361,6 +366,19 @@ int pam_prompt_graceful(pam_handle_t *pamh, int style, char **ret_response, cons
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
int pam_putenv_assign(pam_handle_t *pamh, const char *name, const char *value) {
|
||||
_cleanup_(erase_and_freep) char *s = NULL;
|
||||
|
||||
assert(pamh);
|
||||
assert(name);
|
||||
assert(value);
|
||||
|
||||
if (asprintf(&s, "%s=%s", name, value) < 0)
|
||||
return PAM_BUF_ERR;
|
||||
|
||||
return sym_pam_putenv(pamh, s);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int dlopen_libpam(int log_level) {
|
||||
@@ -378,10 +396,15 @@ int dlopen_libpam(int log_level) {
|
||||
DLSYM_ARG(pam_acct_mgmt),
|
||||
DLSYM_ARG(pam_close_session),
|
||||
DLSYM_ARG(pam_end),
|
||||
DLSYM_ARG(pam_get_authtok_noverify),
|
||||
DLSYM_ARG(pam_get_authtok_verify),
|
||||
DLSYM_ARG(pam_get_data),
|
||||
DLSYM_ARG(pam_get_item),
|
||||
DLSYM_ARG(pam_get_user),
|
||||
DLSYM_ARG(pam_getenv),
|
||||
DLSYM_ARG(pam_getenvlist),
|
||||
DLSYM_ARG(pam_open_session),
|
||||
DLSYM_ARG(pam_prompt),
|
||||
DLSYM_ARG(pam_putenv),
|
||||
DLSYM_ARG(pam_set_data),
|
||||
DLSYM_ARG(pam_set_item),
|
||||
|
||||
+15
-1
@@ -6,7 +6,7 @@
|
||||
#if HAVE_PAM
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/pam_ext.h>
|
||||
#include <security/pam_modules.h> /* IWYU pragma: export */
|
||||
#include <security/pam_modules.h> /* IWYU pragma: export */
|
||||
#include <syslog.h>
|
||||
|
||||
#include "dlfcn-util.h"
|
||||
@@ -14,10 +14,15 @@
|
||||
extern DLSYM_PROTOTYPE(pam_acct_mgmt);
|
||||
extern DLSYM_PROTOTYPE(pam_close_session);
|
||||
extern DLSYM_PROTOTYPE(pam_end);
|
||||
extern DLSYM_PROTOTYPE(pam_get_authtok_noverify);
|
||||
extern DLSYM_PROTOTYPE(pam_get_authtok_verify);
|
||||
extern DLSYM_PROTOTYPE(pam_get_data);
|
||||
extern DLSYM_PROTOTYPE(pam_get_item);
|
||||
extern DLSYM_PROTOTYPE(pam_get_user);
|
||||
extern DLSYM_PROTOTYPE(pam_getenv);
|
||||
extern DLSYM_PROTOTYPE(pam_getenvlist);
|
||||
extern DLSYM_PROTOTYPE(pam_open_session);
|
||||
extern DLSYM_PROTOTYPE(pam_prompt);
|
||||
extern DLSYM_PROTOTYPE(pam_putenv);
|
||||
extern DLSYM_PROTOTYPE(pam_set_data);
|
||||
extern DLSYM_PROTOTYPE(pam_set_item);
|
||||
@@ -27,6 +32,11 @@ extern DLSYM_PROTOTYPE(pam_strerror);
|
||||
extern DLSYM_PROTOTYPE(pam_syslog);
|
||||
extern DLSYM_PROTOTYPE(pam_vsyslog);
|
||||
|
||||
/* sym_pam_prompt() replacement for the pam_info() macro from <security/pam_ext.h>, which expands to a direct
|
||||
* pam_prompt() call. */
|
||||
#define sym_pam_info(pamh, fmt, ...) \
|
||||
sym_pam_prompt((pamh), PAM_TEXT_INFO, NULL, (fmt), ## __VA_ARGS__)
|
||||
|
||||
void pam_log_setup(void);
|
||||
|
||||
int errno_to_pam_error(int error) _const_;
|
||||
@@ -90,6 +100,10 @@ int pam_get_data_many_internal(pam_handle_t *pamh, ...) _sentinel_;
|
||||
|
||||
int pam_prompt_graceful(pam_handle_t *pamh, int style, char **ret_response, const char *fmt, ...) _printf_(4,5);
|
||||
|
||||
/* Equivalent of pam_misc_setenv(pamh, name, value, 0), without the libpam_misc dep — builds "name=value"
|
||||
* and hands it to sym_pam_putenv(), then erases the buffer before freeing in case it carried a secret. */
|
||||
int pam_putenv_assign(pam_handle_t *pamh, const char *name, const char *value);
|
||||
|
||||
#endif
|
||||
|
||||
int dlopen_libpam(int log_level);
|
||||
|
||||
Reference in New Issue
Block a user