From patchwork Thu Jan 21 22:11:59 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Faraz Shahbazker X-Patchwork-Id: 10511 Received: (qmail 54109 invoked by alias); 21 Jan 2016 22:12:08 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 54093 invoked by uid 89); 21 Jan 2016 22:12:07 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.2 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_NONE, RP_MATCHES_RCVD, SPF_PASS autolearn=ham version=3.3.2 spammy=dl_main, elfh, prevailing, Initialization X-HELO: mailapp01.imgtec.com Message-ID: <56A157AF.8080504@imgtec.com> Date: Thu, 21 Jan 2016 14:11:59 -0800 From: Faraz Shahbazker User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.2.0 MIME-Version: 1.0 To: "libc-alpha@sourceware.org" Subject: [RFC] [MIPS] Enable non-executable PT_GNU_STACK support References: <56A15768.20005@imgtec.com> In-Reply-To: <56A15768.20005@imgtec.com> 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. * 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 | 4 ++ 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 | 8 ++++ sysdeps/unix/sysv/linux/mips/dl-execstack-ovrd.c | 50 ++++++++++++++++++++++ sysdeps/unix/sysv/linux/mips/init-first.c | 26 +++++++++++ sysdeps/unix/sysv/linux/mips/ldsodefs.h | 2 +- sysdeps/unix/sysv/linux/mips/libc-abis | 6 +++ 13 files changed, 143 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 \ No newline at end of file diff --git a/csu/init-first.c b/csu/init-first.c index 77c6e1c..3e84690 100644 --- a/csu/init-first.c +++ b/csu/init-first.c @@ -77,6 +77,10 @@ _init (int argc, char **argv, char **envp) /* First the initialization which normally would be done by the dynamic linker. */ _dl_non_dynamic_init (); + +#ifdef EXEC_STACK_OVERRIDE + EXEC_STACK_OVERRIDE (&GL(dl_stack_flags)); +#endif #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 + . */ + +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..d0d0e9b 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; @@ -629,6 +632,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 + . */ + +#include +#include +#include + + /* 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..28a3033 --- /dev/null +++ b/sysdeps/unix/sysv/linux/mips/init-first.c @@ -0,0 +1,26 @@ +/* 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 + . */ + +#ifndef SHARED +#include + +# define EXEC_STACK_OVERRIDE GL(dl_exec_stack_override) +#endif /* !SHARED */ + +#include 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..8728f68 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*