2008-11-30 Nix * debug/stack_chk_fail.c: Enhanced version, from Gentoo. * debug/Makefile (CFLAGS-stack_chk_fail.c): Always dump core on stack corruption. configure-driven activation of stack protection: * configure.in (--with-stack-protector): New argument, adds -fstack-protector(-all). Error out if specified when GCC does not support it. Use -lssp when linking -nostdlib iff GCC supports it. Move the stack protection check above all such linking. * config.make.in: Propagate this flag to a variable... * Makeconfig: ... and convert it to a CFLAGS addition. * Makerules ($(common-objpfx)sysd-rules): Permit CFLAGS overrides for sysdep rules, used by rtld-Rules. Explicitly avoid stack protection for certain things, iff stack protection is supported by this GCC version. * csu/Makefile: Don't build startup files with stack protection. * libio/Makefile: Don't build code called by such files with stack protection. * misc/Makefile: Likewise, for brk and sbrk. * string/Makefile: Likewise, for C memcpy implementations. * elf/Makefile (CFLAGS-.os): Don't build rtld-specific source, or its corresponding code in static libraries, with stack protection. Don't build filter modules with stack protection. * elf/rtld-Rules: Don't build rtld versions of code from the rest of glibc with stack protection. Pass custom CFLAGS down. * stdlib/Makefile: Don't build tests not linked against libc with stack protection. * nscd/Makefile: Build with -fstack-protector-all if requested. nptl: 2008-11-30 Nix * Makefile: Don't build startup files with stack protection. Index: libc-patched/debug/Makefile =================================================================== --- libc-patched.orig/debug/Makefile 2011-04-16 10:48:07.645343593 +0100 +++ libc-patched/debug/Makefile 2011-04-16 10:48:10.575152735 +0100 @@ -59,6 +59,7 @@ static-only-routines := warning-nop stack_chk_fail_local CFLAGS-backtrace.c = -fno-omit-frame-pointer +CFLAGS-stack_chk_fail.c = -DSSP_SMASH_DUMPS_CORE CFLAGS-sprintf_chk.c = -D_IO_MTSAFE_IO CFLAGS-snprintf_chk.c = -D_IO_MTSAFE_IO CFLAGS-vsprintf_chk.c = -D_IO_MTSAFE_IO Index: libc-patched/debug/stack_chk_fail.c =================================================================== --- libc-patched.orig/debug/stack_chk_fail.c 2011-04-16 10:48:07.645343593 +0100 +++ libc-patched/debug/stack_chk_fail.c 2011-04-16 10:48:10.575152735 +0100 @@ -1,4 +1,4 @@ -/* Copyright (C) 2005, 2007 Free Software Foundation, Inc. +/* 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 @@ -16,15 +16,297 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include +/* Copyright (C) 2006-2007 Gentoo Foundation Inc. + * License terms as above. + * + * Hardened Gentoo SSP handler + * + * An SSP failure handler that does not use functions from the rest of + * glibc; it uses the INTERNAL_SYSCALL methods directly. This ensures + * no possibility of recursion into the handler. + * + * Direct all bug reports to http://bugs.gentoo.org/ + * + * Re-written from the glibc-2.3 Hardened Gentoo SSP handler + * by Kevin F. Quinn - + * + * The following people contributed to the glibc-2.3 Hardened + * Gentoo SSP handler, from which this implementation draws much: + * + * Ned Ludd - + * Alexander Gabert - + * The PaX Team - + * Peter S. Mazinger - + * Yoann Vandoorselaere - + * Robert Connolly - + * Cory Visi + * Mike Frysinger + */ + +#include #include +#include +#include + +#include + +#include +#include +#include + +#include + +#include +/* from sysdeps */ +#include +/* for the stuff in bits/socket.h */ +#include +#include + + +/* Sanity check on SYSCALL macro names - force compilation + * failure if the names used here do not exist + */ +#if !defined __NR_socketcall && !defined __NR_socket +# error Cannot do syscall socket or socketcall +#endif +#if !defined __NR_socketcall && !defined __NR_connect +# error Cannot do syscall connect or socketcall +#endif +#ifndef __NR_write +# error Cannot do syscall write +#endif +#ifndef __NR_close +# error Cannot do syscall close +#endif +#ifndef __NR_getpid +# error Cannot do syscall getpid +#endif +#ifndef __NR_kill +# error Cannot do syscall kill +#endif +#ifndef __NR_exit +# error Cannot do syscall exit +#endif +#ifdef SSP_SMASH_DUMPS_CORE +# define ENABLE_SSP_SMASH_DUMPS_CORE 1 +# if !defined _KERNEL_NSIG && !defined _NSIG +# error No _NSIG or _KERNEL_NSIG for rt_sigaction +# endif +# if !defined __NR_sigaction && !defined __NR_rt_sigaction +# error Cannot do syscall sigaction or rt_sigaction +# endif +/* Although rt_sigaction expects sizeof(sigset_t) - it expects the size + * of the _kernel_ sigset_t which is not the same as the user sigset_t. + * Most arches have this as _NSIG bits - mips has _KERNEL_NSIG bits for + * some reason. + */ +# ifdef _KERNEL_NSIG +# define _SSP_NSIG _KERNEL_NSIG +# else +# define _SSP_NSIG _NSIG +# endif +#else +# define _SSP_NSIG 0 +# define ENABLE_SSP_SMASH_DUMPS_CORE 0 +#endif + +/* Define DO_SIGACTION - default to newer rt signal interface but + * fallback to old as needed. + */ +#ifdef __NR_rt_sigaction +# define DO_SIGACTION(signum, act, oldact) \ + INLINE_SYSCALL(rt_sigaction, 4, signum, act, oldact, _SSP_NSIG/8) +#else +# define DO_SIGACTION(signum, act, oldact) \ + INLINE_SYSCALL(sigaction, 3, signum, act, oldact) +#endif + +/* Define DO_SOCKET/DO_CONNECT functions to deal with socketcall vs socket/connect */ +#if defined(__NR_socket) && defined(__NR_connect) +# define USE_OLD_SOCKETCALL 0 +#else +# define USE_OLD_SOCKETCALL 1 +#endif +/* stub out the __NR_'s so we can let gcc optimize away dead code */ +#ifndef __NR_socketcall +# define __NR_socketcall 0 +#endif +#ifndef __NR_socket +# define __NR_socket 0 +#endif +#ifndef __NR_connect +# define __NR_connect 0 +#endif +#define DO_SOCKET(result, domain, type, protocol) \ + do { \ + if (USE_OLD_SOCKETCALL) { \ + socketargs[0] = domain; \ + socketargs[1] = type; \ + socketargs[2] = protocol; \ + socketargs[3] = 0; \ + result = INLINE_SYSCALL(socketcall, 2, SOCKOP_socket, socketargs); \ + } else \ + result = INLINE_SYSCALL(socket, 3, domain, type, protocol); \ + } while (0) +#define DO_CONNECT(result, sockfd, serv_addr, addrlen) \ + do { \ + if (USE_OLD_SOCKETCALL) { \ + socketargs[0] = sockfd; \ + socketargs[1] = (unsigned long int)serv_addr; \ + socketargs[2] = addrlen; \ + socketargs[3] = 0; \ + result = INLINE_SYSCALL(socketcall, 2, SOCKOP_connect, socketargs); \ + } else \ + result = INLINE_SYSCALL(connect, 3, sockfd, serv_addr, addrlen); \ + } while (0) + +#ifndef _PATH_LOG +# define _PATH_LOG "/dev/log" +#endif + +static const char path_log[] = _PATH_LOG; + +/* For building glibc with SSP switched on, define __progname to a + * constant if building for the run-time loader, to avoid pulling + * in more of libc.so into ld.so + */ +#ifdef IS_IN_rtld +static char *__progname = ""; +#else +extern char *__progname; +#endif + +/* Common handler code, used by stack_chk_fail and __stack_smash_handler + * Inlined to ensure no self-references to the handler within itself. + * Data static to avoid putting more than necessary on the stack, + * to aid core debugging. + * The copy in rtld must be hidden to ensure that it gets no relocations + * and thus does not crash if called during libc startup. + */ +__attribute__ ((__noreturn__ , __always_inline__)) +#ifdef IS_IN_rtld +attribute_hidden +#endif +static inline void +__hardened_gentoo_stack_chk_fail(char func[], int damaged) +{ +#define MESSAGE_BUFSIZ 256 + static pid_t pid; + static int plen, i; + static char message[MESSAGE_BUFSIZ]; + static const char msg_ssa[] = ": stack smashing attack"; + static const char msg_inf[] = " in function "; + static const char msg_ssd[] = "*** stack smashing detected ***: "; + static const char msg_terminated[] = " - terminated\n"; + static const char msg_unknown[] = ""; + static int log_socket, connect_result; + static struct sockaddr_un sock; + static unsigned long int socketargs[4]; + + /* Build socket address + */ + sock.sun_family = AF_UNIX; + i = 0; + while ((path_log[i] != '\0') && (i<(sizeof(sock.sun_path)-1))) { + sock.sun_path[i] = path_log[i]; + i++; + } + sock.sun_path[i] = '\0'; + + /* Try SOCK_DGRAM connection to syslog */ + connect_result = -1; + DO_SOCKET(log_socket, AF_UNIX, SOCK_DGRAM, 0); + if (log_socket != -1) + DO_CONNECT(connect_result, log_socket, &sock, sizeof(sock)); + if (connect_result == -1) { + if (log_socket != -1) + INLINE_SYSCALL(close, 1, log_socket); + /* Try SOCK_STREAM connection to syslog */ + DO_SOCKET(log_socket, AF_UNIX, SOCK_STREAM, 0); + if (log_socket != -1) + DO_CONNECT(connect_result, log_socket, &sock, sizeof(sock)); + } + + /* Build message. Messages are generated both in the old style and new style, + * so that log watchers that are configured for the old-style message continue + * to work. + */ +#define strconcat(str) \ + {i=0; while ((str[i] != '\0') && ((i+plen)<(MESSAGE_BUFSIZ-1))) \ + {\ + message[plen+i]=str[i];\ + i++;\ + }\ + plen+=i;} + + /* R.Henderson post-gcc-4 style message */ + plen = 0; + strconcat(msg_ssd); + if (__progname != (char *)0) + strconcat(__progname) + else + strconcat(msg_unknown); + strconcat(msg_terminated); + + /* Write out error message to STDERR, to syslog if open */ + INLINE_SYSCALL(write, 3, STDERR_FILENO, message, plen); + if (connect_result != -1) + INLINE_SYSCALL(write, 3, log_socket, message, plen); + + /* Dr. Etoh pre-gcc-4 style message */ + plen = 0; + if (__progname != (char *)0) + strconcat(__progname) + else + strconcat(msg_unknown); + strconcat(msg_ssa); + strconcat(msg_inf); + if (func != NULL) + strconcat(func) + else + strconcat(msg_unknown); + strconcat(msg_terminated); + /* Write out error message to STDERR, to syslog if open */ + INLINE_SYSCALL(write, 3, STDERR_FILENO, message, plen); + if (connect_result != -1) + INLINE_SYSCALL(write, 3, log_socket, message, plen); -extern char **__libc_argv attribute_hidden; + /* Write out error message to STDERR, to syslog if open */ + INLINE_SYSCALL(write, 3, STDERR_FILENO, message, plen); + if (connect_result != -1) + INLINE_SYSCALL(write, 3, log_socket, message, plen); + + if (log_socket != -1) + INLINE_SYSCALL(close, 1, log_socket); + + /* Suicide */ + pid = INLINE_SYSCALL(getpid, 0); + + if (ENABLE_SSP_SMASH_DUMPS_CORE) { + static struct sigaction default_abort_act; + /* Remove any user-supplied handler for SIGABRT, before using it */ + default_abort_act.sa_handler = SIG_DFL; + default_abort_act.sa_sigaction = NULL; + __sigfillset(&default_abort_act.sa_mask); + default_abort_act.sa_flags = 0; + if (DO_SIGACTION(SIGABRT, &default_abort_act, NULL) == 0) + INLINE_SYSCALL(kill, 2, pid, SIGABRT); + } + + /* Note; actions cannot be added to SIGKILL */ + INLINE_SYSCALL(kill, 2, pid, SIGKILL); + + /* In case the kill didn't work, exit anyway + * The loop prevents gcc thinking this routine returns + */ + while (1) + INLINE_SYSCALL(exit, 0); +} -void -__attribute__ ((noreturn)) -__stack_chk_fail (void) +__attribute__ ((__noreturn__)) +void __stack_chk_fail(void) { - __fortify_fail ("stack smashing detected"); + __hardened_gentoo_stack_chk_fail(NULL, 0); } Index: libc-patched/configure.in =================================================================== --- libc-patched.orig/configure.in 2011-04-16 10:48:07.655342942 +0100 +++ libc-patched/configure.in 2011-04-16 10:48:10.575152735 +0100 @@ -221,6 +221,19 @@ [bindnow=no]) AC_SUBST(bindnow) +dnl Build glibc with -fstack-protector, or with -fstack-protector-all. +AC_ARG_WITH([stack-protector], + AC_HELP_STRING([--with-stack-protector=@<:@yes|no|all@:>@], + [Detect stack overflows in glibc functions with large string buffers, or in all glibc functions]), + [with_stack_protector=$withval], + [with_stack_protector=no]) +case x"$with_stack_protector" in + xall|xyes|xno) ;; + *) AC_MSG_ERROR([Not a valid argument for --with-stack-protector]);; +esac +stack_protect="$with_stack_protector" +AC_SUBST(stack_protect) + dnl On some platforms we cannot use dynamic loading. We must provide dnl static NSS modules. AC_ARG_ENABLE([static-nss], @@ -1259,6 +1272,27 @@ override stddef.h = # The installed seems to be libc-friendly." fi +AC_CACHE_CHECK(for -fstack-protector, libc_cv_ssp, [dnl +if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -Werror -fstack-protector + -o /dev/null -c -x c /dev/null 1>&AS_MESSAGE_LOG_FD]) +then + libc_cv_ssp=yes + + dnl While most tests can be conducted with stack protection on, a few are + dnl incompatible with it. + no_ssp=-fno-stack-protector + libssp="-lssp_nonshared -lssp" +else + libc_cv_ssp=no + no_ssp= + libssp= + + if test x"$with_stack_protector" != xno; then + AC_MSG_ERROR([--with-stack-protector=$with_stack_protector specified, but stack protection is not supported by the compiler.]) + fi +fi]) +AC_SUBST(libc_cv_ssp) + AC_CACHE_CHECK(whether we need to use -P to assemble .S files, libc_cv_need_minus_P, [dnl cat > conftest.S <&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then + -nostartfiles -nostdlib -fno-stack-protector \ + -o conftest conftest.s conftest1.c $libssp 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then libc_cv_asm_set_directive=yes else libc_cv_asm_set_directive=no @@ -1348,7 +1382,7 @@ EOF if ${CC-cc} -c $ASFLAGS conftest.s 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then if AC_TRY_COMMAND([${CC-cc} $CFLAGS $LDFLAGS -shared - -o conftest.so conftest.o + -o conftest.so conftest.o $libssp -nostartfiles -nostdlib -Wl,--version-script,conftest.map 1>&AS_MESSAGE_LOG_FD]); @@ -1521,7 +1555,7 @@ int foo (void) { return 1; } int (*fp) (void) __attribute__ ((section (".init_array"))) = foo; EOF - if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -o conftest conftest.c + if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -o conftest conftest.c -static -nostartfiles -nostdlib 1>&AS_MESSAGE_LOG_FD]) then if readelf -S conftest | fgrep INIT_ARRAY > /dev/null; then @@ -1563,7 +1597,7 @@ EOF if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -fPIC -shared -o conftest.so conftest.c - -nostartfiles -nostdlib + -nostartfiles -nostdlib $libssp -Wl,--enable-new-dtags,-z,nodelete 1>&AS_MESSAGE_LOG_FD]) then libc_cv_z_nodelete=yes @@ -1579,7 +1613,7 @@ EOF if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -fPIC -shared -o conftest.so conftest.c - -nostartfiles -nostdlib + -nostartfiles -nostdlib $libssp -Wl,--enable-new-dtags,-z,nodlopen 1>&AS_MESSAGE_LOG_FD]) then libc_cv_z_nodlopen=yes @@ -1595,7 +1629,7 @@ EOF if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -fPIC -shared -o conftest.so conftest.c - -nostartfiles -nostdlib + -nostartfiles -nostdlib $libssp -Wl,--enable-new-dtags,-z,initfirst 1>&AS_MESSAGE_LOG_FD]) then libc_cv_z_initfirst=yes @@ -1630,7 +1664,7 @@ cat > conftest.c <&AS_MESSAGE_LOG_FD]) then @@ -1663,7 +1697,7 @@ if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -fPIC -shared -o conftest.so conftest.c -lgcc_s$libc_cv_libgcc_s_suffix -Wl,--as-needed - -nostdlib 1>&AS_MESSAGE_LOG_FD]) + -nostdlib $libssp 1>&AS_MESSAGE_LOG_FD]) then libc_cv_as_needed=yes else @@ -1703,7 +1737,7 @@ EOF if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -fPIC -shared -o conftest.so conftest.c - -nostdlib -nostartfiles + -nostdlib -nostartfiles $libssp -Wl,-z,combreloc 1>&AS_MESSAGE_LOG_FD]) then dnl The following test is a bit weak. We must use a tool which can test @@ -1732,7 +1766,7 @@ EOF if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -fPIC -shared -o conftest.so conftest.c - -Wl,-z,execstack -nostdlib + -Wl,-z,execstack -nostdlib $libssp 1>&AS_MESSAGE_LOG_FD]) then libc_cv_z_execstack=yes @@ -1756,7 +1790,7 @@ EOF if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -fPIC -shared -o conftest.so conftest.c - -Wl,--hash-style=both -nostdlib 1>&AS_MESSAGE_LOG_FD]) + -Wl,--hash-style=both -nostdlib $libssp 1>&AS_MESSAGE_LOG_FD]) then libc_cv_hashstyle=yes else @@ -1785,16 +1819,6 @@ fi AC_SUBST(fno_unit_at_a_time) -AC_CACHE_CHECK(for -fstack-protector, libc_cv_ssp, [dnl -if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS -Werror -fstack-protector - -o /dev/null -c -x c /dev/null 1>&AS_MESSAGE_LOG_FD]) -then - libc_cv_ssp=yes -else - libc_cv_ssp=no -fi]) -AC_SUBST(libc_cv_ssp) - AC_CACHE_CHECK(for -fgnu89-inline, libc_cv_gnu89_inline, [dnl cat > conftest.c <&AS_MESSAGE_LOG_FD]); then + -o conftest conftest.c $libssp 1>&AS_MESSAGE_LOG_FD]); then libc_cv_ld_no_whole_archive=yes else libc_cv_ld_no_whole_archive=no @@ -2000,7 +2024,7 @@ dnl No \ in command here because it ends up inside ''. if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostdlib -nostartfiles -fexceptions - -o conftest conftest.c 1>&AS_MESSAGE_LOG_FD]); then + -o conftest conftest.c $libssp 1>&AS_MESSAGE_LOG_FD]); then libc_cv_gcc_exceptions=yes else libc_cv_gcc_exceptions=no @@ -2035,7 +2059,7 @@ EOF dnl No \ in command here because it ends up inside ''. if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostdlib -nostartfiles - -o conftest conftest.c -lgcc >&AS_MESSAGE_LOG_FD]); then + -o conftest conftest.c -lgcc $libssp >&AS_MESSAGE_LOG_FD]); then libc_cv_gcc_builtin_expect=yes else libc_cv_gcc_builtin_expect=no Index: libc-patched/csu/Makefile =================================================================== --- libc-patched.orig/csu/Makefile 2011-04-16 10:48:09.795203544 +0100 +++ libc-patched/csu/Makefile 2011-04-16 10:48:10.575152735 +0100 @@ -53,6 +53,13 @@ include ../Makeconfig +ifeq ($(have-ssp),yes) +CFLAGS-.o += -fno-stack-protector +CFLAGS-.og += -fno-stack-protector +CFLAGS-.op += -fno-stack-protector +CFLAGS-.os += -fno-stack-protector +endif + ifeq (yes,$(build-shared)) extra-objs += S$(start-installed-name) install-lib += S$(start-installed-name) Index: libc-patched/Makerules =================================================================== --- libc-patched.orig/Makerules 2011-04-16 10:48:09.795203544 +0100 +++ libc-patched/Makerules 2011-04-16 10:48:10.575152735 +0100 @@ -252,7 +252,7 @@ while [ $$# -ge 2 ]; do \ t=$$1; shift; \ d=$$1; shift; \ - v=$${t%%%}; [ x"$$v" = x ] || v="\$$($${v}CPPFLAGS)"; \ + v=$${t%%%}; [ x"$$v" = x ] || v="\$$($${v}CPPFLAGS) \$$($${v}CFLAGS)"; \ for s in $$asm .c; do \ echo "\$$(objpfx)$$t$$o: $$dir/$$d$$s \$$(before-compile)"; \ echo " \$$(compile-command$$s) $$v"; \ Index: libc-patched/elf/rtld-Rules =================================================================== --- libc-patched.orig/elf/rtld-Rules 2011-04-16 10:48:07.655342942 +0100 +++ libc-patched/elf/rtld-Rules 2011-04-16 10:48:10.575152735 +0100 @@ -104,7 +104,7 @@ $(objpfx)rtld-%.os: %.s $(before-compile) $(compile-command.s) $(rtld-CPPFLAGS) $(objpfx)rtld-%.os: %.c $(before-compile) - $(compile-command.c) $(rtld-CPPFLAGS) + $(compile-command.c) $(rtld-CPPFLAGS) $(rtld-CFLAGS) # The rules for generated source files. $(objpfx)rtld-%.os: $(objpfx)rtld-%.S $(before-compile); $(compile-command.S) @@ -133,4 +133,8 @@ # This here is the whole point of all the shenanigans. rtld-CPPFLAGS := -DNOT_IN_libc=1 -DIS_IN_rtld=1 +ifeq ($(have-ssp),yes) +rtld-CFLAGS := -fno-stack-protector +endif + endif Index: libc-patched/elf/Makefile =================================================================== --- libc-patched.orig/elf/Makefile 2011-04-16 10:48:07.655342942 +0100 +++ libc-patched/elf/Makefile 2011-04-16 10:48:10.575152735 +0100 @@ -129,6 +129,16 @@ include ../Makeconfig +ifeq ($(have-ssp),yes) +# In the dynamic loader, some routines (which include routines called before +# the stack guard is initialized) are compiled without stack protection. +# Do the same when those routines are found in the static library. + +CFLAGS-.o += $(if $(filter $(@F),$(patsubst %,%.o,$(elide-routines.os))),-fno-stack-protector) +CFLAGS-.op += $(if $(filter $(@F),$(patsubst %,%.op,$(elide-routines.os))),-fno-stack-protector) +CFLAGS-.og += $(if $(filter $(@F),$(patsubst %,%.og,$(elide-routines.os))),-fno-stack-protector) +endif + ifeq ($(unwind-find-fde),yes) routines += unwind-dw2-fde-glibc shared-only-routines += unwind-dw2-fde-glibc @@ -476,6 +486,9 @@ CFLAGS-cache.c = $(SYSCONF-FLAGS) CPPFLAGS-.os += $(if $(filter $(@F),$(patsubst %,%.os,$(all-rtld-routines))),-DNOT_IN_libc=1 -DIS_IN_rtld=1) +ifeq ($(have-ssp),yes) +CFLAGS-.os += $(if $(filter $(@F),$(patsubst %,%.os,$(all-rtld-routines))),-fno-stack-protector) +endif test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(strip $(modules-names)))) generated += $(addsuffix .so,$(strip $(modules-names))) @@ -708,6 +721,12 @@ $< -Wl,-F,$(objpfx)filtmod2.so $(objpfx)filter: $(objpfx)filtmod1.so +ifeq ($(have-ssp),yes) +# These do not link against libc. +CFLAGS-filtmod1.c = -fno-stack-protector +CFLAGS-filtmod2.c = -fno-stack-protector +endif + $(objpfx)unload: $(libdl) $(objpfx)unload.out: $(objpfx)unloadmod.so Index: libc-patched/nptl/Makefile =================================================================== --- libc-patched.orig/nptl/Makefile 2011-04-16 10:48:07.655342942 +0100 +++ libc-patched/nptl/Makefile 2011-04-16 10:48:10.575152735 +0100 @@ -314,6 +314,11 @@ endif endif +ifeq ($(have-ssp),yes) +# Parts of nptl-init.c are called before the stack guard is initialized. +CFLAGS-nptl-init.c += -fno-stack-protector +endif + modules-names = tst-atfork2mod tst-tls3mod tst-tls4moda tst-tls4modb \ tst-tls5mod tst-tls5moda tst-tls5modb tst-tls5modc \ tst-tls5modd tst-tls5mode tst-tls5modf \ Index: libc-patched/libio/Makefile =================================================================== --- libc-patched.orig/libio/Makefile 2011-04-16 10:48:07.655342942 +0100 +++ libc-patched/libio/Makefile 2011-04-16 10:48:10.575152735 +0100 @@ -162,6 +162,12 @@ CFLAGS-oldtmpfile.c = $(exceptions) # XXX Do we need filedoalloc and wfiledoalloc? Others? +ifeq ($(have-ssp),yes) +# libc_fatal() is called in extremis, and before static initialization +# is complete: don't stack-protect it. +CFLAGS-libc_fatal.o = -fno-stack-protector +endif + CFLAGS-tst_putwc.c = -DOBJPFX=\"$(objpfx)\" tst_wprintf2-ARGS = "Some Text" Index: libc-patched/misc/Makefile =================================================================== --- libc-patched.orig/misc/Makefile 2011-04-16 10:48:07.655342942 +0100 +++ libc-patched/misc/Makefile 2011-04-16 10:48:10.575152735 +0100 @@ -112,6 +112,12 @@ CFLAGS-tst-tsearch.c = $(stack-align-test-flags) CFLAGS-mntent_r.c = -D_IO_MTSAFE_IO +ifeq ($(have-ssp),yes) +# Called during static library initialization. +CFLAGS-sbrk.c = -fno-stack-protector +CFLAGS-brk.c = -fno-stack-protector +endif + include ../Rules $(objpfx)libbsd-compat.a: $(dep-dummy-lib); $(make-dummy-lib) Index: libc-patched/string/Makefile =================================================================== --- libc-patched.orig/string/Makefile 2011-04-16 10:48:07.655342942 +0100 +++ libc-patched/string/Makefile 2011-04-16 10:48:10.575152735 +0100 @@ -84,6 +84,11 @@ CFLAGS-tst-inlcall.c = -fno-builtin CFLAGS-bug-strstr1.c = -fno-builtin +ifeq ($(have-ssp),yes) +# This is used in early initialization. +CFLAGS-memcpy.c = -fno-stack-protector +endif + # eglibc: ifeq ($(cross-compiling),no) tests: $(objpfx)tst-svc.out $(objpfx)tst-svc.out: tst-svc.input $(objpfx)tst-svc Index: libc-patched/stdlib/Makefile =================================================================== --- libc-patched.orig/stdlib/Makefile 2011-04-16 10:48:07.655342942 +0100 +++ libc-patched/stdlib/Makefile 2011-04-16 10:48:10.575152735 +0100 @@ -158,4 +158,8 @@ $(objpfx)tst-putenvmod.so: $(objpfx)tst-putenvmod.os $(build-module) +# This is not only not in libc, it's not even linked with it. CFLAGS-tst-putenvmod.c = -DNOT_IN_libc=1 +ifeq ($(have-ssp),yes) +CFLAGS-tst-putenvmod.c += -fno-stack-protector +endif Index: libc-patched/Makeconfig =================================================================== --- libc-patched.orig/Makeconfig 2011-04-16 10:48:09.795203544 +0100 +++ libc-patched/Makeconfig 2011-04-16 10:48:10.575152735 +0100 @@ -620,6 +620,13 @@ # actually different, so allow the compiler to merge them all. +merge-constants = -fmerge-all-constants +# We might want to compile with some stack-protection flag. +ifeq ($(stack-protect),yes) ++stack-protector=-fstack-protector +else ifeq ($(stack-protect),all) ++stack-protector=-fstack-protector-all +endif + # This is the program that generates makefile dependencies from C source files. # The -MP flag tells GCC >= 3.2 (which we now require) to produce dummy # targets for headers so that removed headers don't break the build. @@ -679,7 +686,7 @@ +cflags := $(default_cflags) endif # $(+cflags) == "" -+cflags += $(cflags-cpu) $(+gccwarn) $(+merge-constants) ++cflags += $(cflags-cpu) $(+gccwarn) $(+merge-constants) $(+stack-protector) +gcc-nowarn := -w # Don't duplicate options if we inherited variables from the parent. Index: libc-patched/config.make.in =================================================================== --- libc-patched.orig/config.make.in 2011-04-16 10:48:09.795203544 +0100 +++ libc-patched/config.make.in 2011-04-16 10:48:10.575152735 +0100 @@ -61,6 +61,7 @@ have-fpie = @libc_cv_fpie@ gnu89-inline-CFLAGS = @gnu89_inline@ have-ssp = @libc_cv_ssp@ +stack-protect = @stack_protect@ have-selinux = @have_selinux@ have-libaudit = @have_libaudit@ have-libcap = @have_libcap@ Index: libc-patched/nscd/Makefile =================================================================== --- libc-patched.orig/nscd/Makefile 2011-04-16 10:48:07.655342942 +0100 +++ libc-patched/nscd/Makefile 2011-04-16 10:48:10.575152735 +0100 @@ -100,7 +100,11 @@ nscd-cflags += $(pie-ccflag) endif ifeq (yes,$(have-ssp)) +ifneq (all,$(stack-protect)) nscd-cflags += -fstack-protector +else +nscd-cflags += -fstack-protector-all +endif endif CFLAGS-nscd.c += $(nscd-cflags)