Fix: lazily dlopen 2.12 lttng-ust from liblttng-ust-fd.so symbol overrides
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 4 Oct 2022 17:04:38 +0000 (13:04 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 5 Oct 2022 15:04:05 +0000 (11:04 -0400)
Fix warnings:

/usr/lib64/liblttng-ust-common.so.1: undefined symbol: lttng_ust_safe_close_fd

Lazily dlopen liblttng-ust.so.0 when close/fclose are used early before
execution of liblttng-ust-fd.so's constructor, and use it to perform the
perform the required dlsym() lookups to find the 2.12 LTTng-UST symbols.

Also perform these dlopen/dlsym intialization operations from
liblttng-ust-fd.so's contructor, so if close() is used from a signal
handler, it does not have to invoke dlopen()/dlsym() which are not
async-signal-safe.

Add compiler #error around closefrom() which is only emitted on Solaris
and BSDs, and not relevant to the 2.13 custom upgrade scope.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Change-Id: I292434328f512bbb284c97f6a6170edbeef7c222

src/lib/lttng-ust-common/fd-tracker.c
src/lib/lttng-ust-common/fd-tracker.h
src/lib/lttng-ust-fd/lttng-ust-fd.c

index d61cfbc98c26ab1df06e423e154113b329a24c6b..c47dc1fc527eae5e9d2f0c95f22686189cb98abe 100644 (file)
@@ -34,6 +34,8 @@
 
 #include "lib/lttng-ust-common/fd-tracker.h"
 
+#define LTTNG_UST_DLSYM_FAILED_PTR 0x1
+
 /* Operations on the fd set. */
 #define IS_FD_VALID(fd)                        ((fd) >= 0 && (fd) < lttng_ust_max_fd)
 #define GET_FD_SET_FOR_FD(fd, fd_sets) (&((fd_sets)[(fd) / FD_SETSIZE]))
@@ -80,6 +82,76 @@ void lttng_ust_fd_tracker_alloc_tls(void)
        asm volatile ("" : : "m" (URCU_TLS(ust_fd_mutex_nest)));
 }
 
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+static int (*__lttng_ust_safe_close_fd)(int fd, int (*close_cb)(int fd)) = NULL;
+
+void *lttng_ust_safe_close_fd_init(void)
+{
+       if (__lttng_ust_safe_close_fd == NULL) {
+               __lttng_ust_safe_close_fd = dlsym(RTLD_DEFAULT, "lttng_ust_safe_close_fd");
+
+               if (__lttng_ust_safe_close_fd == NULL) {
+                       __lttng_ust_safe_close_fd = (void *) LTTNG_UST_DLSYM_FAILED_PTR;
+                       fprintf(stderr, "%s\n", dlerror());
+               }
+       }
+
+       return __lttng_ust_safe_close_fd;
+}
+
+static int lttng_ust_safe_close_fd_chain(int fd, int (*close_cb)(int fd))
+{
+       assert(__lttng_ust_safe_close_fd != NULL);
+       if (__lttng_ust_safe_close_fd != (void *) LTTNG_UST_DLSYM_FAILED_PTR) {
+               /* Chain on ust-2.12 preload */
+               return __lttng_ust_safe_close_fd(fd, close_cb);
+       } else {
+               /* Fallback to libc symbol */
+               return close_cb(fd);
+       }
+}
+#else
+static int lttng_ust_safe_close_fd_chain(int fd, int (*close_cb)(int fd))
+{
+       return close_cb(fd);
+}
+#endif
+
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+static int (*__lttng_ust_safe_fclose_stream)(FILE *stream, int (*fclose_cb)(FILE *stream)) = NULL;
+
+void *lttng_ust_safe_fclose_stream_init(void)
+{
+       if (__lttng_ust_safe_fclose_stream == NULL) {
+               __lttng_ust_safe_fclose_stream = dlsym(RTLD_DEFAULT, "lttng_ust_safe_fclose_stream");
+
+               if (__lttng_ust_safe_fclose_stream == NULL) {
+                       __lttng_ust_safe_fclose_stream = (void *) LTTNG_UST_DLSYM_FAILED_PTR;
+                       fprintf(stderr, "%s\n", dlerror());
+               }
+       }
+
+       return __lttng_ust_safe_fclose_stream;
+}
+
+static int lttng_ust_safe_fclose_stream_chain(FILE *stream, int (*fclose_cb)(FILE *stream))
+{
+       assert(__lttng_ust_safe_fclose_stream != NULL);
+       if (__lttng_ust_safe_fclose_stream != (void *) LTTNG_UST_DLSYM_FAILED_PTR) {
+               /* Chain on ust-2.12 preload */
+               return __lttng_ust_safe_fclose_stream(stream, fclose_cb);
+       } else {
+               /* Fallback to libc symbol */
+               return fclose_cb(stream);
+       }
+}
+#else
+static int lttng_ust_safe_fclose_stream_chain(FILE *stream, int (*fclose_cb)(FILE *stream))
+{
+       return fclose_cb(stream);
+}
+#endif
+
 /*
  * Allocate the fd set array based on the hard limit set for this
  * process. This will be called during the constructor execution
@@ -302,35 +374,6 @@ static void lttng_ust_delete_fd_from_tracker_orig(int fd)
        DEL_FD_FROM_SET(fd, lttng_fd_set);
 }
 
-#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
-static int (*__lttng_ust_safe_close_fd)(int fd, int (*close_cb)(int fd)) = NULL;
-
-static
-void *_init_lttng_ust_safe_close_fd(void)
-{
-       if (__lttng_ust_safe_close_fd == NULL) {
-               __lttng_ust_safe_close_fd = dlsym(RTLD_DEFAULT, "lttng_ust_safe_close_fd");
-
-               if (__lttng_ust_safe_close_fd == NULL) {
-                       fprintf(stderr, "%s\n", dlerror());
-               }
-       }
-
-       return __lttng_ust_safe_close_fd;
-}
-
-static int lttng_ust_safe_close_fd_chain(int fd, int (*close_cb)(int fd))
-{
-       if (_init_lttng_ust_safe_close_fd()) {
-               /* Chain on ust-2.12 preload */
-               return __lttng_ust_safe_close_fd(fd, close_cb);
-       } else {
-               /* Fallback to libc symbol */
-               return close_cb(fd);
-       }
-}
-#endif
-
 /*
  * Interface allowing applications to close arbitrary file descriptors.
  * We check if it is owned by lttng-ust, and return -1, errno=EBADF
@@ -365,46 +408,13 @@ static int lttng_ust_safe_close_fd_orig(int fd, int (*close_cb)(int fd))
                ret = -1;
                errno = EBADF;
        } else {
-#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
                ret = lttng_ust_safe_close_fd_chain(fd, close_cb);
-#else
-               ret = close_cb(fd);
-#endif
        }
        lttng_ust_unlock_fd_tracker();
 
        return ret;
 }
 
-#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
-static int (*__lttng_ust_safe_fclose_stream)(FILE *stream, int (*fclose_cb)(FILE *stream)) = NULL;
-
-static
-void *_init_lttng_ust_safe_fclose_stream(void)
-{
-       if (__lttng_ust_safe_fclose_stream == NULL) {
-               __lttng_ust_safe_fclose_stream = dlsym(RTLD_DEFAULT, "lttng_ust_safe_fclose_stream");
-
-               if (__lttng_ust_safe_fclose_stream == NULL) {
-                       fprintf(stderr, "%s\n", dlerror());
-               }
-       }
-
-       return __lttng_ust_safe_fclose_stream;
-}
-
-static int lttng_ust_safe_fclose_stream_chain(FILE *stream, int (*fclose_cb)(FILE *stream))
-{
-       if (_init_lttng_ust_safe_fclose_stream()) {
-               /* Chain on ust-2.12 preload */
-               return __lttng_ust_safe_fclose_stream(stream, fclose_cb);
-       } else {
-               /* Fallback to libc symbol */
-               return fclose_cb(stream);
-       }
-}
-#endif
-
 /*
  * Interface allowing applications to close arbitrary streams.
  * We check if it is owned by lttng-ust, and return -1, errno=EBADF
@@ -441,11 +451,7 @@ static int lttng_ust_safe_fclose_stream_orig(FILE *stream, int (*fclose_cb)(FILE
                ret = -1;
                errno = EBADF;
        } else {
-#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
                ret = lttng_ust_safe_fclose_stream_chain(stream, fclose_cb);
-#else
-               ret = fclose_cb(stream);
-#endif
        }
        lttng_ust_unlock_fd_tracker();
 
index 2432eaa47bdbe353afc38084872c72bab1208fc5..657d99eb3ff26441e3ca72d0b334a729e16e17f4 100644 (file)
@@ -13,4 +13,9 @@ void lttng_ust_fd_tracker_init(void)
 void lttng_ust_fd_tracker_alloc_tls(void)
        __attribute__((visibility("hidden")));
 
+#if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
+void *lttng_ust_safe_close_fd_init(void);
+void *lttng_ust_safe_fclose_stream_init(void);
+#endif
+
 #endif
index c58ebdb71bf084316bae330febfa0e0ee4d0c81b..af208a9852dbf03e9442140d6089c9f18472d110 100644 (file)
@@ -16,6 +16,7 @@
 
 #include "common/macros.h"
 #include "common/ust-fd.h"
+#include "lib/lttng-ust-common/fd-tracker.h"
 
 #define LTTNG_UST_DLSYM_FAILED_PTR 0x1
 
@@ -60,25 +61,44 @@ void *_lttng_ust_fd_init_plibc_fclose(void)
        return __lttng_ust_fd_plibc_fclose;
 }
 
-static
-void _lttng_ust_fd_ctor(void)
-       __attribute__((constructor));
-static
-void _lttng_ust_fd_ctor(void)
-{
 #if !defined(LTTNG_UST_CUSTOM_UPGRADE_CONFLICTING_SYMBOLS)
-       void *handle = NULL;
 
+static void *lttng_ust_2_12_handle;
+
+static
+void lttng_ust_init_close_chaining(void)
+{
+       if (lttng_ust_2_12_handle)
+               return;
        /*
         * Load ust-2.12 in the global symbol namespace.
         */
