This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


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] One more RELRO fix


Hi!

On !DONT_USE_BOOTSTRAP_MAP platforms, prelink stopped working.
The problem is that ehdr = (ElfW(Ehdr) *) bootstrap_map.l_addr;
of course doesn't work with prelinked ld.so.
Setting GL(dl_rtld_map).l_relro_{addr,size} can very well be done
later, after ld.so itself has been relocated for the first time
but before second time relocation and it should be even faster
(_dl_start used to cycle through all program headers, while
the code in patch as PT_GNU_RELRO check is the sole thing in
the loop can go from the last Phdr down till it finds it
(ATM it is always the last one)).
Also, ld.so apparently did not handle PT_GNU_RELRO program header
in the executable, which this patch adds as well.
Although in most executables PT_GNU_RELRO would be really small
(essentially small .got, .dynamic, .ctors/.dtors/.jcr and that's
about it), there are cases where it can be bigger and IMHO ld.so
should handle it.

2004-01-27  Jakub Jelinek  <jakub@redhat.com>

	* elf/rtld.c (_dl_start_final): Don't set l_relro_* here.
	(_dl_start): And neither here.
	(dl_main): Set GL(dl_loaded)->l_relro_* and
	GL(dl_rtld_map)->l_relro_*.

--- libc/elf/rtld.c.jj	2004-01-27 15:17:27.000000000 +0100
+++ libc/elf/rtld.c	2004-01-27 15:33:34.043449517 +0100
@@ -224,8 +224,6 @@ _dl_start_final (void *arg, struct dl_st
   memcpy (GL(dl_rtld_map).l_info, info->l.l_info,
 	  sizeof GL(dl_rtld_map).l_info);
   GL(dl_rtld_map).l_mach = info->l.l_mach;
-  GL(dl_rtld_map).l_relro_addr = info->l.l_relro_addr;
-  GL(dl_rtld_map).l_relro_size = info->l.l_relro_size;
 #endif
   _dl_setup_hash (&GL(dl_rtld_map));
   GL(dl_rtld_map).l_opencount = 1;
@@ -351,17 +349,16 @@ _dl_start (void *arg)
      on the `l_addr' value, which is not the value we want when prelinked.  */
 #if USE___THREAD
   dtv_t initdtv[3];
-#endif	/* USE___THREAD */
   ElfW(Ehdr) *ehdr
 # ifdef DONT_USE_BOOTSTRAP_MAP
     = (ElfW(Ehdr) *) &_begin;
 # else
+#  error This will not work with prelink.
     = (ElfW(Ehdr) *) bootstrap_map.l_addr;
 # endif
   ElfW(Phdr) *phdr = (ElfW(Phdr) *) ((void *) ehdr + ehdr->e_phoff);
   size_t cnt = ehdr->e_phnum;	/* PT_TLS is usually the last phdr.  */
   while (cnt-- > 0)
-#if USE___THREAD
     if (phdr[cnt].p_type == PT_TLS)
       {
 	void *tlsblock;
@@ -457,13 +454,7 @@ _dl_start (void *arg)
 	/* So far this is module number one.  */
 	bootstrap_map.l_tls_modid = 1;
       }
-    else
 #endif	/* USE___THREAD */
-      if (phdr[cnt].p_type == PT_GNU_RELRO)
-	{
-	  bootstrap_map.l_relro_addr = phdr[cnt].p_vaddr;
-	  bootstrap_map.l_relro_size = phdr[cnt].p_memsz;
-	}
 
 #ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
   ELF_MACHINE_BEFORE_RTLD_RELOC (bootstrap_map.l_info);
@@ -958,6 +949,11 @@ of this helper program; chances are you 
       case PT_GNU_STACK:
 	GL(dl_stack_flags) = ph->p_flags;
 	break;
+
+      case PT_GNU_RELRO:
+	GL(dl_loaded)->l_relro_addr = ph->p_vaddr;
+	GL(dl_loaded)->l_relro_size = ph->p_memsz;
+	break;                            
       }
 #ifdef USE_TLS
     /* Adjust the address of the TLS initialization image in case
@@ -1030,10 +1026,21 @@ of this helper program; chances are you 
   /* Set up the program header information for the dynamic linker
      itself.  It is needed in the dl_iterate_phdr() callbacks.  */
   ElfW(Ehdr) *rtld_ehdr = (ElfW(Ehdr) *) GL(dl_rtld_map).l_map_start;
-  GL(dl_rtld_map).l_phdr = (ElfW(Phdr) *) (GL(dl_rtld_map).l_map_start
-					   + rtld_ehdr->e_phoff);
+  ElfW(Phdr) *rtld_phdr = (ElfW(Phdr) *) (GL(dl_rtld_map).l_map_start
+					  + rtld_ehdr->e_phoff);
+  GL(dl_rtld_map).l_phdr = rtld_phdr;
   GL(dl_rtld_map).l_phnum = rtld_ehdr->e_phnum;
 
+  /* PT_GNU_RELRO is usually the last phdr.  */
+  size_t cnt = rtld_ehdr->e_phnum;
+  while (cnt-- > 0)
+    if (rtld_phdr[cnt].p_type == PT_GNU_RELRO)
+      {
+	GL(dl_rtld_map).l_relro_addr = rtld_phdr[cnt].p_vaddr;
+	GL(dl_rtld_map).l_relro_size = rtld_phdr[cnt].p_memsz;
+	break;
+      }
+
   /* We have two ways to specify objects to preload: via environment
      variable and via the file /etc/ld.so.preload.  The latter can also
      be used when security is enabled.  */

	Jakub


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