This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] ld.so: Adjust the auxv if ld.so is directly invoked


Hi,

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.

The executable might want to do this in order to locate the elf header
in memory for e.g. hwcap checks.  In a discussion on libc-help:
http://sources.redhat.com/ml/libc-help/2010-01/msg00019.html the
AT_PHDR field has been identified to be the best way to do this
safely.

The attached patch adds a new parameter to dl_main which holds a
pointer to the auxv on the stack.  That way it is possible to rescan
the vector and adjust several values in dl_main.

I already have a S/390 patch for start.s which will make use of this
and has successfully been tested in combination with that patch.

Tested on x86_64, s390 and s390x.  No regressions.

Ok?

Bye,

-Andreas-


2010-01-13  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>

	* 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.


Index: glibc/elf/dl-sysdep.c
===================================================================
--- glibc.orig/elf/dl-sysdep.c	2010-01-13 09:56:54.000000000 +0100
+++ glibc/elf/dl-sysdep.c	2010-01-13 10:21:34.000000000 +0100
@@ -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;
 }
 
Index: glibc/elf/rtld.c
===================================================================
--- glibc.orig/elf/rtld.c	2010-01-13 09:56:54.000000000 +0100
+++ glibc/elf/rtld.c	2010-01-13 10:21:34.000000000 +0100
@@ -182,7 +182,7 @@ extern struct rtld_global_ro _rtld_local
 
 
 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
@@ -1082,6 +1085,20 @@ of this helper program; chances are you 
 	 makes sense to free the old string first.  */
       main_map->l_name = (char *) "";
       *user_entry = main_map->l_entry;
+
+      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
     {
Index: glibc/elf/dl-open.c
===================================================================
--- glibc.orig/elf/dl-open.c	2010-01-13 09:56:54.000000000 +0100
+++ glibc/elf/dl-open.c	2010-01-13 10:21:34.000000000 +0100
@@ -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.  */
Index: glibc/sysdeps/generic/ldsodefs.h
===================================================================
--- glibc.orig/sysdeps/generic/ldsodefs.h	2010-01-13 09:56:54.000000000 +0100
+++ glibc/sysdeps/generic/ldsodefs.h	2010-01-13 10:21:34.000000000 +0100
@@ -1015,7 +1015,8 @@ extern void *_dl_sysdep_read_whole_file 
 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)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]