[2/3,MIPS] Define USE_DL_EXEC_STACK_OVERRIDE on Mips
diff mbox series

Message ID 1561672142-5907-3-git-send-email-dmladjenovic@wavecomp.com
State New
Headers show
Series
  • Mips support for PT_GNU_STACK
Related show

Commit Message

Dragan Mladjenovic June 27, 2019, 9:50 p.m. UTC
This patch conditionally defines USE_DL_EXEC_STACK_OVERRIDE for hard-float builds
targeting minimum Linux kernel version lower than 4.8. In that case _dl_exec_stack_override
performs run-time check of kernel version and enforces executable stack on pre-4.8 kernels.

We now detect when glibc is built with toolchain that uses GNU.stack notes and xfail the
check-execstack only if one isn't used.

	* sysdeps/unix/sysv/linux/mips/Makefile[$(subdir) == elf] (sysdep-dl-routines):
	Add dl-execstack-ovrd.
	(tests): Add tst-execstack-ovrd and tst-execstack-ovrd1.
	(tests-static): Add tst-execstack-ovrd-static and tst-execstack-ovrd1-static.
	(LDFLAGS-tst-execstack-ovrd*, tst-execstack-ovrd*-ENV ...): New.
	(test-xfail-check-execstack): Enable when mips-has-gnustack is false.
	(test-xfail-tst-execstack-ovrd1, test-xfail-tst-execstack-ovrd1-static): New.
	Likewise enabled.
	* sysdeps/unix/sysv/linux/mips/configure.ac (mips-has-gnustack): New var.
	Set to value of libc_cv_as_noexecstack.
	* sysdeps/unix/sysv/linux/mips/configure: Regenerated.
	* sysdeps/unix/sysv/linux/mips/dl-execstack-ovrd.c: New file.
	* sysdeps/unix/sysv/linux/mips/dl-sysdep.h: New file.
	* sysdeps/unix/sysv/linux/mips/tst-execstack-ovrd-static.c: New file.
	* sysdeps/unix/sysv/linux/mips/tst-execstack-ovrd.c: New file.
	* sysdeps/unix/sysv/linux/mips/tst-execstack-ovrd1-static.c: New file.
	* sysdeps/unix/sysv/linux/mips/tst-execstack-ovrd1.c: New file.
---
 sysdeps/unix/sysv/linux/mips/Makefile              | 28 +++++++++++--
 sysdeps/unix/sysv/linux/mips/configure.ac          |  2 +
 sysdeps/unix/sysv/linux/mips/dl-execstack-ovrd.c   | 48 ++++++++++++++++++++++
 sysdeps/unix/sysv/linux/mips/dl-sysdep.h           | 28 +++++++++++++
 .../sysv/linux/mips/tst-execstack-ovrd-static.c    |  1 +
 sysdeps/unix/sysv/linux/mips/tst-execstack-ovrd.c  |  2 +
 .../sysv/linux/mips/tst-execstack-ovrd1-static.c   |  1 +
 sysdeps/unix/sysv/linux/mips/tst-execstack-ovrd1.c | 11 +++++
 8 files changed, 117 insertions(+), 4 deletions(-)
 create mode 100644 sysdeps/unix/sysv/linux/mips/dl-execstack-ovrd.c
 create mode 100644 sysdeps/unix/sysv/linux/mips/dl-sysdep.h
 create mode 100644 sysdeps/unix/sysv/linux/mips/tst-execstack-ovrd-static.c
 create mode 100644 sysdeps/unix/sysv/linux/mips/tst-execstack-ovrd.c
 create mode 100644 sysdeps/unix/sysv/linux/mips/tst-execstack-ovrd1-static.c
 create mode 100644 sysdeps/unix/sysv/linux/mips/tst-execstack-ovrd1.c

Patch
diff mbox series

diff --git a/sysdeps/unix/sysv/linux/mips/Makefile b/sysdeps/unix/sysv/linux/mips/Makefile
index 8217f42..4f2f422 100644
--- a/sysdeps/unix/sysv/linux/mips/Makefile
+++ b/sysdeps/unix/sysv/linux/mips/Makefile
@@ -57,6 +57,8 @@  abi-n64_hard_2008-condition := defined(__mips_nan2008) \
 			       && (_MIPS_SIM == _MIPS_SIM_ABI64)
 
 ifeq ($(subdir),elf)
+sysdep-dl-routines += dl-execstack-ovrd
+
 ifeq ($(build-shared),yes)
 # This is needed for DSO loading from static binaries.
 sysdep-dl-routines += dl-static
@@ -64,11 +66,29 @@  sysdep-dl-routines += dl-static
 sysdep_routines += dl-vdso
 endif
 
