This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [RFC] [MIPS] Enable non-executable PT_GNU_STACK support v2
- From: Faraz Shahbazker <faraz dot shahbazker at imgtec dot com>
- To: Joseph Myers <joseph at codesourcery dot com>
- Cc: "libc-alpha at sourceware dot org" <libc-alpha at sourceware dot org>
- Date: Fri, 5 Feb 2016 10:38:59 -0800
- Subject: Re: [RFC] [MIPS] Enable non-executable PT_GNU_STACK support v2
- Authentication-results: sourceware.org; auth=none
- References: <56A15768 dot 20005 at imgtec dot com> <56A157AF dot 8080504 at imgtec dot com> <alpine dot DEB dot 2 dot 10 dot 1601212215030 dot 24424 at digraph dot polyomino dot org dot uk> <56A6BF93 dot 5010401 at imgtec dot com>
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*
>