]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: tools: avoid calling dlsym() in static builds
authorWilly Tarreau <w@1wt.eu>
Sat, 16 Jul 2022 11:49:34 +0000 (13:49 +0200)
committerWilly Tarreau <w@1wt.eu>
Sat, 16 Jul 2022 11:49:34 +0000 (13:49 +0200)
Since 2.4 with commit 64192392c ("MINOR: tools: add functions to retrieve
the address of a symbol"), we can resolve symbols. However some old glibc
crash in dlsym() when the program is statically built.

Fortunately even on these old libs we can detect lack of support by
calling dlopen(NULL). Normally it returns a handle to the current
program, but on a static build it returns NULL. This is sufficient to
refrain from calling dlsym() (which will be of very limited use anyway),
so we check this once at boot and use the result when needed.

This may be backported to 2.4. On stable versions, be careful to place
the init code inside an if/endif guard that checks for DL support.

src/tools.c

index e77b7e13bbc8db19fd3dd9d46687ee8496a40772..44424176cc394789da30acc738fb4e9136bc1b7e 100644 (file)
@@ -4920,6 +4920,23 @@ static int dladdr_and_size(const void *addr, Dl_info *dli, size_t *size)
        return ret;
 }
 
+/* dlopen() support: 0=no/not yet checked, 1=ok */
+static int dlopen_usable = 0;
+
+/* Sets dlopen_usable to true if dlopen() works and is usable. We verify if
+ * we're in a static build because some old glibcs used to crash in dlsym()
+ * in this case.
+ */
+void check_if_dlopen_usable()
+{
+       /* dlopen(NULL) returns a handle to the main program or NULL
+        * on static builds.
+        */
+       dlopen_usable = dlopen(NULL, RTLD_LAZY) ? 1 : 0;
+}
+
+INITCALL0(STG_PREPARE, check_if_dlopen_usable);
+
 /* Tries to retrieve the address of the first occurrence symbol <name>.
  * Note that NULL in return is not always an error as a symbol may have that
  * address in special situations.
@@ -4929,7 +4946,8 @@ void *get_sym_curr_addr(const char *name)
        void *ptr = NULL;
 
 #ifdef RTLD_DEFAULT
-       ptr = dlsym(RTLD_DEFAULT, name);
+       if (dlopen_usable)
+               ptr = dlsym(RTLD_DEFAULT, name);
 #endif
        return ptr;
 }
@@ -4944,7 +4962,8 @@ void *get_sym_next_addr(const char *name)
        void *ptr = NULL;
 
 #ifdef RTLD_NEXT
-       ptr = dlsym(RTLD_NEXT, name);
+       if (dlopen_usable)
+               ptr = dlsym(RTLD_NEXT, name);
 #endif
        return ptr;
 }