Various dlopen/linking cleanups from #42100 (#42166)

- **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:
Daan De Meyer
2026-05-19 08:54:27 +02:00
committed by GitHub
78 changed files with 802 additions and 719 deletions
-49
View File
@@ -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 */);
}
-221
View File
@@ -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 -1
View File
@@ -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"
+178
View File
@@ -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
View File
@@ -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);
+2
View File
@@ -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),
+1
View File
@@ -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);
+2 -5
View File
@@ -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,
+23
View File
@@ -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
View File
@@ -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);