From 62f3121a3d209fb4f826988d53b1aac93842502c Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Thu, 15 Mar 2012 10:02:30 +0000 Subject: [PATCH 1/5] fix for bug #5210: enable GCC and LD hardening by default --- changes/bug5210 | 2 ++ configure.in | 12 ++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 changes/bug5210 diff --git a/changes/bug5210 b/changes/bug5210 new file mode 100644 index 0000000000..b07e7f1f23 --- /dev/null +++ b/changes/bug5210 @@ -0,0 +1,2 @@ + o Security fixes: + - Enable gcc and ld hardening by default. Fixes bug 5210. diff --git a/configure.in b/configure.in index 7415ce8312..4a3ed0e6c3 100644 --- a/configure.in +++ b/configure.in @@ -122,19 +122,23 @@ dnl -D_FORTIFY_SOURCE=2 -fstack-protector-all dnl Others suggest '/gs /safeseh /nxcompat /dynamicbase' for non-gcc on Windows dnl This requires that we use gcc and that we add -O2 to the CFLAGS. AC_ARG_ENABLE(gcc-hardening, - AS_HELP_STRING(--enable-gcc-hardening, enable compiler security checks), + AS_HELP_STRING(--disable-gcc-hardening, disable compiler security checks), + [], + [enableval=yes;]) [if test x$enableval = xyes; then CFLAGS="$CFLAGS -D_FORTIFY_SOURCE=2 -fstack-protector-all" CFLAGS="$CFLAGS -fwrapv -fPIE -Wstack-protector" CFLAGS="$CFLAGS --param ssp-buffer-size=1" LDFLAGS="$LDFLAGS -pie" -fi]) +fi] dnl Linker hardening options dnl Currently these options are ELF specific - you can't use this with MacOSX AC_ARG_ENABLE(linker-hardening, - AS_HELP_STRING(--enable-linker-hardening, enable linker security fixups), -[if test x$enableval = xyes; then + AS_HELP_STRING(--disable-linker-hardening, disable linker security fixups), + [], + [enableval=yes;]) +AC_CHECK_HEADER([elf.h], [if test x$enableval = xyes; then LDFLAGS="$LDFLAGS -z relro -z now" fi]) From e36cd016337f26188f572e0bd511a4f8b72c07dc Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 11 May 2012 15:08:16 -0400 Subject: [PATCH 2/5] Try to manually test for whether the compiler hardening flags work Also, make the check for whether they're on by default work; there's no need to mess around with this "$enableval" silliness. --- acinclude.m4 | 34 ++++++++++++++++++++++++++++++++++ configure.in | 31 ++++++++++++++++--------------- 2 files changed, 50 insertions(+), 15 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index ccfecff28d..c482e37546 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -41,6 +41,40 @@ AC_DEFUN([TOR_DEFINE_CODEPATH], AC_SUBST(TOR_LDFLAGS_$2) ]) +dnl 1:flags +AC_DEFUN([TOR_CHECK_CFLAGS], [ + AS_VAR_PUSHDEF([VAR],[tor_cv_cflags_$1]) + AC_CACHE_CHECK([whether the compiler accepts $1], VAR, [ + tor_saved_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $1" + AC_TRY_COMPILE([], [return 0;], + [AS_VAR_SET(VAR,yes)], + [AS_VAR_SET(VAR,no)]) + CFLAGS="$tor_saved_CFLAGS" + ]) + if test x$VAR = xyes; then + CFLAGS="$CFLAGS $1" + fi + AS_VAR_POPDEF([VAR]) +]) + +dnl 1:flags +AC_DEFUN([TOR_CHECK_LDFLAGS], [ + AS_VAR_PUSHDEF([VAR],[tor_cv_ldflags_$1]) + AC_CACHE_CHECK([whether the linker accepts $1], VAR, [ + tor_saved_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $1" + AC_TRY_LINK([], [return 0;], + [AS_VAR_SET(VAR,yes)], + [AS_VAR_SET(VAR,no)]) + LDFLAGS="$tor_saved_LDFLAGS" + ]) + if test x$VAR = xyes; then + LDFLAGS="$LDFLAGS $1" + fi + AS_VAR_POPDEF([VAR]) +]) + dnl 1:libname AC_DEFUN([TOR_WARN_MISSING_LIB], [ h="" diff --git a/configure.in b/configure.in index 4a3ed0e6c3..d894c73df8 100644 --- a/configure.in +++ b/configure.in @@ -122,25 +122,12 @@ dnl -D_FORTIFY_SOURCE=2 -fstack-protector-all dnl Others suggest '/gs /safeseh /nxcompat /dynamicbase' for non-gcc on Windows dnl This requires that we use gcc and that we add -O2 to the CFLAGS. AC_ARG_ENABLE(gcc-hardening, - AS_HELP_STRING(--disable-gcc-hardening, disable compiler security checks), - [], - [enableval=yes;]) -[if test x$enableval = xyes; then - CFLAGS="$CFLAGS -D_FORTIFY_SOURCE=2 -fstack-protector-all" - CFLAGS="$CFLAGS -fwrapv -fPIE -Wstack-protector" - CFLAGS="$CFLAGS --param ssp-buffer-size=1" - LDFLAGS="$LDFLAGS -pie" -fi] + AS_HELP_STRING(--disable-gcc-hardening, disable compiler security checks)) dnl Linker hardening options dnl Currently these options are ELF specific - you can't use this with MacOSX AC_ARG_ENABLE(linker-hardening, - AS_HELP_STRING(--disable-linker-hardening, disable linker security fixups), - [], - [enableval=yes;]) -AC_CHECK_HEADER([elf.h], [if test x$enableval = xyes; then - LDFLAGS="$LDFLAGS -z relro -z now" -fi]) + AS_HELP_STRING(--disable-linker-hardening, disable linker security fixups)) AC_ARG_ENABLE(local-appdata, AS_HELP_STRING(--enable-local-appdata, default to host local application data paths on Windows)) @@ -184,6 +171,20 @@ AM_CONDITIONAL(NAT_PMP, test x$natpmp = xtrue) AM_CONDITIONAL(MINIUPNPC, test x$upnp = xtrue) AM_PROG_CC_C_O +if test x$enable_gcc_hardening != xno; then + CFLAGS="$CFLAGS -D_FORTIFY_SOURCE=2" + TOR_CHECK_CFLAGS(-fstack-protector-all) + TOR_CHECK_CFLAGS(-Wstack-protector) + TOR_CHECK_CFLAGS(-fwrapv) + TOR_CHECK_CFLAGS(-fPIE) + TOR_CHECK_CFLAGS(--param ssp-buffer-size=1) + TOR_CHECK_LDFLAGS(-pie) +fi + +if test x$enable_linker_hardening != xno; then + TOR_CHECK_LDFLAGS(-z relro -z now) +fi + ifdef([AC_C_FLEXIBLE_ARRAY_MEMBER], [ AC_C_FLEXIBLE_ARRAY_MEMBER ], [ From e6dbe693b7fd90a495b98ec790205ff4ac56fea9 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 11 May 2012 15:52:36 -0400 Subject: [PATCH 3/5] Make the option-checker code work with osx clang This is a matter of making gcc and friends squirm more loudly when they get an option they don't like (-pedantic) and making clang shut up with it gets an option it tolerates but doesnt know (-Qunknown-argument). Is there no better way? --- acinclude.m4 | 4 ++-- configure.in | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index c482e37546..c5037fa35d 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -46,7 +46,7 @@ AC_DEFUN([TOR_CHECK_CFLAGS], [ AS_VAR_PUSHDEF([VAR],[tor_cv_cflags_$1]) AC_CACHE_CHECK([whether the compiler accepts $1], VAR, [ tor_saved_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $1" + CFLAGS="$CFLAGS -pedantic $1" AC_TRY_COMPILE([], [return 0;], [AS_VAR_SET(VAR,yes)], [AS_VAR_SET(VAR,no)]) @@ -63,7 +63,7 @@ AC_DEFUN([TOR_CHECK_LDFLAGS], [ AS_VAR_PUSHDEF([VAR],[tor_cv_ldflags_$1]) AC_CACHE_CHECK([whether the linker accepts $1], VAR, [ tor_saved_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $1" + LDFLAGS="$LDFLAGS -pedantic $1" AC_TRY_LINK([], [return 0;], [AS_VAR_SET(VAR,yes)], [AS_VAR_SET(VAR,no)]) diff --git a/configure.in b/configure.in index d894c73df8..3e645753ee 100644 --- a/configure.in +++ b/configure.in @@ -173,6 +173,7 @@ AM_PROG_CC_C_O if test x$enable_gcc_hardening != xno; then CFLAGS="$CFLAGS -D_FORTIFY_SOURCE=2" + TOR_CHECK_CFLAGS(-Qunused-arguments) TOR_CHECK_CFLAGS(-fstack-protector-all) TOR_CHECK_CFLAGS(-Wstack-protector) TOR_CHECK_CFLAGS(-fwrapv) From ebaaa4834f803015e68d348f330fcef88de34a92 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 11 Jun 2012 11:00:48 -0400 Subject: [PATCH 4/5] Make our compiler-hardening checks robust against MinGW First, specify -Werror when we are testing each option; if it causes a warning to appear, we shouldn't be adding it. Second, do not attempt to add these options until after we have found the libraries we want. Previously, I would hit a bug where the linker hardening options worked fine when we weren't linking anything, but failed completely once we added openssl or libevent. --- acinclude.m4 | 12 ++++++++++-- configure.in | 39 +++++++++++++++++++++++---------------- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index c5037fa35d..5e09c960fe 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -46,7 +46,7 @@ AC_DEFUN([TOR_CHECK_CFLAGS], [ AS_VAR_PUSHDEF([VAR],[tor_cv_cflags_$1]) AC_CACHE_CHECK([whether the compiler accepts $1], VAR, [ tor_saved_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -pedantic $1" + CFLAGS="$CFLAGS -pedantic -Werror $1" AC_TRY_COMPILE([], [return 0;], [AS_VAR_SET(VAR,yes)], [AS_VAR_SET(VAR,no)]) @@ -59,15 +59,23 @@ AC_DEFUN([TOR_CHECK_CFLAGS], [ ]) dnl 1:flags +dnl 2:extra ldflags +dnl 3:extra libraries AC_DEFUN([TOR_CHECK_LDFLAGS], [ AS_VAR_PUSHDEF([VAR],[tor_cv_ldflags_$1]) AC_CACHE_CHECK([whether the linker accepts $1], VAR, [ + tor_saved_CFLAGS="$CFLAGS" tor_saved_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS -pedantic $1" + tor_saved_LIBS="$LIBS" + CFLAGS="$CFLAGS -pedantic -Werror" + LDFLAGS="$LDFLAGS $2 $1" + LIBS="$LIBS $3" AC_TRY_LINK([], [return 0;], [AS_VAR_SET(VAR,yes)], [AS_VAR_SET(VAR,no)]) + CFLAGS="$tor_saved_CFLAGS" LDFLAGS="$tor_saved_LDFLAGS" + LIBS="$tor_saved_LIBS" ]) if test x$VAR = xyes; then LDFLAGS="$LDFLAGS $1" diff --git a/configure.in b/configure.in index 3e645753ee..7167ca9366 100644 --- a/configure.in +++ b/configure.in @@ -171,21 +171,6 @@ AM_CONDITIONAL(NAT_PMP, test x$natpmp = xtrue) AM_CONDITIONAL(MINIUPNPC, test x$upnp = xtrue) AM_PROG_CC_C_O -if test x$enable_gcc_hardening != xno; then - CFLAGS="$CFLAGS -D_FORTIFY_SOURCE=2" - TOR_CHECK_CFLAGS(-Qunused-arguments) - TOR_CHECK_CFLAGS(-fstack-protector-all) - TOR_CHECK_CFLAGS(-Wstack-protector) - TOR_CHECK_CFLAGS(-fwrapv) - TOR_CHECK_CFLAGS(-fPIE) - TOR_CHECK_CFLAGS(--param ssp-buffer-size=1) - TOR_CHECK_LDFLAGS(-pie) -fi - -if test x$enable_linker_hardening != xno; then - TOR_CHECK_LDFLAGS(-z relro -z now) -fi - ifdef([AC_C_FLEXIBLE_ARRAY_MEMBER], [ AC_C_FLEXIBLE_ARRAY_MEMBER ], [ @@ -566,8 +551,29 @@ else fi AC_SUBST(TOR_ZLIB_LIBS) -dnl Make sure to enable support for large off_t if available. +dnl --------------------------------------------------------------------- +dnl Now that we know about our major libraries, we can check for compiler +dnl and linker hardening options. We need to do this with the libraries known, +dnl since sometimes the linker will like an option but not be willing to +dnl use it with a build of a library. +all_ldflags_for_check="$TOR_LDFLAGS_zlib $TOR_LDFLAGS_openssl $TOR_LDFLAGS_libevent" +all_libs_for_check="$TOR_ZLIB_LIBS $TOR_LIB_MATH $TOR_LIBEVENT_LIBS $TOR_OPENSSL_LIBS $TOR_LIB_WS32 $TOR_LIB_GDI" + +if test x$enable_gcc_hardening != xno; then + CFLAGS="$CFLAGS -D_FORTIFY_SOURCE=2" + TOR_CHECK_CFLAGS(-Qunused-arguments) + TOR_CHECK_CFLAGS(-fstack-protector-all) + TOR_CHECK_CFLAGS(-Wstack-protector) + TOR_CHECK_CFLAGS(-fwrapv) + TOR_CHECK_CFLAGS(-fPIE) + TOR_CHECK_CFLAGS(--param ssp-buffer-size=1) + TOR_CHECK_LDFLAGS(-pie, "$all_ldflags_for_check", "$all_libs_for_check") +fi + +if test x$enable_linker_hardening != xno; then + TOR_CHECK_LDFLAGS(-z relro -z now, "$all_ldflags_for_check", "$all_libs_for_check") +fi dnl ------------------------------------------------------ dnl Where do you live, libnatpmp? And how do we call you? @@ -609,6 +615,7 @@ if test "$upnp" = "true"; then [/usr/lib/]) fi +dnl Make sure to enable support for large off_t if available. AC_SYS_LARGEFILE AC_CHECK_HEADERS( From 4717951cfaa7bc97ace35b6a542495680844f407 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 11 Jun 2012 12:22:48 -0400 Subject: [PATCH 5/5] Do not try to use -pie on windows; it appears to break badly and weirdly --- configure.in | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 7167ca9366..051c924a9d 100644 --- a/configure.in +++ b/configure.in @@ -566,9 +566,11 @@ if test x$enable_gcc_hardening != xno; then TOR_CHECK_CFLAGS(-fstack-protector-all) TOR_CHECK_CFLAGS(-Wstack-protector) TOR_CHECK_CFLAGS(-fwrapv) - TOR_CHECK_CFLAGS(-fPIE) TOR_CHECK_CFLAGS(--param ssp-buffer-size=1) - TOR_CHECK_LDFLAGS(-pie, "$all_ldflags_for_check", "$all_libs_for_check") + if test "$bwin32" = "false"; then + TOR_CHECK_CFLAGS(-fPIE) + TOR_CHECK_LDFLAGS(-pie, "$all_ldflags_for_check", "$all_libs_for_check") + fi fi if test x$enable_linker_hardening != xno; then