diff mbox

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

Message ID 56A6BF93.5010401@imgtec.com
State New, archived
Headers show

Commit Message

Faraz Shahbazker Jan. 26, 2016, 12:36 a.m. UTC
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

Comments

Faraz Shahbazker Feb. 5, 2016, 6:38 p.m. UTC | #1
Bump!

Related patches for review:
* binutils: https://sourceware.org/ml/libc-alpha/2016-01/msg00567.html
* gcc :     https://gcc.gnu.org/ml/gcc-patches/2016-02/msg00444.html

Regards,
Faraz Shahbazker


On 01/25/2016 04:36 PM, Faraz Shahbazker wrote:
> 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*
>
Andreas Schwab Feb. 5, 2016, 7:21 p.m. UTC | #2
Faraz Shahbazker <faraz.shahbazker@imgtec.com> writes:

> 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.

Which means this patch cannot be applied before the IFUNC support is
added.

Andreas.
Joseph Myers Feb. 5, 2016, 10:33 p.m. UTC | #3
On Fri, 5 Feb 2016, Andreas Schwab wrote:

> Faraz Shahbazker <faraz.shahbazker@imgtec.com> writes:
> 
> > 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.
> 
> Which means this patch cannot be applied before the IFUNC support is
> added.

Indeed, and thus it's blocked on the MIPS binutils IFUNC support, but that 
shouldn't stop discussion of the design approach for the 
architecture-independent changes (which are the bulk of this patch).
Aurelien Jarno Aug. 11, 2016, 9:01 p.m. UTC | #4
On 2016-02-05 10:38, Faraz Shahbazker wrote:
> Bump!
> 
> Related patches for review:
> * binutils: https://sourceware.org/ml/libc-alpha/2016-01/msg00567.html
> * gcc :     https://gcc.gnu.org/ml/gcc-patches/2016-02/msg00444.html
> 

It seems that the patches are present in the 2.27 binutils release,
while they are not yet ready on the glibc side (I guess still waiting
on the IFUNC patches).

This means that building binaries with -Wl,-z,noexecstack set the ABI
version to 5 and we then have no way to execute them. Some configure
scripts probe for the availability of this option and enable it
automatically.

Aurelien
Aaro Koskinen Dec. 22, 2016, 12:36 a.m. UTC | #5
Hi,

On Thu, Aug 11, 2016 at 11:01:18PM +0200, Aurelien Jarno wrote:
> On 2016-02-05 10:38, Faraz Shahbazker wrote:
> > Bump!
> > 
> > Related patches for review:
> > * binutils: https://sourceware.org/ml/libc-alpha/2016-01/msg00567.html
> > * gcc :     https://gcc.gnu.org/ml/gcc-patches/2016-02/msg00444.html
> > 
> 
> It seems that the patches are present in the 2.27 binutils release,
> while they are not yet ready on the glibc side (I guess still waiting
> on the IFUNC patches).
> 
> This means that building binaries with -Wl,-z,noexecstack set the ABI
> version to 5 and we then have no way to execute them. Some configure
> scripts probe for the availability of this option and enable it
> automatically.

Would it be possible to revert (or provide option to disable) these
changes in binutils 2.28?

A.
Maciej W. Rozycki Dec. 22, 2016, 12:52 a.m. UTC | #6
Hi,

On Thu, 22 Dec 2016, Aaro Koskinen wrote:

> On Thu, Aug 11, 2016 at 11:01:18PM +0200, Aurelien Jarno wrote:
> > On 2016-02-05 10:38, Faraz Shahbazker wrote:
> > > Bump!
> > > 
> > > Related patches for review:
> > > * binutils: https://sourceware.org/ml/libc-alpha/2016-01/msg00567.html
> > > * gcc :     https://gcc.gnu.org/ml/gcc-patches/2016-02/msg00444.html
> > > 
> > 
> > It seems that the patches are present in the 2.27 binutils release,
> > while they are not yet ready on the glibc side (I guess still waiting
> > on the IFUNC patches).
> > 
> > This means that building binaries with -Wl,-z,noexecstack set the ABI
> > version to 5 and we then have no way to execute them. Some configure
> > scripts probe for the availability of this option and enable it
> > automatically.
> 
> Would it be possible to revert (or provide option to disable) these
> changes in binutils 2.28?

 Making PT_GNU_STACK executables stop working with legacy glibc which 
does not support the feature required is IIUC the whole point of the 
binutils change, so it serves its purpose AFAICT.  I can revert the 
change, but before I do it can someone please tell me why can't MIPS 
support for PT_GNU_STACK be simply pushed to glibc instead?  And what's 
the relevance of the IFUNC feature here (which will now use ABI version 
6, the next available one) -- is there a functional dependency between 
the glibc side of these two features?

  Maciej
