This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC] [MIPS] Enable non-executable PT_GNU_STACK support v2


Check AT_FLAGS bits to decide if the kernel supports a non-executable
stack. If not, keep stack executable in spite of permissions requested for
PT_GNU_STACK. Increment ABIVERSION to 5 to mark the new behaviour.

ChangeLog:
	* csu/init-first.c:
	(_init): Invoke EXEC_STACK_OVERRIDE method for static executables.
	* elf/Makefile: Add execstack-ovrd to list of dl-routines.
	Add tst-execstack-ovrd & tst-execstack-ovrd-static test cases.
	* elf/dl-execstack-ovrd.c: New file.
	(_dl_exec_stack_override) New function.
	* elf/dl-load.c
	(_dl_map_object_from_fd): Check if this machine supports
	non-executable stacks using allow_noexec_stack_p_hook and override
	stack executable permissions accordingly.
	* elf/dl-support.c
	(_dl_exec_stack_override_hook): New variable,  initialize to
	_dl_exec_stack_override at startup.
	* elf/rtld.c
	(dl_main): Initialize _dl_exec_stack_override_hook to
	_dl_exec_stack_override at startup.
	* elf/tst-execstack-ovrd-static.c: New test file.
	* elf/tst-execstack-ovrd.c: New test file.
	* sysdeps/generic/ldsodefs.h
	(_dl_exec_stack_override_hook): New function declaration.
	(_dl_exec_stack_override): Likewise.
	(EXEC_STACK_OVERRIDE): New macro, empty definition.
	* sysdeps/unix/sysv/linux/mips/dl-execstack-ovrd.c: New file.
	(_dl_exec_stack_override) New function.
	* sysdeps/unix/sysv/linux/mips/init-first.c: New file.
	* sysdeps/mips/unix/sysv/linux/mips/ldsodefs.h
	(VALID_ELF_ABIVERSION): Up valid ABI version check to < 6.
	* sysdeps/unix/sysv/linux/mips/libc-abis:
	(MIPS_GNU_STACK): New libc ABI version.
---
 csu/init-first.c                                 |    2 +
 elf/Makefile                                     |   11 +++--
 elf/dl-execstack-ovrd.c                          |   25 +++++++++++
 elf/dl-load.c                                    |    8 ++++
 elf/dl-support.c                                 |    4 ++
 elf/rtld.c                                       |    1 +
 elf/tst-execstack-ovrd-static.c                  |    1 +
 elf/tst-execstack-ovrd.c                         |    1 +
 sysdeps/generic/ldsodefs.h                       |   11 +++++
 sysdeps/unix/sysv/linux/mips/dl-execstack-ovrd.c |   50 ++++++++++++++++++++++
 sysdeps/unix/sysv/linux/mips/init-first.c        |   27 ++++++++++++
 sysdeps/unix/sysv/linux/mips/ldsodefs.h          |    2 +-
 sysdeps/unix/sysv/linux/mips/libc-abis           |    6 +++
 13 files changed, 145 insertions(+), 4 deletions(-)
 create mode 100644 elf/dl-execstack-ovrd.c
 create mode 100644 elf/tst-execstack-ovrd-static.c
 create mode 100644 elf/tst-execstack-ovrd.c
 create mode 100644 sysdeps/unix/sysv/linux/mips/dl-execstack-ovrd.c
 create mode 100644 sysdeps/unix/sysv/linux/mips/init-first.c

diff --git a/csu/init-first.c b/csu/init-first.c
index 77c6e1c..dc51bc0 100644
--- a/csu/init-first.c
+++ b/csu/init-first.c
@@ -77,6 +77,8 @@ _init (int argc, char **argv, char **envp)
   /* First the initialization which normally would be done by the
      dynamic linker.  */
   _dl_non_dynamic_init ();
+
+  EXEC_STACK_OVERRIDE (&GL(dl_stack_flags));
 #endif
 
 #ifdef VDSO_SETUP
diff --git a/elf/Makefile b/elf/Makefile
index 63a5355..e9f6458 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -31,7 +31,8 @@ routines	= $(all-dl-routines) dl-support dl-iteratephdr \
 dl-routines	= $(addprefix dl-,load lookup object reloc deps hwcaps \
 				  runtime error init fini debug misc \
 				  version profile conflict tls origin scope \
-				  execstack caller open close trampoline)
+				  execstack caller open close trampoline \
+				  execstack-ovrd)
 ifeq (yes,$(use-ldconfig))
 dl-routines += dl-cache
 endif
@@ -122,7 +123,8 @@ tests = tst-tls1 tst-tls2 tst-tls9 tst-leaks1 \
 tests-static = tst-tls1-static tst-tls2-static tst-stackguard1-static \
 	       tst-leaks1-static tst-array1-static tst-array5-static \
 	       tst-ptrguard1-static tst-dl-iter-static \
