about summary refs log tree commit diff
path: root/sysdeps/unix/sysv/linux/dl-execstack.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2003-09-25 23:04:12 +0000
committerRoland McGrath <roland@gnu.org>2003-09-25 23:04:12 +0000
commite95dc10c40a2a2867aec1bbbb145cf1da022f729 (patch)
treebe212c70865304aef477b35074fa93449c929475 /sysdeps/unix/sysv/linux/dl-execstack.c
parent55715bfca6b803d78847f51219e8d1d4ff7b4902 (diff)
downloadglibc-e95dc10c40a2a2867aec1bbbb145cf1da022f729.tar.gz
glibc-e95dc10c40a2a2867aec1bbbb145cf1da022f729.tar.xz
glibc-e95dc10c40a2a2867aec1bbbb145cf1da022f729.zip
2003-09-25 Roland McGrath <roland@redhat.com>
	* sysdeps/unix/sysv/linux/dl-execstack.c (_dl_make_stack_executable):
	Don't check for zero __libc_stack_end, it should be initialized.
	[_STACK_GROWS_DOWN] [PROT_GROWSDOWN]: Try using PROT_GROWSDOWN flag
	and fall back if it fails with EINVAL.
	[_STACK_GROWS_UP] [PROT_GROWSUP]: Likewise for PROT_GROWSUP.
Diffstat (limited to 'sysdeps/unix/sysv/linux/dl-execstack.c')
-rw-r--r--sysdeps/unix/sysv/linux/dl-execstack.c34
1 files changed, 28 insertions, 6 deletions
diff --git a/sysdeps/unix/sysv/linux/dl-execstack.c b/sysdeps/unix/sysv/linux/dl-execstack.c
index c840f61031..7ea3a714ac 100644
--- a/sysdeps/unix/sysv/linux/dl-execstack.c
+++ b/sysdeps/unix/sysv/linux/dl-execstack.c
@@ -29,16 +29,24 @@ int
 internal_function
 _dl_make_stack_executable (void)
 {
-  if (__libc_stack_end == 0)
-    /* XXX for a DT_NEEDED library that requires the change,
-       this is not initialized yet!
-    */
-    return ENOSYS;
-
 #if _STACK_GROWS_DOWN
   /* This gives us the highest page that needs to be changed.  */
   uintptr_t page = (uintptr_t) __libc_stack_end & -(intptr_t) GL(dl_pagesize);
 
+  /* Newer Linux kernels support a flag to make our job easy.  */
+# ifdef PROT_GROWSDOWN
+  static bool no_growsdown;
+  if (! no_growsdown)
+    {
+      if (__mprotect ((void *) page, GL(dl_pagesize),
+		      PROT_READ|PROT_WRITE|PROT_EXEC|PROT_GROWSDOWN) == 0)
+	return 0;
+      if (errno != EINVAL)
+	return errno;
+      no_growsdown = true;
+    }
+# endif
+
   /* There is always a hole in the address space below the bottom of the
      stack.  So when we make an mprotect call that starts below the bottom
      of the stack, it will include the hole and fail with ENOMEM.
@@ -76,6 +84,20 @@ _dl_make_stack_executable (void)
   /* This gives us the lowest page that needs to be changed.  */
   uintptr_t page = (uintptr_t) __libc_stack_end & -(intptr_t) GL(dl_pagesize);
 
+  /* Newer Linux kernels support a flag to make our job easy.  */
+# ifdef PROT_GROWSUP
+  static bool no_growsup;
+  if (! no_growsup)
+    {
+      if (__mprotect ((void *) page, GL(dl_pagesize),
+		      PROT_READ|PROT_WRITE|PROT_EXEC|PROT_GROWSUP) == 0)
+	return 0;
+      if (errno != EINVAL)
+	return errno;
+      no_growsup = true;
+    }
+# endif
+
   /* There is always a hole in the address space above the top of the
      stack.  So when we make an mprotect call that spans past the top
      of the stack, it will include the hole and fail with ENOMEM.