Joseph Myers Dec. 22, 2016, 1:07 a.m. UTC | #7
On Thu, 22 Dec 2016, Maciej W. Rozycki wrote:

>  Making PT_GNU_STACK executables stop working with legacy glibc which 
> does not support the feature required is IIUC the whole point of the 
> binutils change, so it serves its purpose AFAICT.  I can revert the 
> change, but before I do it can someone please tell me why can't MIPS 
> support for PT_GNU_STACK be simply pushed to glibc instead?  And what's 
> the relevance of the IFUNC feature here (which will now use ABI version 
> 6, the next available one) -- is there a functional dependency between 
> the glibc side of these two features?

I thought 4 was reserved for IFUNC, meaning that support for 5 implied 
support for IFUNC (because a simple comparison is all that's available to 
tell whether glibc supports the features required by an executable / 
shared library; it's a single ABI version number, not a bitmask of 
features used) and so the ordering was forced.  Certainly the patch here 
lists IFUNC before MIPS_GNU_STACK, and I don't think the libc-abis system 
supports gaps in the numbering (you'd need to put in a dummy name if 4 is 
now to be unused, but then the dummy name would be visible when you run 
libc.so.6, which it shouldn't be).

Has a non-RFC patch posting for glibc for this feature been made?  If it's 
to get in glibc someone will need to post a patch tested against current 
glibc - with the architecture-independent pieces posted separately from 
the MIPS-specific pieces, please, as they are likely to be reviewed 
separately, making sure to include self-contained rationale and pointers 
to any relevant ABIs, information about kernel, GCC, binutils support, 
etc. (I'd suggest updating the comment on the XFAIL in 
sysdeps/unix/sysv/linux/mips/Makefile to give concrete information about 
the specific versions of GCC and binutils needed for the test to pass / 
kernel version needed for no-exec stack support to work properly - I mean 
upstream mainline versions, any references to uncommitted or non-mainline 
patches need to be clear about their status).  Even then, it seems 
unlikely you'll get review in time for 2.25, i.e. by 31 December (and you 
may need to keep pinging weekly); I don't know how many dynamic linker 
experts we have to review the design of the architecture-independent 
pieces.
Joseph Myers Dec. 22, 2016, 1:10 a.m. UTC | #8
On Thu, 22 Dec 2016, Joseph Myers wrote:

> I thought 4 was reserved for IFUNC, meaning that support for 5 implied 
> support for IFUNC (because a simple comparison is all that's available to 
> tell whether glibc supports the features required by an executable / 
> shared library; it's a single ABI version number, not a bitmask of 
> features used) and so the ordering was forced.  Certainly the patch here 
> lists IFUNC before MIPS_GNU_STACK, and I don't think the libc-abis system 
> supports gaps in the numbering (you'd need to put in a dummy name if 4 is 
> now to be unused, but then the dummy name would be visible when you run 
> libc.so.6, which it shouldn't be).

The natural way to address that issue, incidentally, would be to reassign 
number 4 to MIPS_GNU_STACK and say that IFUNC will get number 5 when 
ready.  (All the other comments about patch proposals that are explicitly 
for review not RFC, with rationale, architecture-independent pieces split 
out etc., still apply.)
Aaro Koskinen Dec. 22, 2016, 1:12 a.m. UTC | #9
Hi,

On Thu, Dec 22, 2016 at 12:52:41AM +0000, Maciej W. Rozycki wrote:
> On Thu, 22 Dec 2016, Aaro Koskinen wrote:
> > On Thu, Aug 11, 2016 at 11:01:18PM +0200, Aurelien Jarno wrote:
> > > On 2016-02-05 10:38, Faraz Shahbazker wrote:
> > > > Bump!
> > > > 
> > > > Related patches for review:
> > > > * binutils: https://sourceware.org/ml/libc-alpha/2016-01/msg00567.html
> > > > * gcc :     https://gcc.gnu.org/ml/gcc-patches/2016-02/msg00444.html
> > > > 
> > > 
> > > It seems that the patches are present in the 2.27 binutils release,
> > > while they are not yet ready on the glibc side (I guess still waiting
> > > on the IFUNC patches).
> > > 
> > > This means that building binaries with -Wl,-z,noexecstack set the ABI
> > > version to 5 and we then have no way to execute them. Some configure
> > > scripts probe for the availability of this option and enable it
> > > automatically.
> > 
> > Would it be possible to revert (or provide option to disable) these
> > changes in binutils 2.28?
> 
>  Making PT_GNU_STACK executables stop working with legacy glibc which 
> does not support the feature required is IIUC the whole point of the 
> binutils change, so it serves its purpose AFAICT.

Maybe, but today only "legacy glibc" exists and people have no way
of knowing or preparing for that when taking new binutils into use. I
don't think it's good a practice to make a release that depends on some
imaginary future version of some other software component. At least it's
not very pragmatic.

A.
Maciej W. Rozycki Dec. 22, 2016, 1:39 a.m. UTC | #10
On Thu, 22 Dec 2016, Joseph Myers wrote:

> > I thought 4 was reserved for IFUNC, meaning that support for 5 implied 
> > support for IFUNC (because a simple comparison is all that's available to 
> > tell whether glibc supports the features required by an executable / 
> > shared library; it's a single ABI version number, not a bitmask of 
> > features used) and so the ordering was forced.  Certainly the patch here 
> > lists IFUNC before MIPS_GNU_STACK, and I don't think the libc-abis system 
> > supports gaps in the numbering (you'd need to put in a dummy name if 4 is 
> > now to be unused, but then the dummy name would be visible when you run 
> > libc.so.6, which it shouldn't be).
> 
> The natural way to address that issue, incidentally, would be to reassign 
> number 4 to MIPS_GNU_STACK and say that IFUNC will get number 5 when 
> ready.  (All the other comments about patch proposals that are explicitly 
> for review not RFC, with rationale, architecture-independent pieces split 
> out etc., still apply.)

 Unfortunately binutils 2.27 have been released which already set ABI 
version to 5 despite that they do not support IFUNC.  So we cannot 
retroactively make version 5 imply IFUNC support, and consequently we 
cannot make version 4 imply IFUNC support either, as we work under the 
assumption that any given ABI version supports all the previous 
(lower-numbered) ABI versions' features.

 We can make version 4 imply MIPS_GNU_STACK because it will not break the 
said assumption, and I suppose it may help with chosing reasonable ABI 
names for versions 4 and 5 if we cannot support gaps (why?).  However 
IFUNC will have to use version 6 or higher.

 Have I missed anything?

 Regrettably I haven't realised I need to veto the binutils change before 
it was upstreamed, or at least back it out before 2.27 went out; sorry 
about that.

  Maciej
Joseph Myers Dec. 22, 2016, 1:50 a.m. UTC | #11
On Thu, 22 Dec 2016, Maciej W. Rozycki wrote:

>  Unfortunately binutils 2.27 have been released which already set ABI 
> version to 5 despite that they do not support IFUNC.  So we cannot 
> retroactively make version 5 imply IFUNC support, and consequently we 
> cannot make version 4 imply IFUNC support either, as we work under the 
> assumption that any given ABI version supports all the previous 
> (lower-numbered) ABI versions' features.

It's only if a version was released in glibc that you can't reassign it.  
I don't see why you can't change binutils to use version 4 for GNU_STACK 
(and then 5 for IFUNC), probably including on 2.27 branch - binaries built 
to use version 5 for GNU_STACK just won't work with glibc until it gets 
IFUNC support.  The relevant rule is: glibc doesn't claim to support a 
version unless it supports all ABIs <= that version (that is, all ABIs 
used by binaries that give a version <= that version).

It's OK for binaries to specify an ABI version higher than they require 
(which would, effectively, be the case for binaries built now that use 
version 5 for GNU_STACK - version 5 meaning, under the reassigned numbers, 
that you need a glibc supporting all of MIPS_PLT, UNIQUE, MIPS_O32_FP64, 
GNU_STACK and IFUNC - which is a stricter requirement than necessary, but 
it's OK for binaries to specify stricter requirements than necessary).
Maciej W. Rozycki Dec. 23, 2016, 11:15 p.m. UTC | #12
On Thu, 22 Dec 2016, Joseph Myers wrote:

> It's only if a version was released in glibc that you can't reassign it.  
> I don't see why you can't change binutils to use version 4 for GNU_STACK 
> (and then 5 for IFUNC), probably including on 2.27 branch - binaries built 
> to use version 5 for GNU_STACK just won't work with glibc until it gets 
> IFUNC support.  The relevant rule is: glibc doesn't claim to support a 
> version unless it supports all ABIs <= that version (that is, all ABIs 
> used by binaries that give a version <= that version).
> 
> It's OK for binaries to specify an ABI version higher than they require 
> (which would, effectively, be the case for binaries built now that use 
> version 5 for GNU_STACK - version 5 meaning, under the reassigned numbers, 
> that you need a glibc supporting all of MIPS_PLT, UNIQUE, MIPS_O32_FP64, 
> GNU_STACK and IFUNC - which is a stricter requirement than necessary, but 
> it's OK for binaries to specify stricter requirements than necessary).

 OK, this makes sense to me, thanks for the clarification.

 Change reverted now then with commit 4d4f40e041ce ("MIPS/BFD: Remove 
EI_ABIVERSION 5 allocation for PT_GNU_STACK support") and backported to 
2.28 and 2.27 branches.

 Happy festive season, everyone!

  Maciej
diff mbox

Patch

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*