-	       tst-tlsalign-static tst-tlsalign-extern-static
+	       tst-tlsalign-static tst-tlsalign-extern-static \
+	       tst-execstack-ovrd-static
 ifeq (yes,$(build-shared))
 tests-static += tst-tls9-static
 tst-tls9-static-ENV = \
@@ -158,7 +160,8 @@ endif
 test-srcs = tst-pathopt
 selinux-enabled := $(shell cat /selinux/enforce 2> /dev/null)
 ifneq ($(selinux-enabled),1)
-tests-execstack-yes = tst-execstack tst-execstack-needed tst-execstack-prog
+tests-execstack-yes = tst-execstack tst-execstack-needed tst-execstack-prog \
+	tst-execstack-ovrd
 endif
 endif
 ifeq ($(run-built-tests),yes)
@@ -901,6 +904,8 @@ LDFLAGS-tst-execstack-needed = -Wl,-z,noexecstack
 LDFLAGS-tst-execstack-prog = -Wl,-z,execstack
 CFLAGS-tst-execstack-prog.c += -Wno-trampolines
 CFLAGS-tst-execstack-mod.c += -Wno-trampolines
+LDFLAGS-tst-execstack-ovrd = -Wl,-z,noexecstack
+LDFLAGS-tst-execstack-ovrd-static = -Wl,-z,noexecstack
 endif
 
 LDFLAGS-tst-array2 = $(no-as-needed)
diff --git a/elf/dl-execstack-ovrd.c b/elf/dl-execstack-ovrd.c
new file mode 100644
index 0000000..e0b6cd1
--- /dev/null
+++ b/elf/dl-execstack-ovrd.c
@@ -0,0 +1,25 @@
+/* Non-executable stack override for GNU dynamic linker.  Stub version.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+int
+internal_function
+_dl_exec_stack_override (void* flags)
+{
+  return 0;
+}
+rtld_hidden_def (_dl_exec_stack_override)
diff --git a/elf/dl-load.c b/elf/dl-load.c
index c0d6249..bec0d1b 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1278,6 +1278,14 @@ cannot allocate TLS data structures for initial thread");
     /* Adjust the PT_PHDR value by the runtime load address.  */
     l->l_phdr = (ElfW(Phdr) *) ((ElfW(Addr)) l->l_phdr + l->l_addr);
 
