elf: Always set l in _dl_init_paths (bug 23462)

After d1d5471579 ("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>
This commit is contained in:
Carlos O'Donell 2021-03-12 16:44:47 +01:00 committed by Florian Weimer
parent 08a0ebb20e
commit 3324213125
3 changed files with 66 additions and 36 deletions

View File

@ -164,7 +164,8 @@ tests-static-normal := tst-leaks1-static tst-array1-static tst-array5-static \
tst-dl-iter-static \
tst-tlsalign-static tst-tlsalign-extern-static \
tst-linkall-static tst-env-setuid tst-env-setuid-tunables \
tst-single_threaded-static tst-single_threaded-pthread-static
tst-single_threaded-static tst-single_threaded-pthread-static \
tst-dst-static
tests-static-internal := tst-tls1-static tst-tls2-static \
tst-ptrguard1-static tst-stackguard1-static \
@ -1904,3 +1905,5 @@ $(objpfx)list-tunables.out: tst-rtld-list-tunables.sh $(objpfx)ld.so
cmp tst-rtld-list-tunables.exp \
$(objpfx)/tst-rtld-list-tunables.out > $@; \
$(evaluate-test)
tst-dst-static-ENV = LD_LIBRARY_PATH='$$ORIGIN'

View File

@ -758,50 +758,45 @@ _dl_init_paths (const char *llp, const char *source,
max_dirnamelen = SYSTEM_DIRS_MAX_LEN;
*aelem = NULL;
#ifdef SHARED
/* This points to the map of the main object. */
l = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
if (l != NULL)
{
assert (l->l_type != lt_loaded);
assert (l->l_type != lt_loaded);
if (l->l_info[DT_RUNPATH])
if (l->l_info[DT_RUNPATH])
{
/* Allocate room for the search path and fill in information
from RUNPATH. */
decompose_rpath (&l->l_runpath_dirs,
(const void *) (D_PTR (l, l_info[DT_STRTAB])
+ l->l_info[DT_RUNPATH]->d_un.d_val),
l, "RUNPATH");
/* During rtld init the memory is allocated by the stub malloc,
prevent any attempt to free it by the normal malloc. */
l->l_runpath_dirs.malloced = 0;
/* The RPATH is ignored. */
l->l_rpath_dirs.dirs = (void *) -1;
}
else
{
l->l_runpath_dirs.dirs = (void *) -1;
if (l->l_info[DT_RPATH])
{
/* Allocate room for the search path and fill in information
from RUNPATH. */
decompose_rpath (&l->l_runpath_dirs,
from RPATH. */
decompose_rpath (&l->l_rpath_dirs,
(const void *) (D_PTR (l, l_info[DT_STRTAB])
+ l->l_info[DT_RUNPATH]->d_un.d_val),
l, "RUNPATH");
/* During rtld init the memory is allocated by the stub malloc,
prevent any attempt to free it by the normal malloc. */
l->l_runpath_dirs.malloced = 0;
/* The RPATH is ignored. */
l->l_rpath_dirs.dirs = (void *) -1;
+ l->l_info[DT_RPATH]->d_un.d_val),
l, "RPATH");
/* During rtld init the memory is allocated by the stub
malloc, prevent any attempt to free it by the normal
malloc. */
l->l_rpath_dirs.malloced = 0;
}
else
{
l->l_runpath_dirs.dirs = (void *) -1;
if (l->l_info[DT_RPATH])
{
/* Allocate room for the search path and fill in information
from RPATH. */
decompose_rpath (&l->l_rpath_dirs,
(const void *) (D_PTR (l, l_info[DT_STRTAB])
+ l->l_info[DT_RPATH]->d_un.d_val),
l, "RPATH");
/* During rtld init the memory is allocated by the stub
malloc, prevent any attempt to free it by the normal
malloc. */
l->l_rpath_dirs.malloced = 0;
}
else
l->l_rpath_dirs.dirs = (void *) -1;
}
l->l_rpath_dirs.dirs = (void *) -1;
}
#endif /* SHARED */
if (llp != NULL && *llp != '\0')
{

32
elf/tst-dst-static.c Normal file
View File

@ -0,0 +1,32 @@
/* Test DST expansion for static binaries doesn't carsh. Bug 23462.
Copyright (C) 2021 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
/* The purpose of this test is to exercise the code in elf/dl-loac.c
(_dl_init_paths) or thereabout and ensure that static binaries
don't crash when expanding DSTs.
If the dynamic loader code linked into the static binary cannot
handle expanding the DSTs e.g. null-deref on an incomplete link
map, then it will crash before reaching main, so the test harness
is unnecessary. */
int
main (void)
{
return 0;
}