[BZ #1346]
authorRoland McGrath <roland@gnu.org>
Tue, 20 Sep 2005 07:46:12 +0000 (07:46 +0000)
committerRoland McGrath <roland@gnu.org>
Tue, 20 Sep 2005 07:46:12 +0000 (07:46 +0000)
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.

elf/dl-load.c

index 58b0f91..9a780be 100644 (file)
@@ -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