about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2003-09-24 01:56:08 +0000
committerRoland McGrath <roland@gnu.org>2003-09-24 01:56:08 +0000
commitc70ba48888000f00556aa91348c9c5a33a508b49 (patch)
treeeb0d2bf8d0d96ff29d929d6ba2efe397262c8109
parent217ed70e1381922db0d0d7fa41e4938114848251 (diff)
downloadglibc-c70ba48888000f00556aa91348c9c5a33a508b49.tar.gz
glibc-c70ba48888000f00556aa91348c9c5a33a508b49.tar.xz
glibc-c70ba48888000f00556aa91348c9c5a33a508b49.zip
* elf/rtld.c (dl_main): In rtld_is_main case, reinitialize
	GL(dl_stack_flags) according to rtld's own PT_GNU_STACK.
	Move GL(dl_make_stack_executable_hook) initialization up.
	* elf/tst-execstack-prog.c: New file.
	* elf/Makefile (tests-execstack-yes): Add it.
	(LDFLAGS-tst-execstack-prog): New variable.
-rw-r--r--ChangeLog9
-rw-r--r--elf/Makefile4
-rw-r--r--elf/rtld.c27
-rw-r--r--elf/tst-execstack-prog.c35
4 files changed, 70 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index 57bee5451c..1c659e8b46 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2003-09-23  Roland McGrath  <roland@redhat.com>
+
+	* elf/rtld.c (dl_main): In rtld_is_main case, reinitialize
+	GL(dl_stack_flags) according to rtld's own PT_GNU_STACK.
+	Move GL(dl_make_stack_executable_hook) initialization up.
+	* elf/tst-execstack-prog.c: New file.
+	* elf/Makefile (tests-execstack-yes): Add it.
+	(LDFLAGS-tst-execstack-prog): New variable.
+
 2003-09-23  Jakub Jelinek  <jakub@redhat.com>
 
 	* sysdeps/x86_64/dl-machine.h (RTLD_START): Set __libc_stack_end
diff --git a/elf/Makefile b/elf/Makefile
index 36f205abb2..2e6b6cb2b2 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -159,7 +159,7 @@ test-srcs = tst-pathopt
 tests-vis-yes = vismain
 tests-nodelete-yes = nodelete nodelete2
 tests-nodlopen-yes = nodlopen nodlopen2
-tests-execstack-yes = tst-execstack tst-execstack-needed
+tests-execstack-yes = tst-execstack tst-execstack-needed tst-execstack-prog
 endif
 modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
 		testobj1_1 failobj constload2 constload3 unloadmod \
@@ -673,6 +673,8 @@ LDFLAGS-tst-execstack-mod = -Wl,-z,execstack
 
 $(objpfx)tst-execstack-needed: $(objpfx)tst-execstack-mod.so
 LDFLAGS-tst-execstack-needed = -Wl,-z,noexecstack
+
+LDFLAGS-tst-execstack-prog = -Wl,-z,execstack
 endif
 
 $(objpfx)tst-array1.out: $(objpfx)tst-array1
diff --git a/elf/rtld.c b/elf/rtld.c
index c17f621cc9..d57d8838ac 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -648,6 +648,10 @@ dl_main (const ElfW(Phdr) *phdr,
   GL(dl_rtld_unlock_recursive) = rtld_lock_default_unlock_recursive;
 #endif
 
+  /* The explicit initialization here is cheaper than processing the reloc
+     in the _rtld_local definition's initializer.  */
+  GL(dl_make_stack_executable_hook) = &_dl_make_stack_executable;
+
   /* Process the environment variable which control the behaviour.  */
   process_envvars (&mode);
 
@@ -748,6 +752,25 @@ of this helper program; chances are you did not intend to run this program.\n\
 	 objects.  */
       _dl_init_paths (library_path);
 
+      /* The initialization of _dl_stack_flags done below assumes the
+	 executable's PT_GNU_STACK may have been honored by the kernel, and
+	 so a PT_GNU_STACK with PF_X set means the stack started out with
+	 execute permission.  However, this is not really true if the
+	 dynamic linker is the executable the kernel loaded.  For this
+	 case, we must reinitialize _dl_stack_flags to match the dynamic
+	 linker itself.  If the dynamic linker was built with a
+	 PT_GNU_STACK, then the kernel may have loaded us with a
+	 nonexecutable stack that we will have to make executable when we
+	 load the program below unless it has a PT_GNU_STACK indicating
+	 nonexecutable stack is ok.  */
+
+      for (ph = phdr; ph < &phdr[phnum]; ++ph)
+	if (ph->p_type == PT_GNU_STACK)
+	  {
+	    GL(dl_stack_flags) = ph->p_flags;
+	    break;
+	  }
+
       if (__builtin_expect (mode, normal) == verify)
 	{
 	  const char *objname;
@@ -954,10 +977,6 @@ of this helper program; chances are you did not intend to run this program.\n\
       _exit (has_interp ? 0 : 2);
     }
 
-  /* The explicit initialization here is cheaper than processing the reloc
-     in the _rtld_local definition's initializer.  */
-  GL(dl_make_stack_executable_hook) = &_dl_make_stack_executable;
-
   if (! rtld_is_main)
     /* Initialize the data structures for the search paths for shared
        objects.  */
diff --git a/elf/tst-execstack-prog.c b/elf/tst-execstack-prog.c
new file mode 100644
index 0000000000..5a66d63ca9
--- /dev/null
+++ b/elf/tst-execstack-prog.c
@@ -0,0 +1,35 @@
+/* Test program for executable stacks in an executable itself.  */
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <error.h>
+
+#include "tst-execstack-mod.c"	/* This defines the `tryme' test function.  */
+
+static void deeper (void (*f) (void));
+
+static int
+do_test (void)
+{
+  tryme ();
+
+  /* Test that growing the stack region gets new executable pages too.  */
+  deeper (&tryme);
+
+  return 0;
+}
+
+static void
+deeper (void (*f) (void))
+{
+  char stack[1100 * 1024];
+  memfrob (stack, sizeof stack);
+  (*f) ();
+  memfrob (stack, sizeof stack);
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"