about summary refs log tree commit diff
path: root/elf
diff options
context:
space:
mode:
authorAndreas Krebbel <Andreas.Krebbel@de.ibm.com>2010-01-15 09:09:35 -0800
committerUlrich Drepper <drepper@redhat.com>2010-01-15 09:09:35 -0800
commit3a56ea26730755076cb5bc1d07727c7a4fcb8fd7 (patch)
tree37a1e680e8b1e9301e7e7493a64e776f72e7df93 /elf
parent5306d3613a3e71d8ede6529e858e2398223ac3da (diff)
downloadglibc-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.c9
-rw-r--r--elf/dl-sysdep.c10
-rw-r--r--elf/rtld.c41
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