From 3a56ea26730755076cb5bc1d07727c7a4fcb8fd7 Mon Sep 17 00:00:00 2001 From: Andreas Krebbel Date: Fri, 15 Jan 2010 09:09:35 -0800 Subject: [PATCH] ld.so: Adjust the auxv if ld.so is directly invoked. If a binary gets invoked by passing it as argument to ld.so the stack still holds the auxiliary vector of ld.so when entering the _start routine of the executable. So the invocation via ld.so is not fully transparent to the executable. This causes problems if the executable wants to scan the auxv itself. --- ChangeLog | 10 ++++++++++ elf/dl-open.c | 9 +++++---- elf/dl-sysdep.c | 10 +++++----- elf/rtld.c | 41 ++++++++++++++++++++++++++++++----------- sysdeps/generic/ldsodefs.h | 5 +++-- 5 files changed, 53 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1e766bd274..dbfd8646ef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2010-01-13 Andreas Krebbel + + * elf/dl-sysdep.c (_dl_sysdep_start): Added the auxv parameter to + dl_main. + * elf/dl-open.c (_dl_sysdep_start): Likewise.. + * sysdeps/generic/ldsodefs.h (_dl_sysdep_start): Likewise. + * elf/rtld.c (dl_main): Added new parameter auxv. Adjust the + AT_PHDR, AT_PHNUM and AT_ENTRY fields if the ld.so is directly + started. + 2010-01-14 Ulrich Drepper [BZ #11027] diff --git a/elf/dl-open.c b/elf/dl-open.c index e920c7738c..754a263fa1 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -1,5 +1,5 @@ /* Load a shared object at runtime, relocate it, and run its initializer. - Copyright (C) 1996-2007, 2009 Free Software Foundation, Inc. + Copyright (C) 1996-2007, 2009, 2010 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 @@ -40,7 +40,8 @@ extern ElfW(Addr) _dl_sysdep_start (void **start_argptr, void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phnum, - ElfW(Addr) *user_entry)); + ElfW(Addr) *user_entry, + ElfW(auxv_t) *auxv)); weak_extern (BP_SYM (_dl_sysdep_start)) extern int __libc_multiple_libcs; /* Defined in init-first.c. */ @@ -346,8 +347,8 @@ dl_open_worker (void *a) { /* If this here is the shared object which we want to profile make sure the profile is started. We can find out whether - this is necessary or not by observing the `_dl_profile_map' - variable. If was NULL but is not NULL afterwars we must + this is necessary or not by observing the `_dl_profile_map' + variable. If was NULL but is not NULL afterwars we must start the profiling. */ struct link_map *old_profile_map = GL(dl_profile_map); diff --git a/elf/dl-sysdep.c b/elf/dl-sysdep.c index 49c5dfb27d..5507e57b96 100644 --- a/elf/dl-sysdep.c +++ b/elf/dl-sysdep.c @@ -85,7 +85,7 @@ void *_dl_random attribute_relro = NULL; ElfW(Addr) _dl_sysdep_start (void **start_argptr, void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phnum, - ElfW(Addr) *user_entry)) + ElfW(Addr) *user_entry, ElfW(auxv_t) *auxv)) { const ElfW(Phdr) *phdr = NULL; ElfW(Word) phnum = 0; @@ -241,7 +241,7 @@ _dl_sysdep_start (void **start_argptr, if (__builtin_expect (INTUSE(__libc_enable_secure), 0)) __libc_check_standard_fds (); - (*dl_main) (phdr, phnum, &user_entry); + (*dl_main) (phdr, phnum, &user_entry, _dl_auxv); return user_entry; } @@ -511,9 +511,9 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz, /* Fill in the information. This follows the following scheme (indeces from TEMP for four strings): entry #0: 0, 1, 2, 3 binary: 1111 - #1: 0, 1, 3 1101 - #2: 0, 2, 3 1011 - #3: 0, 3 1001 + #1: 0, 1, 3 1101 + #2: 0, 2, 3 1011 + #3: 0, 3 1001 This allows the representation of all possible combinations of capability names in the string. First generate the strings. */ result[1].str = result[0].str = cp = (char *) (result + *sz); diff --git a/elf/rtld.c b/elf/rtld.c index 55b84c3bf4..3afb997f85 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -1,5 +1,5 @@ /* Run time dynamic linker. - Copyright (C) 1995-2006, 2007, 2008, 2009 Free Software Foundation, Inc. + Copyright (C) 1995-2006, 2007, 2008, 2009, 2010 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 @@ -182,7 +182,7 @@ extern struct rtld_global_ro _rtld_local_ro static void dl_main (const ElfW(Phdr) *phdr, ElfW(Word) phnum, - ElfW(Addr) *user_entry); + ElfW(Addr) *user_entry, ElfW(auxv_t) *auxv); /* These two variables cannot be moved into .data.rel.ro. */ static struct libname_list _dl_rtld_libname; @@ -882,7 +882,8 @@ static int version_info attribute_relro; static void dl_main (const ElfW(Phdr) *phdr, ElfW(Word) phnum, - ElfW(Addr) *user_entry) + ElfW(Addr) *user_entry, + ElfW(auxv_t) *auxv) { const ElfW(Phdr) *ph; enum mode mode; @@ -927,6 +928,8 @@ dl_main (const ElfW(Phdr) *phdr, if (*user_entry == (ElfW(Addr)) ENTRY_POINT) { + ElfW(auxv_t) *av; + /* Ho ho. We are not the program interpreter! We are the program itself! This means someone ran ld.so as a command. Well, that might be convenient to do sometimes. We support it by @@ -1013,11 +1016,11 @@ of this helper program; chances are you did not intend to run this program.\n\ \n\ --list list all dependencies and how they are resolved\n\ --verify verify that given object really is a dynamically linked\n\ - object we can handle\n\ + object we can handle\n\ --library-path PATH use given PATH instead of content of the environment\n\ - variable LD_LIBRARY_PATH\n\ + variable LD_LIBRARY_PATH\n\ --inhibit-rpath LIST ignore RUNPATH and RPATH information in object names\n\ - in LIST\n\ + in LIST\n\ --audit LIST use objects named in LIST as auditors\n"); ++_dl_skip_args; @@ -1082,6 +1085,22 @@ of this helper program; chances are you did not intend to run this program.\n\ makes sense to free the old string first. */ main_map->l_name = (char *) ""; *user_entry = main_map->l_entry; + + /* Adjust the on-stack auxiliary vector so that it looks like the + binary was executed directly. */ + for (av = auxv; av->a_type != AT_NULL; av++) + switch (av->a_type) + { + case AT_PHDR: + av->a_un.a_val = phdr; + break; + case AT_PHNUM: + av->a_un.a_val = phnum; + break; + case AT_ENTRY: + av->a_un.a_val = *user_entry; + break; + } } else { @@ -2013,7 +2032,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", _dl_relocate_object (&GL(dl_rtld_map), main_map->l_scope, 0, 0); } - } + } #define VERNEEDTAG (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (DT_VERNEED)) if (version_info) { @@ -2682,10 +2701,10 @@ process_envvars (enum mode *modep) while (*nextp != '\0'); if (__access ("/etc/suid-debug", F_OK) != 0) - { + { unsetenv ("MALLOC_CHECK_"); GLRO(dl_debug_mask) = 0; - } + } if (mode != normal) _exit (5); @@ -2752,7 +2771,7 @@ print_statistics (hp_timing_t *rtld_total_timep) } *wp = '\0'; _dl_debug_printf ("\ - time needed for relocation: %s (%s%%)\n", buf, pbuf); + time needed for relocation: %s (%s%%)\n", buf, pbuf); } #endif @@ -2815,7 +2834,7 @@ print_statistics (hp_timing_t *rtld_total_timep) } *wp = '\0'; _dl_debug_printf ("\ - time needed to load objects: %s (%s%%)\n", + time needed to load objects: %s (%s%%)\n", buf, pbuf); } #endif diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index e18e60f73f..230c39a631 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -1,5 +1,5 @@ /* Run-time dynamic linker data structures for loaded ELF shared objects. - Copyright (C) 1995-2006, 2007, 2008, 2009 Free Software Foundation, Inc. + Copyright (C) 1995-2009, 2010 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 @@ -1015,7 +1015,8 @@ extern void *_dl_sysdep_read_whole_file (const char *file, size_t *sizep, extern ElfW(Addr) _dl_sysdep_start (void **start_argptr, void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phnum, - ElfW(Addr) *user_entry)) + ElfW(Addr) *user_entry, + ElfW(auxv_t) *auxv)) attribute_hidden; extern void _dl_sysdep_start_cleanup (void) -- 2.11.4.GIT