diff options
author | Andreas Krebbel <Andreas.Krebbel@de.ibm.com> | 2010-01-15 09:09:35 -0800 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2010-01-15 09:09:35 -0800 |
commit | 3a56ea26730755076cb5bc1d07727c7a4fcb8fd7 (patch) | |
tree | 37a1e680e8b1e9301e7e7493a64e776f72e7df93 /elf | |
parent | 5306d3613a3e71d8ede6529e858e2398223ac3da (diff) | |
download | glibc-3a56ea26730755076cb5bc1d07727c7a4fcb8fd7.tar.gz glibc-3a56ea26730755076cb5bc1d07727c7a4fcb8fd7.tar.xz glibc-3a56ea26730755076cb5bc1d07727c7a4fcb8fd7.zip |
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.
Diffstat (limited to 'elf')
-rw-r--r-- | elf/dl-open.c | 9 | ||||
-rw-r--r-- | elf/dl-sysdep.c | 10 | ||||
-rw-r--r-- | elf/rtld.c | 41 |
3 files changed, 40 insertions, 20 deletions
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 |