From 03baef1c9cfb396d76cae20a00aee657871e79c4 Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Mon, 26 Dec 2016 10:08:18 +0100 Subject: Configure support for --enable-stack-protector [BZ #7065] This adds =all and =strong, with obvious semantics, defaulting to off. We don't validate the value of the option yet: that's in a later patch. Nor do we use it for anything at this stage. We differentiate between 'the compiler understands -fstack-protector' and 'the user wanted -fstack-protector' so that we can pass -fno-stack-protector in appropriate places even if the user didn't want to turn on -fstack-protector for other parts. (This helps us overcome another existing limitation, that glibc doesn't work with GCCs hacked to pass in -fstack-protector by default.) We also arrange to set the STACK_PROTECTOR_LEVEL #define to a value appropriate for the stack-protection level in use for each file in particular. --- ChangeLog | 13 +++++ INSTALL | 11 ++++ config.h.in | 6 +++ configure | 151 +++++++++++++++++++++++++++++++++++----------------- configure.ac | 70 +++++++++++++++++------- manual/install.texi | 11 ++++ 6 files changed, 193 insertions(+), 69 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0dd96f2d0f..f1b95e0e79 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2016-12-26 Nick Alcock + + [BZ #7065] + * configure.ac (libc_cv_ssp): Move up. + (libc_cv_ssp_strong): Likewise. + (libc_cv_ssp_all): New. + (stack_protector): Augment, adding -fstack-protector-all. + (no_stack_protector): New. + (STACK_PROTECTOR_LEVEL): New. + (AC_ARG_ENABLE(stack-protector)): New configure flag. + * manual/install.texi (--enable-stack-protector): Document it. + * config.h.in (STACK_PROTECTOR_LEVEL): New macro. + 2016-12-24 Carlos O'Donell * README.pretty-printers: Must specify CPPFLAGS-* also. diff --git a/INSTALL b/INSTALL index acb622a102..104f36b0bf 100644 --- a/INSTALL +++ b/INSTALL @@ -135,6 +135,17 @@ will be used, and CFLAGS sets optimization options for the compiler. '--enable-lock-elision=yes' Enable lock elision for pthread mutexes by default. +'--enable-stack-protector' +'--enable-stack-protector=strong' +'--enable-stack-protector=all' + Compile the C library and all other parts of the glibc package + (including the threading and math libraries, NSS modules, and + transliteration modules) using the GCC '-fstack-protector', + '-fstack-protector-strong' or '-fstack-protector-all' options to + detect stack overruns. Only the dynamic linker and a small number + of routines called directly from assembler are excluded from this + protection. + '--enable-pt_chown' The file 'pt_chown' is a helper binary for 'grantpt' (*note Pseudo-Terminals: Allocation.) that is installed setuid root to fix diff --git a/config.h.in b/config.h.in index 33757bd553..d96ce0f8cf 100644 --- a/config.h.in +++ b/config.h.in @@ -48,6 +48,12 @@ /* Define if compiler accepts -ftree-loop-distribute-patterns. */ #undef HAVE_CC_INHIBIT_LOOP_TO_LIBCALL +/* The level of stack protection in use for glibc as a whole. + May be overridden on a file-by-file basis. */ +#ifndef STACK_PROTECTOR_LEVEL +#undef STACK_PROTECTOR_LEVEL +#endif + /* Define if the regparm attribute shall be used for local functions (gcc on ix86 only). */ #undef USE_REGPARMS diff --git a/configure b/configure index 10b0fb7069..8c69f09232 100755 --- a/configure +++ b/configure @@ -620,7 +620,6 @@ libc_cv_cc_loop_to_function libc_cv_cc_submachine libc_cv_cc_nofma libc_cv_mtls_dialect_gnu2 -stack_protector fno_unit_at_a_time libc_cv_output_format libc_cv_has_glob_dat @@ -661,6 +660,9 @@ sysdeps_add_ons sysnames submachine multi_arch +no_stack_protector +stack_protector +libc_cv_ssp base_machine add_on_subdirs add_ons @@ -766,6 +768,7 @@ enable_lock_elision enable_add_ons enable_hidden_plt enable_bind_now +enable_stack_protector enable_static_nss enable_force_install enable_maintainer_mode @@ -1427,6 +1430,9 @@ Optional Features: for add-ons if no parameter given --disable-hidden-plt do not hide internal function calls to avoid PLT --enable-bind-now disable lazy relocations in DSOs + --enable-stack-protector=[yes|no|all|strong] + Use -fstack-protector[-all|-strong] to detect glibc + buffer overflows --enable-static-nss build static NSS modules [default=no] --disable-force-install don't force installation of files from this package, even if they are older than the installed files @@ -3427,6 +3433,18 @@ if test "x$bindnow" = xyes; then fi +# Check whether --enable-stack-protector was given. +if test "${enable_stack_protector+set}" = set; then : + enableval=$enable_stack_protector; enable_stack_protector=$enableval +else + enable_stack_protector=no +fi + +case "$enable_stack_protector" in +all|yes|no|strong) ;; +*) as_fn_error $? "Not a valid argument for --enable-stack-protector: \"$enable_stack_protector\"" "$LINENO" 5;; +esac + # Check whether --enable-static-nss was given. if test "${enable_static_nss+set}" = set; then : enableval=$enable_static_nss; static_nss=$enableval @@ -3912,6 +3930,89 @@ fi test -n "$base_machine" || base_machine=$machine +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -fstack-protector" >&5 +$as_echo_n "checking for -fstack-protector... " >&6; } +if ${libc_cv_ssp+:} false; then : + $as_echo_n "(cached) " >&6 +else + if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -Werror -fstack-protector -xc /dev/null -S -o /dev/null' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + libc_cv_ssp=yes +else + libc_cv_ssp=no +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_ssp" >&5 +$as_echo "$libc_cv_ssp" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -fstack-protector-strong" >&5 +$as_echo_n "checking for -fstack-protector-strong... " >&6; } +if ${libc_cv_ssp_strong+:} false; then : + $as_echo_n "(cached) " >&6 +else + if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -Werror -fstack-protector-strong -xc /dev/null -S -o /dev/null' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + libc_cv_ssp_strong=yes +else + libc_cv_ssp_strong=no +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_ssp_strong" >&5 +$as_echo "$libc_cv_ssp_strong" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -fstack-protector-all" >&5 +$as_echo_n "checking for -fstack-protector-all... " >&6; } +if ${libc_cv_ssp_all+:} false; then : + $as_echo_n "(cached) " >&6 +else + if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -Werror -fstack-protector-all -xc /dev/null -S -o /dev/null' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + libc_cv_ssp_all=yes +else + libc_cv_ssp_all=no +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_ssp_all" >&5 +$as_echo "$libc_cv_ssp_all" >&6; } + +stack_protector= +no_stack_protector= +if test "$libc_cv_ssp" = yes; then + no_stack_protector="-fno-stack-protector -DSTACK_PROTECTOR_LEVEL=0" +fi + +if test "$enable_stack_protector" = yes && test "$libc_cv_ssp" = yes; then + stack_protector="-fstack-protector" + $as_echo "#define STACK_PROTECTOR_LEVEL 1" >>confdefs.h + +elif test "$enable_stack_protector" = all && test "$libc_cv_ssp_all" = yes; then + stack_protector="-fstack-protector-all" + $as_echo "#define STACK_PROTECTOR_LEVEL 2" >>confdefs.h + +elif test "$enable_stack_protector" = strong && test "$libc_cv_ssp_strong" = yes; then + stack_protector="-fstack-protector-strong" + $as_echo "#define STACK_PROTECTOR_LEVEL 3" >>confdefs.h + +fi + + + + # For the multi-arch option we need support in the assembler & linker. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for assembler and linker STT_GNU_IFUNC support" >&5 $as_echo_n "checking for assembler and linker STT_GNU_IFUNC support... " >&6; } @@ -5915,54 +6016,6 @@ else fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -fstack-protector" >&5 -$as_echo_n "checking for -fstack-protector... " >&6; } -if ${libc_cv_ssp+:} false; then : - $as_echo_n "(cached) " >&6 -else - if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -Werror -fstack-protector -xc /dev/null -S -o /dev/null' - { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 - (eval $ac_try) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then : - libc_cv_ssp=yes -else - libc_cv_ssp=no -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_ssp" >&5 -$as_echo "$libc_cv_ssp" >&6; } - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -fstack-protector-strong" >&5 -$as_echo_n "checking for -fstack-protector-strong... " >&6; } -if ${libc_cv_ssp_strong+:} false; then : - $as_echo_n "(cached) " >&6 -else - if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -Werror -fstack-protector-strong -xc /dev/null -S -o /dev/null' - { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 - (eval $ac_try) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then : - libc_cv_ssp_strong=yes -else - libc_cv_ssp_strong=no -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_ssp_strong" >&5 -$as_echo "$libc_cv_ssp_strong" >&6; } - -stack_protector= -if test "$libc_cv_ssp_strong" = "yes"; then - stack_protector="-fstack-protector-strong" -elif test "$libc_cv_ssp" = "yes"; then - stack_protector="-fstack-protector" -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -mtls-dialect=gnu2" >&5 $as_echo_n "checking for -mtls-dialect=gnu2... " >&6; } if ${libc_cv_mtls_dialect_gnu2+:} false; then : diff --git a/configure.ac b/configure.ac index aa6e2d7e56..c159768984 100644 --- a/configure.ac +++ b/configure.ac @@ -235,6 +235,18 @@ if test "x$bindnow" = xyes; then AC_DEFINE(BIND_NOW) fi +dnl Build glibc with -fstack-protector, -fstack-protector-all, or +dnl -fstack-protector-strong. +AC_ARG_ENABLE([stack-protector], + AC_HELP_STRING([--enable-stack-protector=@<:@yes|no|all|strong@:>@], + [Use -fstack-protector[-all|-strong] to detect glibc buffer overflows]), + [enable_stack_protector=$enableval], + [enable_stack_protector=no]) +case "$enable_stack_protector" in +all|yes|no|strong) ;; +*) AC_MSG_ERROR([Not a valid argument for --enable-stack-protector: \"$enable_stack_protector\"]);; +esac + dnl On some platforms we cannot use dynamic loading. We must provide dnl static NSS modules. AC_ARG_ENABLE([static-nss], @@ -619,6 +631,44 @@ fi test -n "$base_machine" || base_machine=$machine AC_SUBST(base_machine) +AC_CACHE_CHECK(for -fstack-protector, libc_cv_ssp, [dnl +LIBC_TRY_CC_OPTION([$CFLAGS $CPPFLAGS -Werror -fstack-protector], + [libc_cv_ssp=yes], + [libc_cv_ssp=no]) +]) + +AC_CACHE_CHECK(for -fstack-protector-strong, libc_cv_ssp_strong, [dnl +LIBC_TRY_CC_OPTION([$CFLAGS $CPPFLAGS -Werror -fstack-protector-strong], + [libc_cv_ssp_strong=yes], + [libc_cv_ssp_strong=no]) +]) + +AC_CACHE_CHECK(for -fstack-protector-all, libc_cv_ssp_all, [dnl +LIBC_TRY_CC_OPTION([$CFLAGS $CPPFLAGS -Werror -fstack-protector-all], + [libc_cv_ssp_all=yes], + [libc_cv_ssp_all=no]) +]) + +stack_protector= +no_stack_protector= +if test "$libc_cv_ssp" = yes; then + no_stack_protector="-fno-stack-protector -DSTACK_PROTECTOR_LEVEL=0" +fi + +if test "$enable_stack_protector" = yes && test "$libc_cv_ssp" = yes; then + stack_protector="-fstack-protector" + AC_DEFINE(STACK_PROTECTOR_LEVEL, 1) +elif test "$enable_stack_protector" = all && test "$libc_cv_ssp_all" = yes; then + stack_protector="-fstack-protector-all" + AC_DEFINE(STACK_PROTECTOR_LEVEL, 2) +elif test "$enable_stack_protector" = strong && test "$libc_cv_ssp_strong" = yes; then + stack_protector="-fstack-protector-strong" + AC_DEFINE(STACK_PROTECTOR_LEVEL, 3) +fi +AC_SUBST(libc_cv_ssp) +AC_SUBST(stack_protector) +AC_SUBST(no_stack_protector) + # For the multi-arch option we need support in the assembler & linker. AC_CACHE_CHECK([for assembler and linker STT_GNU_IFUNC support], libc_cv_ld_gnu_indirect_function, [dnl @@ -1461,26 +1511,6 @@ else fi AC_SUBST(fno_unit_at_a_time) -AC_CACHE_CHECK(for -fstack-protector, libc_cv_ssp, [dnl -LIBC_TRY_CC_OPTION([$CFLAGS $CPPFLAGS -Werror -fstack-protector], - [libc_cv_ssp=yes], - [libc_cv_ssp=no]) -]) - -AC_CACHE_CHECK(for -fstack-protector-strong, libc_cv_ssp_strong, [dnl -LIBC_TRY_CC_OPTION([$CFLAGS $CPPFLAGS -Werror -fstack-protector-strong], - [libc_cv_ssp_strong=yes], - [libc_cv_ssp_strong=no]) -]) - -stack_protector= -if test "$libc_cv_ssp_strong" = "yes"; then - stack_protector="-fstack-protector-strong" -elif test "$libc_cv_ssp" = "yes"; then - stack_protector="-fstack-protector" -fi -AC_SUBST(stack_protector) - AC_CACHE_CHECK([for -mtls-dialect=gnu2], libc_cv_mtls_dialect_gnu2, [dnl cat > conftest.c <