+  /* Program requests a non-executable stack, but architecture does
+     not support it.  */
+  if (__glibc_unlikely ((*GL(dl_exec_stack_override_hook)) (&stack_flags) != 0))
+    {
+      errstring = N_("cannot override stack memory protections");
+      goto call_lose_errno;
+    }
+
   if (__glibc_unlikely ((stack_flags &~ GL(dl_stack_flags)) & PF_X))
     {
       if (__glibc_unlikely (__check_caller (RETURN_ADDRESS (0), allow_ldso) != 0))
diff --git a/elf/dl-support.c b/elf/dl-support.c
index c30194c..b25a6b3 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -182,6 +182,10 @@ ElfW(Word) _dl_stack_flags = DEFAULT_STACK_PERMS;
 int (*_dl_make_stack_executable_hook) (void **) internal_function
   = _dl_make_stack_executable;
 
+/* Check if architecture allows non-executable stack.  */
+int (*_dl_exec_stack_override_hook) (void *) internal_function
+  = _dl_exec_stack_override;
+
 
 /* Function in libpthread to wait for termination of lookups.  */
 void (*_dl_wait_lookup_done) (void);
diff --git a/elf/rtld.c b/elf/rtld.c
index 647661c..80a4871 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -768,6 +768,7 @@ dl_main (const ElfW(Phdr) *phdr,
   /* 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;
+  GL(dl_exec_stack_override_hook) = &_dl_exec_stack_override;
 
   /* Process the environment variable which control the behaviour.  */
   process_envvars (&mode);
diff --git a/elf/tst-execstack-ovrd-static.c b/elf/tst-execstack-ovrd-static.c
new file mode 100644
index 0000000..0e5e61b
--- /dev/null
+++ b/elf/tst-execstack-ovrd-static.c
@@ -0,0 +1 @@
+#include "tst-execstack-ovrd.c"
diff --git a/elf/tst-execstack-ovrd.c b/elf/tst-execstack-ovrd.c
new file mode 100644
index 0000000..180657e
--- /dev/null
+++ b/elf/tst-execstack-ovrd.c
@@ -0,0 +1 @@
+#include "tst-execstack-prog.c"
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 2733ac8..bcd772a 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -366,6 +366,9 @@ struct rtld_global
      It returns an errno code or zero on success.  */
   EXTERN int (*_dl_make_stack_executable_hook) (void **) internal_function;
 
+  /* Check if this architecture support non-executable stack segments.  */
+  EXTERN int (*_dl_exec_stack_override_hook) (void *) internal_function;
+
   /* Prevailing state of the stack, PF_X indicating it's executable.  */
   EXTERN ElfW(Word) _dl_stack_flags;
 
@@ -615,6 +618,9 @@ extern const struct rtld_global_ro _rtld_global_ro
 /* dl-support.c defines these and initializes them early on.  */
 extern const ElfW(Phdr) *_dl_phdr;
 extern size_t _dl_phnum;
+
+/* Empty definition to be overridden by arch-specific header.  */
+#define EXEC_STACK_OVERRIDE
 #endif
 
 #if IS_IN (rtld)
@@ -629,6 +635,11 @@ extern void **_dl_initial_error_catch_tsd (void) __attribute__ ((const))
 extern int _dl_make_stack_executable (void **stack_endp) internal_function;
 rtld_hidden_proto (_dl_make_stack_executable)
 
+/* This is the initial value of GL(dl_exec_stack_override_hook).
+   A threads library can change it.  */
+extern int _dl_exec_stack_override (void *) internal_function;
+rtld_hidden_proto (_dl_exec_stack_override)
+
 /* Variable pointing to the end of the stack (or close to it).  This value
    must be constant over the runtime of the application.  Some programs
    might use the variable which results in copy relocations on some
diff --git a/sysdeps/unix/sysv/linux/mips/dl-execstack-ovrd.c b/sysdeps/unix/sysv/linux/mips/dl-execstack-ovrd.c
new file mode 100644
index 0000000..f4ba5b1
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/dl-execstack-ovrd.c
@@ -0,0 +1,50 @@
+/* Non-executable stack override for GNU dynamic linker.  MIPS specific
+   version.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <elf.h>
+#include <ldsodefs.h>
+#include <misc/sys/auxv.h>
+
+ /* Flag to indicate that non-executable stack supported by kernel.
+    Ref: arch/mips/include/asm/elf.h in kernel sources. */
+#define AV_FLAGS_MIPS_GNU_STACK	(1 << 24)
+
+extern int __stack_prot attribute_relro attribute_hidden;
+
+int
+internal_function
+_dl_exec_stack_override (void* flags)
+{
+  if ((*(ElfW(Word) *)flags & PF_X) == 0
+      && (getauxval (AT_FLAGS) & AV_FLAGS_MIPS_GNU_STACK) == 0)
+    {
+#ifndef SHARED
+      /* For static executable, we need to set stack permission here. */
+      uintptr_t page = ((uintptr_t) __libc_stack_end
+		    & -(intptr_t) GLRO(dl_pagesize));
+      if (__mprotect ((void *) page, GLRO(dl_pagesize),
+		      PROT_READ | PROT_WRITE | PROT_EXEC | __stack_prot) < 0)
+	return errno;
+#endif /* !SHARED */
+      *(ElfW(Word) *)flags |= PF_X;
+    }
+
+  return 0;
+}
+rtld_hidden_def (_dl_exec_stack_override)
diff --git a/sysdeps/unix/sysv/linux/mips/init-first.c b/sysdeps/unix/sysv/linux/mips/init-first.c
new file mode 100644
index 0000000..6719bb7
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/init-first.c
@@ -0,0 +1,27 @@
+/* Initialization code run first thing by the ELF startup code.  Linux/ARM.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef SHARED
+#include <ldsodefs.h>
+
+# undef EXEC_STACK_OVERRIDE
+# define EXEC_STACK_OVERRIDE GL(dl_exec_stack_override)
+#endif /* !SHARED */
+
+#include <csu/init-first.c>
diff --git a/sysdeps/unix/sysv/linux/mips/ldsodefs.h b/sysdeps/unix/sysv/linux/mips/ldsodefs.h
index 3d2289c..3eb17d4 100644
--- a/sysdeps/unix/sysv/linux/mips/ldsodefs.h
+++ b/sysdeps/unix/sysv/linux/mips/ldsodefs.h
@@ -34,7 +34,7 @@ extern void _dl_static_init (struct link_map *map);
 #undef VALID_ELF_ABIVERSION
 #define VALID_ELF_ABIVERSION(osabi,ver)			\
   (ver == 0						\
-   || (osabi == ELFOSABI_SYSV && ver < 4)		\
+   || (osabi == ELFOSABI_SYSV && ver < 6)		\
    || (osabi == ELFOSABI_GNU && ver < LIBC_ABI_MAX))
 
 #endif /* ldsodefs.h */
diff --git a/sysdeps/unix/sysv/linux/mips/libc-abis b/sysdeps/unix/sysv/linux/mips/libc-abis
index 14ff603..8d8a18d 100644
--- a/sysdeps/unix/sysv/linux/mips/libc-abis
+++ b/sysdeps/unix/sysv/linux/mips/libc-abis
@@ -14,3 +14,9 @@ UNIQUE
 #
 # MIPS O32 FP64
 MIPS_O32_FP64   mips*-*-linux*
+#
+# MIPS IFUNC
+IFUNC		mips*-*-linux*
+#
+# Non-executable stack support
+MIPS_GNU_STACK mips*-*-linux*
-- 
1.7.9.5


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