]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dlfcn-util: add static asserts ensuring our sym_xyz() func ptrs match the types from...
authorLennart Poettering <lennart@poettering.net>
Wed, 16 Nov 2022 20:37:20 +0000 (21:37 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 21 Nov 2022 15:13:17 +0000 (16:13 +0100)
Make sure that the sym_xyz function pointers have the types that the
functions we'll assign them have.

And of course, this found a number of incompatibilities right-away, in
particular in the bpf hookup.

(Doing this will trigger deprecation warnings from libbpf. I simply
turned them off locally now, since we are well aware of what we are
doing in that regard.)

There's one return type fix (bool → int), that actually matters I think,
as it might have created an incompatibility on some archs.

src/shared/bpf-compat.h
src/shared/bpf-dlopen.c
src/shared/bpf-dlopen.h
src/shared/cryptsetup-util.c
src/shared/dlfcn-util.h
src/shared/idn-util.c
src/shared/idn-util.h

index 04ade82fc1e049f6691ed3a5fede9013333c429e..9ccb7d8205e3c16dd152f173b8eaff08cc06a6e2 100644 (file)
@@ -25,7 +25,7 @@ struct bpf_map_create_opts;
  *  - 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 *);
+extern int (*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);
index 2556053cbb68bca02fdf17741bc33db7b361e5d1..15301aee600c8c34f9814e65ed0a923e36b3e117 100644 (file)
@@ -6,8 +6,20 @@
 #include "strv.h"
 
 #if HAVE_LIBBPF
-struct bpf_link* (*sym_bpf_program__attach_cgroup)(struct bpf_program *, int);
-struct bpf_link* (*sym_bpf_program__attach_lsm)(struct bpf_program *);
+
+/* 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
+
+struct bpf_link* (*sym_bpf_program__attach_cgroup)(const struct bpf_program *, int);
+struct bpf_link* (*sym_bpf_program__attach_lsm)(const struct bpf_program *);
 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 *);
@@ -22,7 +34,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_libbpf_probe_bpf_prog_type)(enum bpf_prog_type, const void *);
+int (*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 *);
@@ -49,6 +61,8 @@ int dlopen_bpf(void) {
         void *dl;
         int r;
 
+        DISABLE_WARNING_DEPRECATED_DECLARATIONS;
+
         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
@@ -61,14 +75,29 @@ int dlopen_bpf(void) {
                                                "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,
+                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),
+                                DLSYM_ARG_FORCE(bpf_probe_prog_type));
+#else
                                 DLSYM_ARG(bpf_create_map),
                                 DLSYM_ARG(bpf_probe_prog_type));
+#endif
         } else {
                 /* symbols available from 0.7.0 */
-                r = dlsym_many_or_warn(dl, LOG_DEBUG,
+                r = dlsym_many_or_warn(
+                                dl, LOG_DEBUG,
+#if MODERN_LIBBPF
                                 DLSYM_ARG(bpf_map_create),
-                                DLSYM_ARG(libbpf_probe_bpf_prog_type));
+                                DLSYM_ARG(libbpf_probe_bpf_prog_type)
+#else
+                                /* These symbols did not exist in old libbpf, hence we cannot type check them */
+                                DLSYM_ARG_FORCE(bpf_map_create),
+                                DLSYM_ARG_FORCE(libbpf_probe_bpf_prog_type)
+#endif
+                );
         }
 
         r = dlsym_many_or_warn(
@@ -86,8 +115,14 @@ int dlopen_bpf(void) {
                         DLSYM_ARG(bpf_object__attach_skeleton),
                         DLSYM_ARG(bpf_object__detach_skeleton),
                         DLSYM_ARG(bpf_object__destroy_skeleton),
+#if MODERN_LIBBPF
                         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_cgroup),
+                        DLSYM_ARG_FORCE(bpf_program__attach_lsm),
+#endif
                         DLSYM_ARG(bpf_program__name),
                         DLSYM_ARG(libbpf_set_print),
                         DLSYM_ARG(libbpf_get_error));
@@ -96,6 +131,9 @@ int dlopen_bpf(void) {
 
         /* We set the print helper unconditionally. Otherwise libbpf will emit not useful log messages. */
         (void) sym_libbpf_set_print(bpf_print_func);
+
+        REENABLE_WARNING;
+
         return r;
 }
 
index 95951e63e0e4c61e7a593332e45380d817211dfd..0750abc56b94d90090c2c3ac4cddd0ed5e412ce0 100644 (file)
@@ -8,8 +8,8 @@
 
 #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 struct bpf_link* (*sym_bpf_program__attach_cgroup)(const struct bpf_program *, int);
