diff options
| -rw-r--r-- | ChangeLog | 31 | ||||
| -rw-r--r-- | Versions.def | 1 | ||||
| -rw-r--r-- | config.h.in | 3 | ||||
| -rwxr-xr-x | configure | 17 | ||||
| -rw-r--r-- | configure.in | 9 | ||||
| -rw-r--r-- | debug/Makefile | 4 | ||||
| -rw-r--r-- | debug/Versions | 2 | ||||
| -rw-r--r-- | debug/stack_chk_fail.c | 33 | ||||
| -rw-r--r-- | debug/stack_chk_fail_local.c | 30 | ||||
| -rw-r--r-- | elf/Makefile | 11 | ||||
| -rw-r--r-- | elf/Versions | 4 | ||||
| -rw-r--r-- | elf/rtld.c | 54 | ||||
| -rw-r--r-- | elf/stackguard-macros.h | 30 | ||||
| -rw-r--r-- | elf/tst-stackguard1-static.c | 1 | ||||
| -rw-r--r-- | elf/tst-stackguard1.c | 196 | ||||
| -rw-r--r-- | nptl/Makefile | 9 | ||||
| -rw-r--r-- | nptl/pthread_create.c | 5 | ||||
| -rw-r--r-- | nptl/sysdeps/i386/tls.h | 9 | ||||
| -rw-r--r-- | nptl/sysdeps/powerpc/tls.h | 22 | ||||
| -rw-r--r-- | nptl/sysdeps/s390/tls.h | 10 | ||||
| -rw-r--r-- | nptl/sysdeps/sparc/tls.h | 9 | ||||
| -rw-r--r-- | nptl/sysdeps/x86_64/tls.h | 9 | ||||
| -rw-r--r-- | nptl/tst-stackguard1-static.c | 1 | ||||
| -rw-r--r-- | nptl/tst-stackguard1.c | 226 | ||||
| -rw-r--r-- | sysdeps/generic/dl-osinfo.h | 13 | ||||
| -rw-r--r-- | sysdeps/generic/libc-start.c | 15 | ||||
| -rw-r--r-- | sysdeps/generic/libc-tls.c | 11 | ||||
| -rw-r--r-- | sysdeps/unix/sysv/linux/dl-osinfo.h | 22 |
28 files changed, 737 insertions, 50 deletions
@@ -1,3 +1,34 @@ +2005-06-25 Jakub Jelinek <jakub@redhat.com> + + * Versions.def (ld): Add GLIBC_2.4. + * configure.in: Add --enable-stackguard-randomization option. + (ENABLE_STACKGUARD_RANDOMIZE): New define. + * config.h.in (ENABLE_STACKGUARD_RANDOMIZE): Add. + * sysdeps/unix/sysv/linux/dl-osinfo.h: Include stdint.h. + (_dl_setup_stack_chk_guard): New inline function. + * sysdeps/generic/dl-osinfo.h: Include stdint.h. + (_dl_setup_stack_chk_guard): New inline function. + * elf/rtld.c (__stack_chk_guard): New variable. + (dl_main): Remove all traces of TLS_INIT_TP_EXPENSIVE. + Set __stack_chk_guard to _dl_setup_stack_chk_guard (), + use THREAD_SET_STACK_GUARD if defined. + * elf/Versions (ld): Export __stack_chk_guard@@GLIBC_2.4. + * sysdeps/generic/libc-start.c (__stack_chk_guard): New variable. + (__libc_start_main): Set __stack_chk_guard to + _dl_setup_stack_chk_guard (), use THREAD_SET_STACK_GUARD if defined. + * sysdeps/generic/libc-tls.c (__libc_setup_tls): Remove all + traces of TLS_INIT_TP_EXPENSIVE. + * debug/Versions (libc): Export __stack_chk_fail@@GLIBC_2.4. + * debug/Makefile (routines): Add stack_chk_fail. + (static-only-routines): Add stack_chk_fail_local. + * debug/stack_chk_fail_local.c: New file. + * debug/stack_chk_fail.c: New file. + * elf/Makefile: Add rules to build and run tst-stackguard1{,-static} + tests. + * elf/tst-stackguard1.c: New file. + * elf/tst-stackguard1-static.c: New file. + * elf/stackguard-macros.h: New file. + 2005-06-21 Ulrich Drepper <drepper@redhat.com> * resource/Makefile (tests): Add tst-getrlimit. diff --git a/Versions.def b/Versions.def index 6ae43c79d6..09cef140bf 100644 --- a/Versions.def +++ b/Versions.def @@ -102,6 +102,7 @@ ld { GLIBC_2.0 GLIBC_2.1 GLIBC_2.3 + GLIBC_2.4 GLIBC_PRIVATE } libthread_db { diff --git a/config.h.in b/config.h.in index 70e67bb912..552523a83e 100644 --- a/config.h.in +++ b/config.h.in @@ -223,6 +223,9 @@ /* Define if your assembler and linker support R_PPC_REL16* relocs. */ #undef HAVE_ASM_PPC_REL16 +/* Define if __stack_chk_guard canary should be randomized at program startup. */ +#undef ENABLE_STACKGUARD_RANDOMIZE + /* */ @@ -873,6 +873,9 @@ Optional Features: objects [default=yes if supported] --enable-oldest-abi=ABI configure the oldest ABI supported [e.g. 2.2] [default=glibc default] + --enable-stackguard-randomization + initialize __stack_chk_guard canary with a random + number at program start --enable-add-ons[=DIRS...] configure and build add-ons in DIR1,DIR2,... search for add-ons if no parameter given @@ -1597,6 +1600,20 @@ _ACEOF fi +# Check whether --enable-stackguard-randomization or --disable-stackguard-randomization was given. +if test "${enable_stackguard_randomization+set}" = set; then + enableval="$enable_stackguard_randomization" + enable_stackguard_randomize=$enableval +else + enable_stackguard_randomize=no +fi; +if test "$enable_stackguard_randomize" = yes; then + cat >>confdefs.h <<\_ACEOF +#define ENABLE_STACKGUARD_RANDOMIZE 1 +_ACEOF + +fi + # Check whether --enable-add-ons or --disable-add-ons was given. if test "${enable_add_ons+set}" = set; then enableval="$enable_add_ons" diff --git a/configure.in b/configure.in index 5f46b5e4ef..4396891db5 100644 --- a/configure.in +++ b/configure.in @@ -174,6 +174,15 @@ else fi AC_SUBST(oldest_abi) +AC_ARG_ENABLE([stackguard-randomization], + AC_HELP_STRING([--enable-stackguard-randomization], + [initialize __stack_chk_guard canary with a random number at program start]), + [enable_stackguard_randomize=$enableval], + [enable_stackguard_randomize=no]) +if test "$enable_stackguard_randomize" = yes; then + AC_DEFINE(ENABLE_STACKGUARD_RANDOMIZE) +fi + dnl Generic infrastructure for drop-in additions to libc. AC_ARG_ENABLE([add-ons], AC_HELP_STRING([--enable-add-ons@<:@=DIRS...@:>@], diff --git a/debug/Makefile b/debug/Makefile index 42e64ad16f..6ec08dc94a 100644 --- a/debug/Makefile +++ b/debug/Makefile @@ -31,9 +31,9 @@ routines = backtrace backtracesyms backtracesymsfd noophooks \ printf_chk fprintf_chk vprintf_chk vfprintf_chk \ gets_chk chk_fail readonly-area fgets_chk fgets_u_chk \ read_chk pread_chk pread64_chk recv_chk recvfrom_chk \ - readlink_chk getwd_chk getcwd_chk \ + readlink_chk getwd_chk getcwd_chk stack_chk_fail \ $(static-only-routines) -static-only-routines := warning-nop +static-only-routines := warning-nop stack_chk_fail_local CFLAGS-backtrace.c = -fno-omit-frame-pointer CFLAGS-sprintf_chk.c = -D_IO_MTSAFE_IO diff --git a/debug/Versions b/debug/Versions index fd97834171..051f4df000 100644 --- a/debug/Versions +++ b/debug/Versions @@ -23,5 +23,7 @@ libc { __read_chk; __pread_chk; __pread64_chk; __readlink_chk; __getcwd_chk; __getwd_chk; __recv_chk; __recvfrom_chk; + + __stack_chk_fail; } } diff --git a/debug/stack_chk_fail.c b/debug/stack_chk_fail.c new file mode 100644 index 0000000000..298b323671 --- /dev/null +++ b/debug/stack_chk_fail.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2005 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <stdio.h> +#include <stdlib.h> + + +extern char **__libc_argv attribute_hidden; + +void +__attribute__ ((noreturn)) +__stack_chk_fail (void) +{ + /* The loop is added only to keep gcc happy. */ + while (1) + __libc_message (1, "*** stack smashing detected ***: %s terminated\n", + __libc_argv[0] ?: "<unknown>"); +} diff --git a/debug/stack_chk_fail_local.c b/debug/stack_chk_fail_local.c new file mode 100644 index 0000000000..de0de8f397 --- /dev/null +++ b/debug/stack_chk_fail_local.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2005 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sys/cdefs.h> + +extern void __stack_chk_fail (void) __attribute__ ((noreturn)); + +/* On some architectures, this helps needless PIC pointer setup + that would be needed just for the __stack_chk_fail call. */ + +void __attribute__ ((noreturn)) attribute_hidden +__stack_chk_fail_local (void) +{ + __stack_chk_fail (); +} diff --git a/elf/Makefile b/elf/Makefile index d988baca3b..c43eb02f5b 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -87,7 +87,8 @@ distribute := rtld-Rules \ unload3mod1.c unload3mod2.c unload3mod3.c unload3mod4.c \ unload4mod1.c unload4mod2.c unload4mod3.c unload4mod4.c \ unload6mod1.c unload6mod2.c unload6mod3.c tst-auditmod1.c \ - order2mod1.c order2mod2.c order2mod3.c order2mod4.c + order2mod1.c order2mod2.c order2mod3.c order2mod4.c \ + tst-stackguard1.c tst-stackguard1-static.c CFLAGS-dl-runtime.c = -fexceptions -fasynchronous-unwind-tables CFLAGS-dl-lookup.c = -fexceptions -fasynchronous-unwind-tables @@ -140,7 +141,7 @@ ifeq (yes,$(have-initfini-array)) tests += tst-array1 tst-array2 tst-array3 tst-array4 endif ifeq (yes,$(build-static)) -tests-static = tst-tls1-static tst-tls2-static +tests-static = tst-tls1-static tst-tls2-static tst-stackguard1-static ifeq (yesyesyes,$(build-static)$(build-shared)$(elf)) tests-static += tst-tls9-static tst-tls9-static-ENV = \ @@ -162,7 +163,8 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \ tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-tls15 tst-align \ tst-align2 $(tests-execstack-$(have-z-execstack)) tst-dlmodcount \ tst-dlopenrpath tst-deep1 tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \ - unload3 unload4 unload5 unload6 tst-audit1 tst-global1 order2 + unload3 unload4 unload5 unload6 tst-audit1 tst-global1 order2 \ + tst-stackguard1 # reldep9 test-srcs = tst-pathopt tests-vis-yes = vismain @@ -843,3 +845,6 @@ $(objpfx)order2mod1.so: $(objpfx)order2mod4.so $(objpfx)order2mod4.so: $(objpfx)order2mod3.so $(objpfx)order2mod2.so: $(objpfx)order2mod3.so order2mod2.so-no-z-defs = yes + +tst-stackguard1-ARGS = --command "$(built-program-cmd) --child" +tst-stackguard1-static-ARGS = --command "$(objpfx)tst-stackguard1-static --child" diff --git a/elf/Versions b/elf/Versions index aaacf3e4ea..9c53f1615e 100644 --- a/elf/Versions +++ b/elf/Versions @@ -43,6 +43,10 @@ ld { # runtime interface to TLS __tls_get_addr; } + GLIBC_2.4 { + # stack canary + __stack_chk_guard; + } GLIBC_PRIVATE { # Those are in the dynamic linker, but used by libc.so. __libc_enable_secure; diff --git a/elf/rtld.c b/elf/rtld.c index bd171e977d..21365af2ba 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -80,6 +80,12 @@ char **_dl_argv attribute_relro = NULL; #endif INTDEF(_dl_argv) +#ifndef THREAD_SET_STACK_GUARD +/* Only exported for architectures that don't store the stack guard canary + in thread local area. */ +uintptr_t __stack_chk_guard attribute_relro; +#endif + /* Nonzero if we were run directly. */ unsigned int _dl_skip_args attribute_relro attribute_hidden; @@ -1398,9 +1404,6 @@ ld.so does not support TLS, but program uses it!\n"); always allocate the static block, we never defer it even if no DF_STATIC_TLS bit is set. The reason is that we know glibc will use the static model. */ -# ifndef TLS_INIT_TP_EXPENSIVE -# define TLS_INIT_TP_EXPENSIVE 0 -# endif /* Since we start using the auditing DSOs right away we need to initialize the data structures now. */ @@ -1807,10 +1810,18 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", used. Trying to do it lazily is too hairy to try when there could be multiple threads (from a non-TLS-using libpthread). */ bool was_tls_init_tp_called = tls_init_tp_called; - if (tcbp == NULL && (!TLS_INIT_TP_EXPENSIVE || GL(dl_tls_max_dtv_idx) > 0)) + if (tcbp == NULL) tcbp = init_tls (); #endif + /* Set up the stack checker's canary. */ + uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (); +#ifdef THREAD_SET_STACK_GUARD + THREAD_SET_STACK_GUARD (stack_chk_guard); +#else + __stack_chk_guard = stack_chk_guard; +#endif + if (__builtin_expect (mode, normal) != normal) { /* We were run just to list the shared libraries. It is @@ -2230,29 +2241,26 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", #endif #ifdef USE_TLS - if (GL(dl_tls_max_dtv_idx) > 0 || USE___THREAD || !TLS_INIT_TP_EXPENSIVE) - { - if (!was_tls_init_tp_called && GL(dl_tls_max_dtv_idx) > 0) - ++GL(dl_tls_generation); + if (!was_tls_init_tp_called && GL(dl_tls_max_dtv_idx) > 0) + ++GL(dl_tls_generation); - /* Now that we have completed relocation, the initializer data - for the TLS blocks has its final values and we can copy them - into the main thread's TLS area, which we allocated above. */ - _dl_allocate_tls_init (tcbp); + /* Now that we have completed relocation, the initializer data + for the TLS blocks has its final values and we can copy them + into the main thread's TLS area, which we allocated above. */ + _dl_allocate_tls_init (tcbp); - /* And finally install it for the main thread. If ld.so itself uses - TLS we know the thread pointer was initialized earlier. */ - if (! tls_init_tp_called) - { - const char *lossage = TLS_INIT_TP (tcbp, USE___THREAD); - if (__builtin_expect (lossage != NULL, 0)) - _dl_fatal_printf ("cannot set up thread-local storage: %s\n", - lossage); - } + /* And finally install it for the main thread. If ld.so itself uses + TLS we know the thread pointer was initialized earlier. */ + if (! tls_init_tp_called) + { + const char *lossage = TLS_INIT_TP (tcbp, USE___THREAD); + if (__builtin_expect (lossage != NULL, 0)) + _dl_fatal_printf ("cannot set up thread-local storage: %s\n", + lossage); } - else +#else + NONTLS_INIT_TP; #endif - NONTLS_INIT_TP; #ifdef SHARED /* Auditing checkpoint: we have added all objects. */ diff --git a/elf/stackguard-macros.h b/elf/stackguard-macros.h new file mode 100644 index 0000000000..0fbf4d2c0b --- /dev/null +++ b/elf/stackguard-macros.h @@ -0,0 +1,30 @@ +#include <stdint.h> + +#ifdef __i386__ +# define STACK_CHK_GUARD \ + ({ uintptr_t x; asm ("movl %%gs:0x14, %0" : "=r" (x)); x; }) +#elif defined __x86_64__ +# define STACK_CHK_GUARD \ + ({ uintptr_t x; asm ("movq %%fs:0x28, %0" : "=r" (x)); x; }) +#elif defined __powerpc64__ +# define STACK_CHK_GUARD \ + ({ uintptr_t x; asm ("ld %0,-28688(13)" : "=r" (x)); x; }) +#elif defined __powerpc__ +# define STACK_CHK_GUARD \ + ({ uintptr_t x; asm ("lwz %0,-28680(2)" : "=r" (x)); x; }) +#elif defined __sparc__ && defined __arch64__ +# define STACK_CHK_GUARD \ + ({ uintptr_t x; asm ("ldx [%%g7+0x28], %0" : "=r" (x)); x; }) +#elif defined __sparc__ +# define STACK_CHK_GUARD \ + ({ uintptr_t x; asm ("ld [%%g7+0x14], %0" : "=r" (x)); x; }) +#elif defined __s390x__ +# define STACK_CHK_GUARD \ + ({ uintptr_t x; asm ("ear %0,%a0; sllg %0,%0,32; ear %0,%a1; lg %0,0x28(%0)" : "=r" (x)); x; }) +#elif defined __s390__ +# define STACK_CHK_GUARD \ + ({ uintptr_t x; asm ("ear %0,%%a0; l %0,0x14(%0)" : "=r" (x)); x; }) +#else +extern uintptr_t __stack_chk_guard; +# define STACK_CHK_GUARD __stack_chk_guard +#endif diff --git a/elf/tst-stackguard1-static.c b/elf/tst-stackguard1-static.c new file mode 100644 index 0000000000..db1e21554d --- /dev/null +++ b/elf/tst-stackguard1-static.c @@ -0,0 +1 @@ +#include "tst-stackguard1.c" diff --git a/elf/tst-stackguard1.c b/elf/tst-stackguard1.c new file mode 100644 index 0000000000..480f9297d0 --- /dev/null +++ b/elf/tst-stackguard1.c @@ -0,0 +1,196 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2005. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/wait.h> +#include <stackguard-macros.h> +#include <unistd.h> + +static const char *command; +static bool child; +static uintptr_t stack_chk_guard_copy; +static bool stack_chk_guard_copy_set; +static int fds[2]; + +static void __attribute__ ((constructor)) +con (void) +{ + stack_chk_guard_copy = STACK_CHK_GUARD; + stack_chk_guard_copy_set = true; |
