mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-09 14:50:05 +00:00
* 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.
This commit is contained in:
parent
2f37117b01
commit
35f1e82763
31
ChangeLog
31
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>
|
2005-06-21 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
* resource/Makefile (tests): Add tst-getrlimit.
|
* resource/Makefile (tests): Add tst-getrlimit.
|
||||||
|
@ -102,6 +102,7 @@ ld {
|
|||||||
GLIBC_2.0
|
GLIBC_2.0
|
||||||
GLIBC_2.1
|
GLIBC_2.1
|
||||||
GLIBC_2.3
|
GLIBC_2.3
|
||||||
|
GLIBC_2.4
|
||||||
GLIBC_PRIVATE
|
GLIBC_PRIVATE
|
||||||
}
|
}
|
||||||
libthread_db {
|
libthread_db {
|
||||||
|
@ -223,6 +223,9 @@
|
|||||||
/* Define if your assembler and linker support R_PPC_REL16* relocs. */
|
/* Define if your assembler and linker support R_PPC_REL16* relocs. */
|
||||||
#undef HAVE_ASM_PPC_REL16
|
#undef HAVE_ASM_PPC_REL16
|
||||||
|
|
||||||
|
/* Define if __stack_chk_guard canary should be randomized at program startup. */
|
||||||
|
#undef ENABLE_STACKGUARD_RANDOMIZE
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
17
configure
vendored
17
configure
vendored
@ -873,6 +873,9 @@ Optional Features:
|
|||||||
objects [default=yes if supported]
|
objects [default=yes if supported]
|
||||||
--enable-oldest-abi=ABI configure the oldest ABI supported [e.g. 2.2]
|
--enable-oldest-abi=ABI configure the oldest ABI supported [e.g. 2.2]
|
||||||
[default=glibc default]
|
[default=glibc default]
|
||||||
|
--enable-stackguard-randomization
|
||||||
|
initialize __stack_chk_guard canary with a random
|
||||||
|
number at program start
|
||||||
--enable-add-ons[=DIRS...]
|
--enable-add-ons[=DIRS...]
|
||||||
configure and build add-ons in DIR1,DIR2,... search
|
configure and build add-ons in DIR1,DIR2,... search
|
||||||
for add-ons if no parameter given
|
for add-ons if no parameter given
|
||||||
@ -1597,6 +1600,20 @@ _ACEOF
|
|||||||
fi
|
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.
|
# Check whether --enable-add-ons or --disable-add-ons was given.
|
||||||
if test "${enable_add_ons+set}" = set; then
|
if test "${enable_add_ons+set}" = set; then
|
||||||
enableval="$enable_add_ons"
|
enableval="$enable_add_ons"
|
||||||
|
@ -174,6 +174,15 @@ else
|
|||||||
fi
|
fi
|
||||||
AC_SUBST(oldest_abi)
|
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.
|
dnl Generic infrastructure for drop-in additions to libc.
|
||||||
AC_ARG_ENABLE([add-ons],
|
AC_ARG_ENABLE([add-ons],
|
||||||
AC_HELP_STRING([--enable-add-ons@<:@=DIRS...@:>@],
|
AC_HELP_STRING([--enable-add-ons@<:@=DIRS...@:>@],
|
||||||
|
@ -31,9 +31,9 @@ routines = backtrace backtracesyms backtracesymsfd noophooks \
|
|||||||
printf_chk fprintf_chk vprintf_chk vfprintf_chk \
|
printf_chk fprintf_chk vprintf_chk vfprintf_chk \
|
||||||
gets_chk chk_fail readonly-area fgets_chk fgets_u_chk \
|
gets_chk chk_fail readonly-area fgets_chk fgets_u_chk \
|
||||||
read_chk pread_chk pread64_chk recv_chk recvfrom_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)
|
||||||
static-only-routines := warning-nop
|
static-only-routines := warning-nop stack_chk_fail_local
|
||||||
|
|
||||||
CFLAGS-backtrace.c = -fno-omit-frame-pointer
|
CFLAGS-backtrace.c = -fno-omit-frame-pointer
|
||||||
CFLAGS-sprintf_chk.c = -D_IO_MTSAFE_IO
|
CFLAGS-sprintf_chk.c = -D_IO_MTSAFE_IO
|
||||||
|
@ -23,5 +23,7 @@ libc {
|
|||||||
__read_chk; __pread_chk; __pread64_chk;
|
__read_chk; __pread_chk; __pread64_chk;
|
||||||
__readlink_chk; __getcwd_chk; __getwd_chk;
|
__readlink_chk; __getcwd_chk; __getwd_chk;
|
||||||
__recv_chk; __recvfrom_chk;
|
__recv_chk; __recvfrom_chk;
|
||||||
|
|
||||||
|
__stack_chk_fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
33
debug/stack_chk_fail.c
Normal file
33
debug/stack_chk_fail.c
Normal file
@ -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>");
|
||||||
|
}
|
30
debug/stack_chk_fail_local.c
Normal file
30
debug/stack_chk_fail_local.c
Normal file
@ -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 ();
|
||||||
|
}
|
11
elf/Makefile
11
elf/Makefile
@ -87,7 +87,8 @@ distribute := rtld-Rules \
|
|||||||
unload3mod1.c unload3mod2.c unload3mod3.c unload3mod4.c \
|
unload3mod1.c unload3mod2.c unload3mod3.c unload3mod4.c \
|
||||||
unload4mod1.c unload4mod2.c unload4mod3.c unload4mod4.c \
|
unload4mod1.c unload4mod2.c unload4mod3.c unload4mod4.c \
|
||||||
unload6mod1.c unload6mod2.c unload6mod3.c tst-auditmod1.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-runtime.c = -fexceptions -fasynchronous-unwind-tables
|
||||||
CFLAGS-dl-lookup.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
|
tests += tst-array1 tst-array2 tst-array3 tst-array4
|
||||||
endif
|
endif
|
||||||
ifeq (yes,$(build-static))
|
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))
|
ifeq (yesyesyes,$(build-static)$(build-shared)$(elf))
|
||||||
tests-static += tst-tls9-static
|
tests-static += tst-tls9-static
|
||||||
tst-tls9-static-ENV = \
|
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-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-tls15 tst-align \
|
||||||
tst-align2 $(tests-execstack-$(have-z-execstack)) tst-dlmodcount \
|
tst-align2 $(tests-execstack-$(have-z-execstack)) tst-dlmodcount \
|
||||||
tst-dlopenrpath tst-deep1 tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \
|
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
|
# reldep9
|
||||||
test-srcs = tst-pathopt
|
test-srcs = tst-pathopt
|
||||||
tests-vis-yes = vismain
|
tests-vis-yes = vismain
|
||||||
@ -843,3 +845,6 @@ $(objpfx)order2mod1.so: $(objpfx)order2mod4.so
|
|||||||
$(objpfx)order2mod4.so: $(objpfx)order2mod3.so
|
$(objpfx)order2mod4.so: $(objpfx)order2mod3.so
|
||||||
$(objpfx)order2mod2.so: $(objpfx)order2mod3.so
|
$(objpfx)order2mod2.so: $(objpfx)order2mod3.so
|
||||||
order2mod2.so-no-z-defs = yes
|
order2mod2.so-no-z-defs = yes
|
||||||
|
|
||||||
|
tst-stackguard1-ARGS = --command "$(built-program-cmd) --child"
|
||||||
|
tst-stackguard1-static-ARGS = --command "$(objpfx)tst-stackguard1-static --child"
|
||||||
|
@ -43,6 +43,10 @@ ld {
|
|||||||
# runtime interface to TLS
|
# runtime interface to TLS
|
||||||
__tls_get_addr;
|
__tls_get_addr;
|
||||||
}
|
}
|
||||||
|
GLIBC_2.4 {
|
||||||
|
# stack canary
|
||||||
|
__stack_chk_guard;
|
||||||
|
}
|
||||||
GLIBC_PRIVATE {
|
GLIBC_PRIVATE {
|
||||||
# Those are in the dynamic linker, but used by libc.so.
|
# Those are in the dynamic linker, but used by libc.so.
|
||||||
__libc_enable_secure;
|
__libc_enable_secure;
|
||||||
|
56
elf/rtld.c
56
elf/rtld.c
@ -80,6 +80,12 @@ char **_dl_argv attribute_relro = NULL;
|
|||||||
#endif
|
#endif
|
||||||
INTDEF(_dl_argv)
|
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. */
|
/* Nonzero if we were run directly. */
|
||||||
unsigned int _dl_skip_args attribute_relro attribute_hidden;
|
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
|
always allocate the static block, we never defer it even if
|
||||||
no DF_STATIC_TLS bit is set. The reason is that we know
|
no DF_STATIC_TLS bit is set. The reason is that we know
|
||||||
glibc will use the static model. */
|
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
|
/* Since we start using the auditing DSOs right away we need to
|
||||||
initialize the data structures now. */
|
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
|
used. Trying to do it lazily is too hairy to try when there could be
|
||||||
multiple threads (from a non-TLS-using libpthread). */
|
multiple threads (from a non-TLS-using libpthread). */
|
||||||
bool was_tls_init_tp_called = tls_init_tp_called;
|
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 ();
|
tcbp = init_tls ();
|
||||||
#endif
|
#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)
|
if (__builtin_expect (mode, normal) != normal)
|
||||||
{
|
{
|
||||||
/* We were run just to list the shared libraries. It is
|
/* 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
|
#endif
|
||||||
|
|
||||||
#ifdef USE_TLS
|
#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);
|
||||||
|
|
||||||
|
/* 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)
|
||||||
{
|
{
|
||||||
if (!was_tls_init_tp_called && GL(dl_tls_max_dtv_idx) > 0)
|
const char *lossage = TLS_INIT_TP (tcbp, USE___THREAD);
|
||||||
++GL(dl_tls_generation);
|
if (__builtin_expect (lossage != NULL, 0))
|
||||||
|
_dl_fatal_printf ("cannot set up thread-local storage: %s\n",
|
||||||
/* Now that we have completed relocation, the initializer data
|
lossage);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
#else
|
||||||
|
NONTLS_INIT_TP;
|
||||||
#endif
|
#endif
|
||||||
NONTLS_INIT_TP;
|
|
||||||
|
|
||||||
#ifdef SHARED
|
#ifdef SHARED
|
||||||
/* Auditing checkpoint: we have added all objects. */
|
/* Auditing checkpoint: we have added all objects. */
|
||||||
|
30
elf/stackguard-macros.h
Normal file
30
elf/stackguard-macros.h
Normal file
@ -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
|
1
elf/tst-stackguard1-static.c
Normal file
1
elf/tst-stackguard1-static.c
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "tst-stackguard1.c"
|
196
elf/tst-stackguard1.c
Normal file
196
elf/tst-stackguard1.c
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
uintptr_t_cmp (const void *a, const void *b)
|
||||||
|
{
|
||||||
|
if (*(uintptr_t *) a < *(uintptr_t *) b)
|
||||||
|
return 1;
|
||||||
|
if (*(uintptr_t *) a > *(uintptr_t *) b)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_test (void)
|
||||||
|
{
|
||||||
|
if (!stack_chk_guard_copy_set)
|
||||||
|
{
|
||||||
|
puts ("constructor has not been run");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stack_chk_guard_copy != STACK_CHK_GUARD)
|
||||||
|
{
|
||||||
|
puts ("STACK_CHK_GUARD changed between constructor and do_test");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (child)
|
||||||
|
{
|
||||||
|
write (2, &stack_chk_guard_copy, sizeof (stack_chk_guard_copy));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command == NULL)
|
||||||
|
{
|
||||||
|
puts ("missing --command or --child argument");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define N 16
|
||||||
|
uintptr_t child_stack_chk_guards[N + 1];
|
||||||
|
child_stack_chk_guards[N] = stack_chk_guard_copy;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < N; ++i)
|
||||||
|
{
|
||||||
|
if (pipe (fds) < 0)
|
||||||
|
{
|
||||||
|
printf ("couldn't create pipe: %m\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid_t pid = fork ();
|
||||||
|
if (pid < 0)
|
||||||
|
{
|
||||||
|
printf ("fork failed: %m\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pid)
|
||||||
|
{
|
||||||
|
if (stack_chk_guard_copy != STACK_CHK_GUARD)
|
||||||
|
{
|
||||||
|
puts ("STACK_CHK_GUARD changed after fork");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
close (fds[0]);
|
||||||
|
close (2);
|
||||||
|
dup2 (fds[1], 2);
|
||||||
|
close (fds[1]);
|
||||||
|
|
||||||
|
system (command);
|
||||||
|
exit (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
close (fds[1]);
|
||||||
|
|
||||||
|
if (TEMP_FAILURE_RETRY (read (fds[0], &child_stack_chk_guards[i],
|
||||||
|
sizeof (uintptr_t))) != sizeof (uintptr_t))
|
||||||
|
{
|
||||||
|
puts ("could not read stack_chk_guard value from child");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
close (fds[0]);
|
||||||
|
|
||||||
|
pid_t termpid;
|
||||||
|
int status;
|
||||||
|
termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
|
||||||
|
if (termpid == -1)
|
||||||
|
{
|
||||||
|
printf ("waitpid failed: %m\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (termpid != pid)
|
||||||
|
{
|
||||||
|
printf ("waitpid returned %ld != %ld\n",
|
||||||
|
(long int) termpid, (long int) pid);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (!WIFEXITED (status) || WEXITSTATUS (status))
|
||||||
|
{
|
||||||
|
puts ("child hasn't exited with exit status 0");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qsort (child_stack_chk_guards, N + 1, sizeof (uintptr_t), uintptr_t_cmp);
|
||||||
|
|
||||||
|
uintptr_t default_guard = 0;
|
||||||
|
unsigned char *p = (unsigned char *) &default_guard;
|
||||||
|
p[sizeof (uintptr_t) - 1] = 255;
|
||||||
|
p[sizeof (uintptr_t) - 2] = '\n';
|
||||||
|
p[0] = 0;
|
||||||
|
|
||||||
|
/* Test if the stack guard canaries are either randomized,
|
||||||
|
or equal to the default stack guard canary value.
|
||||||
|
Even with randomized stack guards it might happen
|
||||||
|
that the random number generator generates the same
|
||||||
|
values, but if that happens in more than half from
|
||||||
|
the 16 runs, something is very wrong. */
|
||||||
|
int ndifferences = 0;
|
||||||
|
int ndefaults = 0;
|
||||||
|
for (i = 0; i < N; ++i)
|
||||||
|
{
|
||||||
|
if (child_stack_chk_guards[i] != child_stack_chk_guards[i+1])
|
||||||
|
ndifferences++;
|
||||||
|
else if (child_stack_chk_guards[i] == default_guard)
|
||||||
|
ndefaults++;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf ("differences %d defaults %d\n", ndifferences, ndefaults);
|
||||||
|
|
||||||
|
if (ndifferences < N / 2 && ndefaults < N / 2)
|
||||||
|
{
|
||||||
|
puts ("stack guard canaries are not randomized enough");
|
||||||
|
puts ("nor equal to the default canary value");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define OPT_COMMAND 10000
|
||||||
|
#define OPT_CHILD 10001
|
||||||
|
#define CMDLINE_OPTIONS \
|
||||||
|
{ "command", required_argument, NULL, OPT_COMMAND }, \
|
||||||
|
{ "child", no_argument, NULL, OPT_CHILD },
|
||||||
|
#define CMDLINE_PROCESS \
|
||||||
|
case OPT_COMMAND: \
|
||||||
|
command = optarg; \
|
||||||
|
break; \
|
||||||
|
case OPT_CHILD: \
|
||||||
|
child = true; \
|
||||||
|
break;
|
||||||
|
#define TEST_FUNCTION do_test ()
|
||||||
|
#include "../test-skeleton.c"
|
@ -269,7 +269,8 @@ tests += tst-cancelx2 tst-cancelx3 tst-cancelx4 tst-cancelx5 \
|
|||||||
tst-oncex3 tst-oncex4
|
tst-oncex3 tst-oncex4
|
||||||
endif
|
endif
|
||||||
ifeq ($(build-shared),yes)
|
ifeq ($(build-shared),yes)
|
||||||
tests += tst-atfork2 tst-tls3 tst-tls4 tst-tls5 tst-_res1 tst-fini1
|
tests += tst-atfork2 tst-tls3 tst-tls4 tst-tls5 tst-_res1 tst-fini1 \
|
||||||
|
tst-stackguard1
|
||||||
tests-nolibpthread += tst-fini1
|
tests-nolibpthread += tst-fini1
|
||||||
ifeq ($(have-z-execstack),yes)
|
ifeq ($(have-z-execstack),yes)
|
||||||
tests += tst-execstack
|
tests += tst-execstack
|
||||||
@ -337,7 +338,8 @@ link-libc-static := $(common-objpfx)libc.a $(static-gnulib) \
|
|||||||
$(common-objpfx)libc.a
|
$(common-objpfx)libc.a
|
||||||
|
|
||||||
ifeq ($(build-static),yes)
|
ifeq ($(build-static),yes)
|
||||||
tests-static += tst-locale1 tst-locale2
|
tests-static += tst-locale1 tst-locale2 tst-stackguard1-static
|
||||||
|
tests += tst-stackguard1-static
|
||||||
xtests-static += tst-setuid1-static
|
xtests-static += tst-setuid1-static
|
||||||
endif
|
endif
|
||||||
# These tests are linked with libc before libpthread
|
# These tests are linked with libc before libpthread
|
||||||
@ -586,6 +588,9 @@ LDFLAGS-tst-execstack = -Wl,-z,noexecstack
|
|||||||
|
|
||||||
$(objpfx)tst-fini1mod.so: $(shared-thread-library)
|
$(objpfx)tst-fini1mod.so: $(shared-thread-library)
|
||||||
|
|
||||||
|
tst-stackguard1-ARGS = --command "$(built-program-cmd) --child"
|
||||||
|
tst-stackguard1-static-ARGS = --command "$(objpfx)tst-stackguard1-static --child"
|
||||||
|
|
||||||
# The tests here better do not run in parallel
|
# The tests here better do not run in parallel
|
||||||
ifneq ($(filter %tests,$(MAKECMDGOALS)),)
|
ifneq ($(filter %tests,$(MAKECMDGOALS)),)
|
||||||
.NOTPARALLEL:
|
.NOTPARALLEL:
|
||||||
|
@ -399,6 +399,11 @@ __pthread_create_2_1 (newthread, attr, start_routine, arg)
|
|||||||
pd->schedpolicy = self->schedpolicy;
|
pd->schedpolicy = self->schedpolicy;
|
||||||
pd->schedparam = self->schedparam;
|
pd->schedparam = self->schedparam;
|
||||||
|
|
||||||
|
/* Copy the stack guard canary. */
|
||||||
|
#ifdef THREAD_COPY_STACK_GUARD
|
||||||
|
THREAD_COPY_STACK_GUARD (pd);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Determine scheduling parameters for the thread. */
|
/* Determine scheduling parameters for the thread. */
|
||||||
if (attr != NULL
|
if (attr != NULL
|
||||||
&& __builtin_expect ((iattr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0, 0)
|
&& __builtin_expect ((iattr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0, 0)
|
||||||
|
@ -49,6 +49,7 @@ typedef struct
|
|||||||
void *self; /* Pointer to the thread descriptor. */
|
void *self; /* Pointer to the thread descriptor. */
|
||||||
int multiple_threads;
|
int multiple_threads;
|
||||||
uintptr_t sysinfo;
|
uintptr_t sysinfo;
|
||||||
|
uintptr_t stack_guard;
|
||||||
} tcbhead_t;
|
} tcbhead_t;
|
||||||
|
|
||||||
# define TLS_MULTIPLE_THREADS_IN_TCB 1
|
# define TLS_MULTIPLE_THREADS_IN_TCB 1
|
||||||
@ -416,6 +417,14 @@ union user_desc_init
|
|||||||
__res; })
|
__res; })
|
||||||
|
|
||||||
|
|
||||||
|
/* Set the stack guard field in TCB head. */
|
||||||
|
#define THREAD_SET_STACK_GUARD(value) \
|
||||||
|
THREAD_SETMEM (THREAD_SELF, header.stack_guard, value)
|
||||||
|
#define THREAD_COPY_STACK_GUARD(descr) \
|
||||||
|
((descr)->header.stack_guard \
|
||||||
|
= THREAD_GETMEM (THREAD_SELF, header.stack_guard))
|
||||||
|
|
||||||
|
|
||||||
#endif /* __ASSEMBLER__ */
|
#endif /* __ASSEMBLER__ */
|
||||||
|
|
||||||
#endif /* tls.h */
|
#endif /* tls.h */
|
||||||
|
@ -65,11 +65,11 @@ typedef union dtv
|
|||||||
/* Get the thread descriptor definition. */
|
/* Get the thread descriptor definition. */
|
||||||
# include <nptl/descr.h>
|
# include <nptl/descr.h>
|
||||||
|
|
||||||
/* This layout is actually wholly private and not affected by the ABI.
|
/* The stack_guard is accessed directly by GCC -fstack-protector code,
|
||||||
Nor does it overlap the pthread data structure, so we need nothing
|
so it is a part of public ABI. The dtv field is private. */
|
||||||
extra here at all. */
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
uintptr_t stack_guard;
|
||||||
dtv_t *dtv;
|
dtv_t *dtv;
|
||||||
} tcbhead_t;
|
} tcbhead_t;
|
||||||
|
|
||||||
@ -127,7 +127,7 @@ register void *__thread_register __asm__ ("r13");
|
|||||||
|
|
||||||
/* Return the address of the dtv for the current thread. */
|
/* Return the address of the dtv for the current thread. */
|
||||||
# define THREAD_DTV() \
|
# define THREAD_DTV() \
|
||||||
(((tcbhead_t *) (__thread_register - TLS_TCB_OFFSET))[-1].dtv)
|
(((tcbhead_t *) (__thread_register - TLS_TCB_OFFSET))[-1].dtv)
|
||||||
|
|
||||||
/* Return the thread descriptor for the current thread. */
|
/* Return the thread descriptor for the current thread. */
|
||||||
# define THREAD_SELF \
|
# define THREAD_SELF \
|
||||||
@ -136,9 +136,9 @@ register void *__thread_register __asm__ ("r13");
|
|||||||
|
|
||||||
/* Magic for libthread_db to know how to do THREAD_SELF. */
|
/* Magic for libthread_db to know how to do THREAD_SELF. */
|
||||||
# define DB_THREAD_SELF \
|
# define DB_THREAD_SELF \
|
||||||
REGISTER (32, 32, PT_THREAD_POINTER * 4, \
|
REGISTER (32, 32, PT_THREAD_POINTER * 4, \
|
||||||
- TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) \
|
- TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) \
|
||||||
REGISTER (64, 64, PT_THREAD_POINTER * 8, \
|
REGISTER (64, 64, PT_THREAD_POINTER * 8, \
|
||||||
- TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)
|
- TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)
|
||||||
|
|
||||||
/* Read member of the thread descriptor directly. */
|
/* Read member of the thread descriptor directly. */
|
||||||
@ -156,6 +156,16 @@ register void *__thread_register __asm__ ("r13");
|
|||||||
# define THREAD_SETMEM_NC(descr, member, idx, value) \
|
# define THREAD_SETMEM_NC(descr, member, idx, value) \
|
||||||
((void)(descr), (THREAD_SELF)->member[idx] = (value))
|
((void)(descr), (THREAD_SELF)->member[idx] = (value))
|
||||||
|
|
||||||
|
/* Set the stack guard field in TCB head. */
|
||||||
|
# define THREAD_SET_STACK_GUARD(value) \
|
||||||
|
(((tcbhead_t *) ((char *) __thread_register \
|
||||||
|
- TLS_TCB_OFFSET))[-1].stack_guard = (value))
|
||||||
|
# define THREAD_COPY_STACK_GUARD(descr) \
|
||||||
|
(((tcbhead_t *) ((char *) (descr) \
|
||||||
|
+ TLS_PRE_TCB_SIZE))[-1].stack_guard \
|
||||||
|
= ((tcbhead_t *) ((char *) __thread_register \
|
||||||
|
- TLS_TCB_OFFSET))[-1].stack_guard)
|
||||||
|
|
||||||
/* l_tls_offset == 0 is perfectly valid on PPC, so we have to use some
|
/* l_tls_offset == 0 is perfectly valid on PPC, so we have to use some
|
||||||
different value to mean unset l_tls_offset. */
|
different value to mean unset l_tls_offset. */
|
||||||
# define NO_TLS_OFFSET -1
|
# define NO_TLS_OFFSET -1
|
||||||
|
@ -48,9 +48,8 @@ typedef struct
|
|||||||
dtv_t *dtv;
|
dtv_t *dtv;
|
||||||
void *self; /* Pointer to the thread descriptor. */
|
void *self; /* Pointer to the thread descriptor. */
|
||||||
int multiple_threads;
|
int multiple_threads;
|
||||||
# ifdef NEED_DL_SYSINFO
|
|
||||||
uintptr_t sysinfo;
|
uintptr_t sysinfo;
|
||||||
# endif
|
uintptr_t stack_guard;
|
||||||
} tcbhead_t;
|
} tcbhead_t;
|
||||||
|
|
||||||
# ifndef __s390x__
|
# ifndef __s390x__
|
||||||
@ -158,6 +157,13 @@ typedef struct
|
|||||||
#define THREAD_SETMEM_NC(descr, member, idx, value) \
|
#define THREAD_SETMEM_NC(descr, member, idx, value) \
|
||||||
descr->member[idx] = (value)
|
descr->member[idx] = (value)
|
||||||
|
|
||||||
|
/* Set the stack guard field in TCB head. */
|
||||||
|
#define THREAD_SET_STACK_GUARD(value) \
|
||||||
|
THREAD_SETMEM (THREAD_SELF, header.stack_guard, value)
|
||||||
|
#define THREAD_COPY_STACK_GUARD(descr) \
|
||||||
|
((descr)->header.stack_guard \
|
||||||
|
= THREAD_GETMEM (THREAD_SELF, header.stack_guard))
|
||||||
|
|
||||||
#endif /* __ASSEMBLER__ */
|
#endif /* __ASSEMBLER__ */
|
||||||
|
|
||||||
#endif /* tls.h */
|
#endif /* tls.h */
|
||||||
|
@ -46,6 +46,8 @@ typedef struct
|
|||||||
dtv_t *dtv;
|
dtv_t *dtv;
|
||||||
void *self;
|
void *self;
|
||||||
int multiple_threads;
|
int multiple_threads;
|
||||||
|
uintptr_t sysinfo;
|
||||||
|
uintptr_t stack_guard;
|
||||||
} tcbhead_t;
|
} tcbhead_t;
|
||||||
|
|
||||||
#else /* __ASSEMBLER__ */
|
#else /* __ASSEMBLER__ */
|
||||||
@ -126,6 +128,13 @@ register struct pthread *__thread_self __asm__("%g7");
|
|||||||
#define THREAD_SETMEM_NC(descr, member, idx, value) \
|
#define THREAD_SETMEM_NC(descr, member, idx, value) \
|
||||||
descr->member[idx] = (value)
|
descr->member[idx] = (value)
|
||||||
|
|
||||||
|
/* Set the stack guard field in TCB head. */
|
||||||
|
#define THREAD_SET_STACK_GUARD(value) \
|
||||||
|
THREAD_SETMEM (THREAD_SELF, header.stack_guard, value)
|
||||||
|
# define THREAD_COPY_STACK_GUARD(descr) \
|
||||||
|
((descr)->header.stack_guard \
|
||||||
|
= THREAD_GETMEM (THREAD_SELF, header.stack_guard))
|
||||||
|
|
||||||
#endif /* !ASSEMBLER */
|
#endif /* !ASSEMBLER */
|
||||||
|
|
||||||
#endif /* tls.h */
|
#endif /* tls.h */
|
||||||
|
@ -47,6 +47,8 @@ typedef struct
|
|||||||
dtv_t *dtv;
|
dtv_t *dtv;
|
||||||
void *self; /* Pointer to the thread descriptor. */
|
void *self; /* Pointer to the thread descriptor. */
|
||||||
int multiple_threads;
|
int multiple_threads;
|
||||||
|
uintptr_t sysinfo;
|
||||||
|
uintptr_t stack_guard;
|
||||||
} tcbhead_t;
|
} tcbhead_t;
|
||||||
|
|
||||||
#else /* __ASSEMBLER__ */
|
#else /* __ASSEMBLER__ */
|
||||||
@ -320,6 +322,13 @@ typedef struct
|
|||||||
__res; })
|
__res; })
|
||||||
|
|
||||||
|
|
||||||
|
/* Set the stack guard field in TCB head. */
|
||||||
|
# define THREAD_SET_STACK_GUARD(value) \
|
||||||
|
THREAD_SETMEM (THREAD_SELF, header.stack_guard, value)
|
||||||
|
# define THREAD_COPY_STACK_GUARD(descr) \
|
||||||
|
((descr)->header.stack_guard \
|
||||||
|
= THREAD_GETMEM (THREAD_SELF, header.stack_guard))
|
||||||
|
|
||||||
#endif /* __ASSEMBLER__ */
|
#endif /* __ASSEMBLER__ */
|
||||||
|
|
||||||
#endif /* tls.h */
|
#endif /* tls.h */
|
||||||
|
1
nptl/tst-stackguard1-static.c
Normal file
1
nptl/tst-stackguard1-static.c
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "tst-stackguard1.c"
|
226
nptl/tst-stackguard1.c
Normal file
226
nptl/tst-stackguard1.c
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
/* 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 <pthread.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <elf/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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
uintptr_t_cmp (const void *a, const void *b)
|
||||||
|
{
|
||||||
|
if (*(uintptr_t *) a < *(uintptr_t *) b)
|
||||||
|
return 1;
|
||||||
|
if (*(uintptr_t *) a > *(uintptr_t *) b)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
tf (void *arg)
|
||||||
|
{
|
||||||
|
if (stack_chk_guard_copy != STACK_CHK_GUARD)
|
||||||
|
{
|
||||||
|
puts ("STACK_CHK_GUARD changed in thread");
|
||||||
|
return (void *) 1L;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_test (void)
|
||||||
|
{
|
||||||
|
if (!stack_chk_guard_copy_set)
|
||||||
|
{
|
||||||
|
puts ("constructor has not been run");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stack_chk_guard_copy != STACK_CHK_GUARD)
|
||||||
|
{
|
||||||
|
puts ("STACK_CHK_GUARD changed between constructor and do_test");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (child)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
pthread_t th[4];
|
||||||
|
void *ret;
|
||||||
|
for (i = 0; i < 4; ++i)
|
||||||
|
if (pthread_create (&th[i], NULL, tf, NULL))
|
||||||
|
{
|
||||||
|
puts ("thread creation failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
for (i = 0; i < 4; ++i)
|
||||||
|
if (pthread_join (th[i], &ret))
|
||||||
|
{
|
||||||
|
puts ("thread join failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (ret != NULL)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
write (2, &stack_chk_guard_copy, sizeof (stack_chk_guard_copy));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command == NULL)
|
||||||
|
{
|
||||||
|
puts ("missing --command or --child argument");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define N 16
|
||||||
|
uintptr_t child_stack_chk_guards[N + 1];
|
||||||
|
child_stack_chk_guards[N] = stack_chk_guard_copy;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < N; ++i)
|
||||||
|
{
|
||||||
|
if (pipe (fds) < 0)
|
||||||
|
{
|
||||||
|
printf ("couldn't create pipe: %m\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid_t pid = fork ();
|
||||||
|
if (pid < 0)
|
||||||
|
{
|
||||||
|
printf ("fork failed: %m\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pid)
|
||||||
|
{
|
||||||
|
if (stack_chk_guard_copy != STACK_CHK_GUARD)
|
||||||
|
{
|
||||||
|
puts ("STACK_CHK_GUARD changed after fork");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
close (fds[0]);
|
||||||
|
close (2);
|
||||||
|
dup2 (fds[1], 2);
|
||||||
|
close (fds[1]);
|
||||||
|
|
||||||
|
system (command);
|
||||||
|
exit (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
close (fds[1]);
|
||||||
|
|
||||||
|
if (TEMP_FAILURE_RETRY (read (fds[0], &child_stack_chk_guards[i],
|
||||||
|
sizeof (uintptr_t))) != sizeof (uintptr_t))
|
||||||
|
{
|
||||||
|
puts ("could not read stack_chk_guard value from child");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
close (fds[0]);
|
||||||
|
|
||||||
|
pid_t termpid;
|
||||||
|
int status;
|
||||||
|
termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
|
||||||
|
if (termpid == -1)
|
||||||
|
{
|
||||||
|
printf ("waitpid failed: %m\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (termpid != pid)
|
||||||
|
{
|
||||||
|
printf ("waitpid returned %ld != %ld\n",
|
||||||
|
(long int) termpid, (long int) pid);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (!WIFEXITED (status) || WEXITSTATUS (status))
|
||||||
|
{
|
||||||
|
puts ("child hasn't exited with exit status 0");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qsort (child_stack_chk_guards, N + 1, sizeof (uintptr_t), uintptr_t_cmp);
|
||||||
|
|
||||||
|
uintptr_t default_guard = 0;
|
||||||
|
unsigned char *p = (unsigned char *) &default_guard;
|
||||||
|
p[sizeof (uintptr_t) - 1] = 255;
|
||||||
|
p[sizeof (uintptr_t) - 2] = '\n';
|
||||||
|
p[0] = 0;
|
||||||
|
|
||||||
|
/* Test if the stack guard canaries are either randomized,
|
||||||
|
or equal to the default stack guard canary value.
|
||||||
|
Even with randomized stack guards it might happen
|
||||||
|
that the random number generator generates the same
|
||||||
|
values, but if that happens in more than half from
|
||||||
|
the 16 runs, something is very wrong. */
|
||||||
|
int ndifferences = 0;
|
||||||
|
int ndefaults = 0;
|
||||||
|
for (i = 0; i < N; ++i)
|
||||||
|
{
|
||||||
|
if (child_stack_chk_guards[i] != child_stack_chk_guards[i+1])
|
||||||
|
ndifferences++;
|
||||||
|
else if (child_stack_chk_guards[i] == default_guard)
|
||||||
|
ndefaults++;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf ("differences %d defaults %d\n", ndifferences, ndefaults);
|
||||||
|
|
||||||
|
if (ndifferences < N / 2 && ndefaults < N / 2)
|
||||||
|
{
|
||||||
|
puts ("stack guard canaries are not randomized enough");
|
||||||
|
puts ("nor equal to the default canary value");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define OPT_COMMAND 10000
|
||||||
|
#define OPT_CHILD 10001
|
||||||
|
#define CMDLINE_OPTIONS \
|
||||||
|
{ "command", required_argument, NULL, OPT_COMMAND }, \
|
||||||
|
{ "child", no_argument, NULL, OPT_CHILD },
|
||||||
|
#define CMDLINE_PROCESS \
|
||||||
|
case OPT_COMMAND: \
|
||||||
|
command = optarg; \
|
||||||
|
break; \
|
||||||
|
case OPT_CHILD: \
|
||||||
|
child = true; \
|
||||||
|
break;
|
||||||
|
#define TEST_FUNCTION do_test ()
|
||||||
|
#include "../test-skeleton.c"
|
@ -1 +1,12 @@
|
|||||||
/* Nothing needed in general. */
|
#include <stdint.h>
|
||||||
|
|
||||||
|
static inline uintptr_t __attribute__ ((always_inline))
|
||||||
|
_dl_setup_stack_chk_guard (void)
|
||||||
|
{
|
||||||
|
uintptr_t ret = 0;
|
||||||
|
unsigned char *p = (unsigned char *) &ret;
|
||||||
|
p[sizeof (ret) - 1] = 255;
|
||||||
|
p[sizeof (ret) - 2] = '\n';
|
||||||
|
p[0] = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@ -35,6 +35,11 @@ extern void __pthread_initialize_minimal (void)
|
|||||||
__attribute__ ((weak))
|
__attribute__ ((weak))
|
||||||
# endif
|
# endif
|
||||||
;
|
;
|
||||||
|
# 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
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_PTR_NTHREADS
|
#ifdef HAVE_PTR_NTHREADS
|
||||||
@ -152,6 +157,16 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
|
|||||||
__pthread_initialize_minimal ();
|
__pthread_initialize_minimal ();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
# ifndef SHARED
|
||||||
|
/* 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
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Register the destructor of the dynamic linker if there is any. */
|
/* Register the destructor of the dynamic linker if there is any. */
|
||||||
if (__builtin_expect (rtld_fini != NULL, 1))
|
if (__builtin_expect (rtld_fini != NULL, 1))
|
||||||
__cxa_atexit ((void (*) (void *)) rtld_fini, NULL, NULL);
|
__cxa_atexit ((void (*) (void *)) rtld_fini, NULL, NULL);
|
||||||
|
@ -133,17 +133,6 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TLS_INIT_TP_EXPENSIVE
|
|
||||||
if (memsz == 0 && tcbsize <= TLS_INIT_TCB_SIZE)
|
|
||||||
{
|
|
||||||
/* We do not need a TLS block and no thread descriptor. */
|
|
||||||
# ifdef NONTLS_INIT_TP
|
|
||||||
NONTLS_INIT_TP;
|
|
||||||
# endif
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* We have to set up the TCB block which also (possibly) contains
|
/* We have to set up the TCB block which also (possibly) contains
|
||||||
'errno'. Therefore we avoid 'malloc' which might touch 'errno'.
|
'errno'. Therefore we avoid 'malloc' which might touch 'errno'.
|
||||||
Instead we use 'sbrk' which would only uses 'errno' if it fails.
|
Instead we use 'sbrk' which would only uses 'errno' if it fails.
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
#include "kernel-features.h"
|
#include "kernel-features.h"
|
||||||
#include <dl-sysdep.h>
|
#include <dl-sysdep.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifndef MIN
|
#ifndef MIN
|
||||||
# define MIN(a,b) (((a)<(b))?(a):(b))
|
# define MIN(a,b) (((a)<(b))?(a):(b))
|
||||||
@ -157,3 +158,24 @@ _dl_discover_osversion (void)
|
|||||||
else if (__LINUX_KERNEL_VERSION > 0) \
|
else if (__LINUX_KERNEL_VERSION > 0) \
|
||||||
FATAL ("FATAL: cannot determine kernel version\n"); \
|
FATAL ("FATAL: cannot determine kernel version\n"); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
static inline uintptr_t __attribute__ ((always_inline))
|
||||||
|
_dl_setup_stack_chk_guard (void)
|
||||||
|
{
|
||||||
|
uintptr_t ret;
|
||||||
|
#ifdef ENABLE_STACKGUARD_RANDOMIZE
|
||||||
|
int fd = __open ("/dev/urandom", O_RDONLY);
|
||||||
|
if (fd >= 0)
|
||||||
|
{
|
||||||
|
ssize_t reslen = __read (fd, &ret, sizeof (ret));
|
||||||
|
__close (fd);
|
||||||
|
if (reslen == (ssize_t) sizeof (ret))
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
ret = 0;
|
||||||
|
unsigned char *p = (unsigned char *) &ret;
|
||||||
|
p[sizeof (ret) - 1] = 255;
|
||||||
|
p[sizeof (ret) - 2] = '\n';
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user