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]

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


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


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