+extern struct bpf_link* (*sym_bpf_program__attach_lsm)(const 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 *);
index 7437cbed6bab448c29cc85c1e12810a0efbeec73..f697429852a8703d8b6f34c4baf3098c5b55560b 100644 (file)
@@ -205,6 +205,14 @@ int dlopen_cryptsetup(void) {
 #if HAVE_LIBCRYPTSETUP
         int r;
 
+        /* libcryptsetup added crypt_reencrypt() in 2.2.0, and marked it obsolete in 2.4.0, replacing it with
+         * crypt_reencrypt_run(), which takes one extra argument but is otherwise identical. The old call is
+         * still available though, and given we want to support 2.2.0 for a while longer, we'll stick to the
+         * old symbol. Howerver, the old symbols now has a GCC deprecation decorator, hence let's turn off
+         * warnings about this for now. */
+
+        DISABLE_WARNING_DEPRECATED_DECLARATIONS;
+
         r = dlopen_many_sym_or_warn(
                         &cryptsetup_dl, "libcryptsetup.so.12", LOG_DEBUG,
                         DLSYM_ARG(crypt_activate_by_passphrase),
@@ -262,6 +270,8 @@ int dlopen_cryptsetup(void) {
         if (r <= 0)
                 return r;
 
+        REENABLE_WARNING;
+
         /* Redirect the default logging calls of libcryptsetup to our own logging infra. (Note that
          * libcryptsetup also maintains per-"struct crypt_device" log functions, which we'll also set
          * whenever allocating a "struct crypt_device" context. Why set both? To be defensive: maybe some
index d786d035d7149e5eb9b9831409873048e2b3672f..f8a16433fceb01619a413cb461b34f16fe947f5a 100644 (file)
@@ -19,4 +19,8 @@ int dlopen_many_sym_or_warn_sentinel(void **dlp, const char *filename, int log_l
  * that each library symbol to resolve will be placed in a variable with the "sym_" prefix, i.e. a symbol
  * "foobar" is loaded into a variable "sym_foobar". */
 #define DLSYM_ARG(arg) \
+        ({ assert_cc(__builtin_types_compatible_p(typeof(sym_##arg), typeof(&arg))); &sym_##arg; }), STRINGIFY(arg)
+
+/* libbpf is a bit confused about type-safety and API compatibility. Provide a macro that can tape over that mess. Sad. */
+#define DLSYM_ARG_FORCE(arg) \
         &sym_##arg, STRINGIFY(arg)
index d4108d0c8e38bda4e04b1ee28d26d0a802ebd5fb..6f36688dc0147d5659d67a2366a0c1eec0fe382e 100644 (file)
@@ -17,7 +17,7 @@ static void* idn_dl = NULL;
 
 #if HAVE_LIBIDN2
 int (*sym_idn2_lookup_u8)(const uint8_t* src, uint8_t** lookupname, int flags) = NULL;
-const char *(*sym_idn2_strerror)(int rc) = NULL;
+const char *(*sym_idn2_strerror)(int rc) _const_ = NULL;
 int (*sym_idn2_to_unicode_8z8z)(const char * input, char ** output, int flags) = NULL;
 
 int dlopen_idn(void) {
@@ -31,7 +31,7 @@ int dlopen_idn(void) {
 
 #if HAVE_LIBIDN
 int (*sym_idna_to_ascii_4i)(const uint32_t * in, size_t inlen, char *out, int flags);
-int (*sym_idna_to_unicode_44i)(const uint32_t * in, size_t inlen,uint32_t * out, size_t * outlen, int flags);
+int (*sym_idna_to_unicode_44i)(const uint32_t * in, size_t inlen, uint32_t * out, size_t * outlen, int flags);
 char* (*sym_stringprep_ucs4_to_utf8)(const uint32_t * str, ssize_t len, size_t * items_read, size_t * items_written);
 uint32_t* (*sym_stringprep_utf8_to_ucs4)(const char *str, ssize_t len, size_t *items_written);
 
index 4698eed3b8003ca4e0fe16ab8a013874796f70c1..e64bd99747e63efe7bda71096e122731992202a8 100644 (file)
@@ -20,7 +20,7 @@ static inline int dlopen_idn(void) {
 
 #if HAVE_LIBIDN2
 extern int (*sym_idn2_lookup_u8)(const uint8_t* src, uint8_t** lookupname, int flags);
-extern const char *(*sym_idn2_strerror)(int rc);
+extern const char *(*sym_idn2_strerror)(int rc) _const_;
 extern int (*sym_idn2_to_unicode_8z8z)(const char * input, char ** output, int flags);
 #endif