A static binary crashes when started with dynamic string tokens in LD_LIBRARY_PATH. For example: LD_LIBRARY_PATH=/foo/'$LIB' ./elf/ldconfig Segmentation fault (core dumped) The problem is here: elf/dl-load.c (_dl_init_paths): 751 #ifdef SHARED 752 /* This points to the map of the main object. */ 753 l = GL(dl_ns)[LM_ID_BASE]._ns_loaded; 754 if (l != NULL) We only load l within #ifdef SHARED, but later on we use it unconditionally in the following call chain fillin_rpath -> expand_dynamic_string_token -> DL_DST_REQUIRED. Previously we had: # define DL_DST_REQ_STATIC(l) \ if ((l) == NULL) \ { \ const char *origin = _dl_get_origin (); \ dst_len = (origin && origin != (char *) -1 ? strlen (origin) : 0); \ } \ else #endif Which guarded against this case, but after: commit d1d5471579eb0426671bf94f2d71e61dfb204c30 Author: Maciej W. Rozycki <macro@codesourcery.com> Date: Sat Jun 22 00:39:42 2013 +0100 Remove dead DL_DST_REQ_STATIC code. We removed it. Maciej's work was specifically designed to make static/dynamic cases have parity here, and so it just looks like an oversight that we don't unconditionally set the link map. The solution is to always set the link map l, and remove the 'if ((l) == NULL)' because we are never NULL. Interestingly coverity scan detected a logical problem here because it said if l is ever NULL then we'll crash, and it was right. I have a patch for this and it passes the above test. I'll submit it shortly.
OK, so for real I'm going to post this. I dropped the ball.
This bug just hit me during a bootstrap of gcc, as the tls detection macro attempts a compilation with -static and is happy if compilation fails but unhappy if there is a segfault later on: https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=config/tls.m4;h=7532305b908abf8c9874d466dc91eeed18954933;hb=HEAD#l12 The bug still persists in 2.32 - @Carlos
*** Bug 27499 has been marked as a duplicate of this bug. ***
We have an upstream patch for this, but the consequences are not entirely trivial, we have to consider what happens for static binaries. Thanks for Florian for initial review. https://patchwork.sourceware.org/project/glibc/patch/ca723e73-c8eb-ca4c-1ca0-5fbf2b88edcd@redhat.com/
I'm going to post an updated patch.
Fixed for glibc 2.34 via: commit 332421312576bd7095e70589154af99b124dd2d1 Author: Carlos O'Donell <carlos@redhat.com> Date: Fri Mar 12 16:44:47 2021 +0100 elf: Always set l in _dl_init_paths (bug 23462) After d1d5471579eb0426671bf94f2d71e61dfb204c30 ("Remove dead DL_DST_REQ_STATIC code.") we always setup the link map l to make the static and shared cases the same. The bug is that in elf/dl-load.c (_dl_init_paths) we conditionally set l only in the #ifdef SHARED case, but unconditionally use it later. The simple solution is to remove the #ifdef SHARED conditional, because it's no longer needed, and unconditionally setup l for both the static and shared cases. A regression test is added to run a static binary with LD_LIBRARY_PATH='$ORIGIN' which crashes before the fix and runs after the fix. Co-Authored-By: Florian Weimer <fweimer@redhat.com>