about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2005-09-20 07:46:12 +0000
committerRoland McGrath <roland@gnu.org>2005-09-20 07:46:12 +0000
commite751d28209b03fdb44e3ddc2f4e7defab256770d (patch)
treeb09479d649a5b2997fa35cf7849ba764ec3dd6b6
parentab209d3a5cdfe565602d4857696410bde4213ca3 (diff)
downloadglibc-e751d28209b03fdb44e3ddc2f4e7defab256770d.tar.gz
glibc-e751d28209b03fdb44e3ddc2f4e7defab256770d.tar.xz
glibc-e751d28209b03fdb44e3ddc2f4e7defab256770d.zip
[BZ #1346]
2005-09-20  Roland McGrath  <roland@redhat.com>
	[BZ #1346]
	* elf/dl-load.c (_dl_map_object_from_fd) [HAVE_Z_RELRO]: Do relro
	magic on __stack_prot only if [SHARED].  Skip mprotect if __stack_prot
	lies outside the page-rounded-down relro region.
-rw-r--r--elf/dl-load.c32
1 files changed, 23 insertions, 9 deletions
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 58b0f91731..9a780beae8 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1354,22 +1354,36 @@ cannot allocate TLS data structures for initial thread");
 
   if (__builtin_expect ((stack_flags &~ GL(dl_stack_flags)) & PF_X, 0))
     {
+      if (__builtin_expect (__check_caller (RETURN_ADDRESS (0), allow_ldso),
+			    0) != 0)
+	{
+	  errstring = N_("invalid caller");
+	  goto call_lose;
+	}
+
       /* The stack is presently not executable, but this module
 	 requires that it be executable.  We must change the
 	 protection of the variable which contains the flags used in
 	 the mprotect calls.  */
-#ifdef HAVE_Z_RELRO
+#if defined HAVE_Z_RELRO && defined SHARED
       if ((mode & (__RTLD_DLOPEN | __RTLD_AUDIT)) == __RTLD_DLOPEN)
 	{
-	  uintptr_t p = ((uintptr_t) &__stack_prot) & ~(GLRO(dl_pagesize) - 1);
-	  size_t s = (uintptr_t) &__stack_prot - p + sizeof (int);
-
-	  __mprotect ((void *) p, s, PROT_READ|PROT_WRITE);
-	  if (__builtin_expect (__check_caller (RETURN_ADDRESS (0),
-						allow_ldso) == 0,
-				0))
+	  const uintptr_t p = (uintptr_t) &__stack_prot & -GLRO(dl_pagesize);
+	  const size_t s = (uintptr_t) (&__stack_prot + 1) - p;
+
+	  struct link_map *const m = &GL(dl_rtld_map);
+	  const uintptr_t relro_end = ((m->l_addr + m->l_relro_addr
+					+ m->l_relro_size)
+				       & -GLRO(dl_pagesize));
+	  if (__builtin_expect (p + s <= relro_end, 1))
+	    {
+	      /* The variable lies in the region protected by RELRO.  */
+	      __mprotect ((void *) p, s, PROT_READ|PROT_WRITE);
+	      __stack_prot |= PROT_READ|PROT_WRITE|PROT_EXEC;
+	      __mprotect ((void *) p, s, PROT_READ);
+	    }
+	  else
 	    __stack_prot |= PROT_READ|PROT_WRITE|PROT_EXEC;
-	  __mprotect ((void *) p, s, PROT_READ);
 	}
       else
 #endif