-       handle = dlopen("liblttng-ust.so.0", RTLD_GLOBAL | RTLD_NOW);
-       if (!handle) {
+       lttng_ust_2_12_handle = dlopen("liblttng-ust.so.0", RTLD_GLOBAL | RTLD_NOW);
+       if (!lttng_ust_2_12_handle) {
                fprintf(stderr, "liblttng-ust-fd.so.1: Failed to dlopen liblttng-ust.so.0: %s\n", dlerror());
                abort();
        }
+       /*
+        * Initialize the function pointers to the ust 2.12 symbols in
+        * the constructor since close() has to stay async-signal-safe
+        * and as such, we can't call dlsym() in the override functions.
+        */
+       (void) lttng_ust_safe_close_fd_init();
+       (void) lttng_ust_safe_fclose_stream_init();
+}
+#else
+static
+void lttng_ust_init_close_chaining(void) { }
 #endif
 
+static
+void _lttng_ust_fd_ctor(void)
+       __attribute__((constructor));
+static
+void _lttng_ust_fd_ctor(void)
+{
+       lttng_ust_init_close_chaining();
+
        lttng_ust_common_ctor();
 
        /*
@@ -99,10 +119,13 @@ void _lttng_ust_fd_ctor(void)
  * errno=ENOSYS.
  *
  * There is a short window before the library constructor has executed where
- * this wrapper could call dlsym() and thus not be async-signal-safe.
+ * this wrapper could call dlsym() and dlopen() and thus not be
+ * async-signal-safe.
  */
 int close(int fd)
 {
+       lttng_ust_init_close_chaining();
+
        /*
         * We can't retry dlsym here since close is async-signal-safe.
         */
@@ -131,6 +154,8 @@ int close(int fd)
  */
 int fclose(FILE *stream)
 {
+       lttng_ust_init_close_chaining();
+
        if (_lttng_ust_fd_init_plibc_fclose() == (void *) LTTNG_UST_DLSYM_FAILED_PTR) {
                errno = ENOSYS;
                return -1;
@@ -141,6 +166,9 @@ int fclose(FILE *stream)
 }
 
 #if defined(__sun__) || defined(__FreeBSD__)
+
+#error "Custom upgrade branch does not support Solaris/FreeBSD closefrom"
+
 /* Solaris and FreeBSD. */
 void closefrom(int lowfd)
 {
@@ -151,6 +179,9 @@ void closefrom(int lowfd)
        (void) lttng_ust_safe_closefrom_fd(lowfd, __lttng_ust_fd_plibc_close);
 }
 #elif defined(__NetBSD__) || defined(__OpenBSD__)
+
+#error "Custom upgrade branch does not support NetBSD/OpenBSD closefrom"
+
 /* NetBSD and OpenBSD. */
 int closefrom(int lowfd)
 {
This page took 0.030559 seconds and 5 git commands to generate.