aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog31
-rw-r--r--Versions.def1
-rw-r--r--config.h.in3
-rwxr-xr-xconfigure17
-rw-r--r--configure.in9
-rw-r--r--debug/Makefile4
-rw-r--r--debug/Versions2
-rw-r--r--debug/stack_chk_fail.c33
-rw-r--r--debug/stack_chk_fail_local.c30
-rw-r--r--elf/Makefile11
-rw-r--r--elf/Versions4
-rw-r--r--elf/rtld.c54
-rw-r--r--elf/stackguard-macros.h30
-rw-r--r--elf/tst-stackguard1-static.c1
-rw-r--r--elf/tst-stackguard1.c196
-rw-r--r--nptl/Makefile9
-rw-r--r--nptl/pthread_create.c5
-rw-r--r--nptl/sysdeps/i386/tls.h9
-rw-r--r--nptl/sysdeps/powerpc/tls.h22
-rw-r--r--nptl/sysdeps/s390/tls.h10
-rw-r--r--nptl/sysdeps/sparc/tls.h9
-rw-r--r--nptl/sysdeps/x86_64/tls.h9
-rw-r--r--nptl/tst-stackguard1-static.c1
-rw-r--r--nptl/tst-stackguard1.c226
-rw-r--r--sysdeps/generic/dl-osinfo.h13
-rw-r--r--sysdeps/generic/libc-start.c15
-rw-r--r--sysdeps/generic/libc-tls.c11
-rw-r--r--sysdeps/unix/sysv/linux/dl-osinfo.h22
28 files changed, 737 insertions, 50 deletions
diff --git a/ChangeLog b/ChangeLog
index 266d918659..09aeab3bda 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
+
/*
*/
diff --git a/configure b/configure
index 8c978e7512..402da463f9 100755
--- a/configure
+++ b/configure
@@ -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;