elf: do not substitute dst in $LD_LIBRARY_PATH twice [BZ #22627]
Commit Message
Starting with commit
glibc-2.18.90-470-g2a939a7e6d81f109d49306bc2e10b4ac9ceed8f9 that
introduced substitution of dynamic string tokens in fillin_rpath,
_dl_init_paths invokes _dl_dst_substitute for $LD_LIBRARY_PATH twice:
the first time it's called directly, the second time the result
is passed on to fillin_rpath which calls expand_dynamic_string_token
which in turn calls _dl_dst_substitute, leading to the following
behaviour:
$ mkdir -p /tmp/'$ORIGIN' && cd /tmp/'$ORIGIN' &&
echo 'int main(){}' |gcc -xc - &&
strace -qq -E LD_LIBRARY_PATH='$ORIGIN' -e /open ./a.out
open("/tmp//tmp/$ORIGIN/tls/x86_64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/tmp//tmp/$ORIGIN/tls/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/tmp//tmp/$ORIGIN/x86_64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/tmp//tmp/$ORIGIN/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
Fix this by removing the direct _dl_dst_substitute invocation.
* elf/dl-load.c (_dl_init_paths): Remove _dl_dst_substitute preparatory
code and invocation.
---
elf/dl-load.c | 20 +-------------------
1 file changed, 1 insertion(+), 19 deletions(-)
Comments
On Dez 18 2017, "Dmitry V. Levin" <ldv@altlinux.org> wrote:
> * elf/dl-load.c (_dl_init_paths): Remove _dl_dst_substitute preparatory
> code and invocation.
Ok.
Andreas.
Please reference the bug in the changelog entry.
Andreas.
I sort of think this shows we need better test coverage for these
substitutions (presumably involving a test creating a $ORIGIN directory,
in this case).
@@ -773,41 +773,23 @@ _dl_init_paths (const char *llp)
if (llp != NULL && *llp != '\0')
{
- char *llp_tmp;
-
-#ifdef SHARED
- /* Expand DSTs. */
- size_t cnt = DL_DST_COUNT (llp, 1);
- if (__glibc_likely (cnt == 0))
- llp_tmp = strdupa (llp);
- else
- {
- /* Determine the length of the substituted string. */
- size_t total = DL_DST_REQUIRED (l, llp, strlen (llp), cnt);
-
- /* Allocate the necessary memory. */
- llp_tmp = (char *) alloca (total + 1);
- llp_tmp = _dl_dst_substitute (l, llp, llp_tmp, 1);
- }
-#else
- llp_tmp = strdupa (llp);
-#endif
+ char *llp_tmp = strdupa (llp);
/* Decompose the LD_LIBRARY_PATH contents. First determine how many
elements it has. */
size_t nllp = 1;
for (const char *cp = llp_tmp; *cp != '\0'; ++cp)
if (*cp == ':' || *cp == ';')
++nllp;
env_path_list.dirs = (struct r_search_path_elem **)
malloc ((nllp + 1) * sizeof (struct r_search_path_elem *));
if (env_path_list.dirs == NULL)
{
errstring = N_("cannot create cache for search path");
goto signal_error;
}
(void) fillin_rpath (llp_tmp, env_path_list.dirs, ":;",
__libc_enable_secure, "LD_LIBRARY_PATH",
NULL, l);