public inbox for libc-hacker@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] One more RELRO fix
@ 2004-01-27 18:59 Jakub Jelinek
  0 siblings, 0 replies; only message in thread
From: Jakub Jelinek @ 2004-01-27 18:59 UTC (permalink / raw)
  To: Ulrich Drepper; +Cc: Glibc hackers

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

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2004-01-27 18:59 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-01-27 18:59 [PATCH] One more RELRO fix Jakub Jelinek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).