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] Fix PT_GNU_RELRO support


Hi!

This patch fixes 3 things.
If ld.so is without PT_GNU_STACK but with PT_GNU_RELRO program header
(say on ppc64), elf/ld.so --library-path . /bin/echo would segfault
immediately because of writing into NULL GL(_dl_loaded).
On !DONT_USE_BOOTSTRAP_MAP arches RELRO region info for the dynamic linker
on the other side would not be recorded and thus not mprotected later.
Last, for prelinked programs we need to mprotect as well (after
_dl_resolve_conflicts finishes).

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

	* elf/dl-reloc.c (_dl_relocate_object): Move PT_GNU_RELRO protection
	into...
	(_dl_protect_relro): New routine.
	* sysdeps/generic/ldsodefs.h (_dl_protect_relro): New prototype.
	* elf/rtld.c (_dl_start_final): Copy l_relro_addr and l_relro_size
	from bootstrap_map.
	(_dl_main): Don't set GL(_dl_loaded)->l_relro_{addr,size} here.
	Call _dl_protect_relro for libraries if prelinking.

--- libc/elf/dl-reloc.c.jj	2004-01-22 12:03:00.000000000 +0100
+++ libc/elf/dl-reloc.c	2004-01-22 13:43:23.000000000 +0100
@@ -311,23 +311,25 @@ _dl_relocate_object (struct link_map *l,
   /* In case we can protect the data now that the relocations are
      done, do it.  */
   if (l->l_relro_size != 0)
+    _dl_protect_relro (l);
+}
+INTDEF (_dl_relocate_object)
+
+void internal_function
+_dl_protect_relro (struct link_map *l)
+{
+  ElfW(Addr) start = ((l->l_addr + l->l_relro_addr) & ~(GL(dl_pagesize) - 1));
+  ElfW(Addr) end = ((l->l_addr + l->l_relro_addr + l->l_relro_size)
+		    & ~(GL(dl_pagesize) - 1));
+
+  if (start != end
+      && __mprotect ((void *) start, end - start, PROT_READ) < 0)
     {
-      ElfW(Addr) start = ((l->l_addr + l->l_relro_addr)
-			  & ~(GL(dl_pagesize) - 1));
-      ElfW(Addr) end = ((l->l_addr + l->l_relro_addr + l->l_relro_size)
-			& ~(GL(dl_pagesize) - 1));
-
-      if (start != end
-	  && __mprotect ((void *) start, end - start, PROT_READ) < 0)
-	{
-	  errstring = N_("\
+      const char *errstring = N_("\
 cannot apply additional memory protection after relocation");
-	  goto call_error;
-	}
+      INTUSE(_dl_signal_error) (errno, l->l_name, NULL, errstring);
     }
 }
-INTDEF (_dl_relocate_object)
-
 
 void
 internal_function __attribute_noinline__
--- libc/elf/rtld.c.jj	2004-01-22 12:02:12.000000000 +0100
+++ libc/elf/rtld.c	2004-01-22 14:08:55.000000000 +0100
@@ -224,6 +224,8 @@ _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;
@@ -794,11 +796,6 @@ of this helper program; chances are you 
 	    GL(dl_stack_flags) = ph->p_flags;
 	    break;
 	  }
-	else if (ph->p_type == PT_GNU_RELRO)
-	  {
-	    GL(dl_loaded)->l_relro_addr = ph->p_vaddr;
-	    GL(dl_loaded)->l_relro_size = ph->p_memsz;
-	  }
 
       if (__builtin_expect (mode, normal) == verify)
 	{
@@ -1676,7 +1673,11 @@ cannot allocate TLS data structures for 
 
       /* Mark all the objects so we know they have been already relocated.  */
       for (l = GL(dl_loaded); l != NULL; l = l->l_next)
-	l->l_relocated = 1;
+	{
+	  l->l_relocated = 1;
+	  if (l->l_relro_size)
+	    _dl_protect_relro (l);
+	}
 
       _dl_sysdep_start_cleanup ();
     }
--- libc/sysdeps/generic/ldsodefs.h.jj	2004-01-22 13:43:41.000000000 +0100
+++ libc/sysdeps/generic/ldsodefs.h	2004-01-22 13:47:57.000000000 +0100
@@ -697,6 +697,10 @@ extern void _dl_relocate_object_internal
 					  int lazy, int consider_profiling)
      attribute_hidden;
 
+/* Protect PT_GNU_RELRO area.  */
+extern void _dl_protect_relro (struct link_map *map)
+     internal_function attribute_hidden;
+
 /* Call _dl_signal_error with a message about an unhandled reloc type.
    TYPE is the result of ELFW(R_TYPE) (r_info), i.e. an R_<CPU>_* value.
    PLT is nonzero if this was a PLT reloc; it just affects the message.  */

	Jakub


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