-# Supporting non-executable stacks on MIPS requires changes to both
-# the Linux kernel and glibc.  See
-# <https://sourceware.org/ml/libc-alpha/2016-01/msg00567.html> and
-# <https://sourceware.org/ml/libc-alpha/2016-01/msg00719.html>.
+tests-static += tst-execstack-ovrd-static
+tests += tst-execstack-ovrd-static
+tests += tst-execstack-ovrd
+tests-static += tst-execstack-ovrd1-static
+tests += tst-execstack-ovrd1-static
+tests += tst-execstack-ovrd1
+LDFLAGS-tst-execstack-ovrd = -Wl,-z,noexecstack
+LDFLAGS-tst-execstack-ovrd-static = -Wl,-z,noexecstack
+LDFLAGS-tst-execstack-ovrd1 = -Wl,-z,noexecstack
+LDFLAGS-tst-execstack-ovrd1-static = -Wl,-z,noexecstack
+tst-execstack-ovrd-ENV = LD_ASSUME_KERNEL=4.5.0
+tst-execstack-ovrd-static-ENV = LD_ASSUME_KERNEL=4.5.0
+tst-execstack-ovrd1-ENV = LD_ASSUME_KERNEL=4.8.0
+tst-execstack-ovrd1-static-ENV = LD_ASSUME_KERNEL=4.8.0
+
+# If the compiler doesn't use GNU.stack note,
+# thease tests are expected to fail.
+ifneq ($(mips-has-gnustack),yes)
 test-xfail-check-execstack = yes
+test-xfail-tst-execstack-ovrd1 = yes
+test-xfail-tst-execstack-ovrd1-static = yes
+endif
+
 endif
 
 ifeq ($(subdir),stdlib)
diff --git a/sysdeps/unix/sysv/linux/mips/configure.ac b/sysdeps/unix/sysv/linux/mips/configure.ac
index 9147aa4..bf2c6a9 100644
--- a/sysdeps/unix/sysv/linux/mips/configure.ac
+++ b/sysdeps/unix/sysv/linux/mips/configure.ac
@@ -118,6 +118,8 @@  fi
 LIBC_CONFIG_VAR([default-abi],
   [${libc_mips_abi}_${libc_mips_float}${libc_mips_nan}])
 
+LIBC_CONFIG_VAR([mips-has-gnustack],[${libc_cv_as_noexecstack}])
+
 case $machine in
 mips/mips64/n64/*)
   LIBC_SLIBDIR_RTLDDIR([lib64], [lib64])
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..408186d
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/dl-execstack-ovrd.c
@@ -0,0 +1,48 @@ 
+/* Non-executable stack override for GNU dynamic linker.  MIPS/Linux version.
+   Copyright (C) 2019 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 <dl-sysdep.h>
+
+
+#ifdef USE_DL_EXEC_STACK_OVERRIDE
+
+extern int __stack_prot attribute_relro attribute_hidden;
+
+int
+_dl_exec_stack_override (void* flags)
+{
+  if ((*(ElfW(Word) *)flags & PF_X) == 0
+       && (GLRO(dl_osversion) > 0)
+       && (GLRO(dl_osversion) < __NOEXECSTACK_MIN_KERNEL_VERSION))
+    {
+#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
+      *(ElfW(Word) *)flags |= PF_X;
+    }
+  return 0;
+}
+rtld_hidden_def (_dl_exec_stack_override)
+#endif
diff --git a/sysdeps/unix/sysv/linux/mips/dl-sysdep.h b/sysdeps/unix/sysv/linux/mips/dl-sysdep.h
new file mode 100644
index 0000000..6ac36b6
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/dl-sysdep.h
@@ -0,0 +1,28 @@ 
+/* System-specific settings for dynamic linker code.  Linux version.
+   Copyright (C) 2019 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_next <dl-sysdep.h>
+
+#define __NOEXECSTACK_MIN_KERNEL_VERSION (0x040800)
+
+#ifdef __mips_hard_float
+# if (__LINUX_KERNEL_VERSION < __NOEXECSTACK_MIN_KERNEL_VERSION)
+#  define USE_DL_EXEC_STACK_OVERRIDE 1
+# endif
+#endif
+
diff --git a/sysdeps/unix/sysv/linux/mips/tst-execstack-ovrd-static.c b/sysdeps/unix/sysv/linux/mips/tst-execstack-ovrd-static.c
new file mode 100644
index 0000000..0e5e61b
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/tst-execstack-ovrd-static.c
@@ -0,0 +1 @@ 
+#include "tst-execstack-ovrd.c"
diff --git a/sysdeps/unix/sysv/linux/mips/tst-execstack-ovrd.c b/sysdeps/unix/sysv/linux/mips/tst-execstack-ovrd.c
new file mode 100644
index 0000000..9d2f4ef
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/tst-execstack-ovrd.c
@@ -0,0 +1,2 @@ 
+#include "tst-execstack-prog.c"
+
diff --git a/sysdeps/unix/sysv/linux/mips/tst-execstack-ovrd1-static.c b/sysdeps/unix/sysv/linux/mips/tst-execstack-ovrd1-static.c
new file mode 100644
index 0000000..e45ac94
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/tst-execstack-ovrd1-static.c
@@ -0,0 +1 @@ 
+#include "tst-execstack-ovrd1.c"
diff --git a/sysdeps/unix/sysv/linux/mips/tst-execstack-ovrd1.c b/sysdeps/unix/sysv/linux/mips/tst-execstack-ovrd1.c
new file mode 100644
index 0000000..7e6252d
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/tst-execstack-ovrd1.c
@@ -0,0 +1,11 @@ 
+#include <signal.h>
+
+/* This test may fail (not produce a SIGSEGV) either because
+   DL_SYSDEP_OSCHECK detects that we are running on older kernel
+   than what we specify with LD_ASSUME_KERNEL and thus uses that
+   or the execution environment doesn't have NX semantics
+   (no RIXI support).  */
+#define EXPECTED_SIGNAL SIGSEGV
+
+#include "tst-execstack-prog.c"
+