[10/12] Work even with compilers hacked to enable -fstack-protector by default.

Message ID 1455963826-21885-11-git-send-email-nix@esperi.org.uk
State New, archived
Headers

Commit Message

Nix Feb. 20, 2016, 10:23 a.m. UTC
  From: Nick Alcock <nick.alcock@oracle.com>

With all the machinery we just added, we can easily arrange to work even
when the compiler passes in -fstack-protector automatically: all the
necessary bits of glibc are always compiled with -fno-stack-protector
now.

So tear out the check in configure, and add appropriate calls to
-fno-stack-protector and/or -lssp in tests that need them (largely
those that use -nostdlib).
---
 aclocal.m4   |  6 ++---
 configure.ac | 76 ++++++++++++++++++++----------------------------------------
 2 files changed, 28 insertions(+), 54 deletions(-)
  

Comments

Joseph Myers Feb. 20, 2016, 5:32 p.m. UTC | #1
On Sat, 20 Feb 2016, Nix wrote:

> From: Nick Alcock <nick.alcock@oracle.com>
> 
> With all the machinery we just added, we can easily arrange to work even
> when the compiler passes in -fstack-protector automatically: all the
> necessary bits of glibc are always compiled with -fno-stack-protector
> now.
> 
> So tear out the check in configure, and add appropriate calls to
> -fno-stack-protector and/or -lssp in tests that need them (largely
> those that use -nostdlib).

You should avoid ever linking with -lssp.  Tests should return the same 
results when built with a minimal static-only bootstrap compiler (which 
likely has libssp disabled) as with a full compiler (indeed, a full 
compiler may well have libssp disabled as well), so that such a bootstrap 
compiler can produce glibc binaries identical to those produced by an 
alternating sequence of GCC and glibc builds.
  

Patch

diff --git a/aclocal.m4 b/aclocal.m4
index 3d64f77..a6db875 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -141,7 +141,7 @@  int _start (void) { return 0; }
 int __start (void) { return 0; }
 $1
 EOF
-AS_IF([AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -o conftest
+AS_IF([AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -o conftest
 		       conftest.c -static -nostartfiles -nostdlib
 		       1>&AS_MESSAGE_LOG_FD])],
       [$2], [$3])
@@ -226,7 +226,7 @@  if test x"$gnu_ld" = x"yes"; then
     cat > conftest.c <<EOF
 int _start (void) { return 42; }
 EOF
-    if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS
+    if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $libssp
 				$2 -nostdlib -nostartfiles
 				-fPIC -shared -o conftest.so conftest.c
 				1>&AS_MESSAGE_LOG_FD])
@@ -268,7 +268,7 @@  libc_compiler_builtin_inlined=no
 cat > conftest.c <<EOF
 int _start (void) { $2 return 0; }
 EOF
-if ! AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS
+if ! AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
 		     $3 -nostdlib -nostartfiles
 		     -S conftest.c -o - | fgrep "$1"
 		     1>&AS_MESSAGE_LOG_FD])
diff --git a/configure.ac b/configure.ac
index 804fac7..694bd68 100644
--- a/configure.ac
+++ b/configure.ac
@@ -643,6 +643,20 @@  fi
 AC_SUBST(libc_cv_ssp)
 AC_SUBST(stack_protector)
 
+if test -n "$stack_protector"; then
+  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
+  no_ssp=
+  libssp=
+
+  if test x"$enable_stack_protector" != xno; then
+    AC_MSG_ERROR([--enable-stack-protector=$enable_stack_protector specified, but specified level of stack protection is not supported by the compiler.])
+  fi
+fi
+
 # 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
@@ -662,7 +676,7 @@  __start:
 EOF
 libc_cv_ld_gnu_indirect_function=no
 if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS \
-	    -nostartfiles -nostdlib \
+	    -nostartfiles -nostdlib $no_ssp \
 	    -o conftest conftest.S 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then
   # Do a link to see if the backend supports IFUNC relocs.
   $READELF -r conftest 1>&AS_MESSAGE_LOG_FD
@@ -1131,8 +1145,8 @@  extern int glibc_conftest_frobozz;
 void _start() { glibc_conftest_frobozz = 1; }
 EOF
 if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS \
-	    -nostartfiles -nostdlib \
-	    -o conftest conftest.s conftest1.c 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then
+	    -nostartfiles -nostdlib $no_ssp \
+	    -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
@@ -1148,12 +1162,12 @@  AC_CACHE_CHECK(linker support for protected data symbol,
 		int bar __attribute__ ((visibility ("protected"))) = 1;
 EOF
 		libc_cv_protected_data=no
-		if AC_TRY_COMMAND(${CC-cc} -nostdlib -nostartfiles -fPIC -shared conftest.c -o conftest.so); then
+		if AC_TRY_COMMAND(${CC-cc} -nostdlib -nostartfiles -fPIC -shared conftest.c -o conftest.so $libssp); then
 		  cat > conftest.c <<EOF
 		  extern int bar;
 		  int main (void) { return bar; }
 EOF
-		  if AC_TRY_COMMAND(${CC-cc} -nostdlib -nostartfiles conftest.c -o conftest conftest.so); then
+		  if AC_TRY_COMMAND(${CC-cc} -nostdlib -nostartfiles conftest.c -o conftest conftest.so $libssp); then
 		    libc_cv_protected_data=yes
 		  fi
 		fi
@@ -1277,7 +1291,7 @@  EOF
 if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS
 			-fPIC -shared -o conftest.so conftest.c
 			-nostdlib -nostartfiles
-			-Wl,-z,combreloc 1>&AS_MESSAGE_LOG_FD])
+			-Wl,-z,combreloc $libssp 1>&AS_MESSAGE_LOG_FD])
 then
 dnl The following test is a bit weak.  We must use a tool which can test
 dnl cross-platform since the gcc used can be a cross compiler.  Without
@@ -1313,9 +1327,9 @@  AC_CACHE_CHECK(for --hash-style option,
 cat > conftest.c <<EOF
 int _start (void) { return 42; }
 EOF
-if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS
+if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
 			    -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
@@ -1385,7 +1399,7 @@  int foo (void) { return mumble; }
 EOF
 if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS
 			-fPIC -shared -o conftest.so conftest.c
-			-nostdlib -nostartfiles
+			-nostdlib -nostartfiles $libssp
 			1>&AS_MESSAGE_LOG_FD])
 then
 dnl look for GLOB_DAT relocation.
@@ -1402,7 +1416,7 @@  AC_SUBST(libc_cv_has_glob_dat)
 
 AC_CACHE_CHECK(linker output format, libc_cv_output_format, [dnl
 if libc_cv_output_format=`
-${CC-cc} -nostartfiles -nostdlib -Wl,--print-output-format 2>&AS_MESSAGE_LOG_FD`
+${CC-cc} -nostartfiles -nostdlib $no_ssp -Wl,--print-output-format 2>&AS_MESSAGE_LOG_FD`
 then
   :
 else
@@ -1601,46 +1615,6 @@  if test $libc_cv_predef_fortify_source = yes; then
 fi
 AC_SUBST(CPPUNDEFS)
 
-dnl Check for silly hacked compilers inserting -fstack-protector.
-dnl This breaks badly for the early startup code we compile, since
-dnl the compiled code can refer to a magic machine-dependent location
-dnl for the canary value before we have sufficient setup for that to
-dnl work.  It's also questionable to build all of libc with this flag
-dnl even when you're doing that for most applications you build, since
-dnl libc's code is so heavily-used and performance-sensitive.  If we
-dnl ever really want to make that work, it should be enabled explicitly
-dnl in the libc build, not inherited from implicit compiler settings.
-AC_CACHE_CHECK([whether $CC implicitly enables -fstack-protector],
-	       libc_cv_predef_stack_protector, [
-AC_TRY_COMPILE([extern void foobar (char *);],
-	       [char large_array[2048]; foobar (large_array);], [
-libc_undefs=`$NM -u conftest.o |
-  LC_ALL=C $AWK '$1 == "U" { print $2 | "sort -u"; next } { exit(1) }' \
-    2>&AS_MESSAGE_LOG_FD` || {
-  AC_MSG_ERROR([confusing output from $NM -u])
-}
-echo >&AS_MESSAGE_LOG_FD "libc_undefs='$libc_undefs'"
-# On some architectures, there are architecture-specific undefined
-# symbols (resolved by the linker), so filter out unknown symbols.
-# This will fail to produce the correct result if the compiler
-# defaults to -fstack-protector but this produces an undefined symbol
-# other than __stack_chk_fail.  However, compilers like that have not
-# been encountered in practice.
-libc_undefs=`echo "$libc_undefs" | egrep '^(foobar|__stack_chk_fail)$'`
-case "$libc_undefs" in
-foobar) libc_cv_predef_stack_protector=no ;;
-'__stack_chk_fail
-foobar') libc_cv_predef_stack_protector=yes ;;
-*) AC_MSG_ERROR([unexpected symbols in test: $libc_undefs]) ;;
-esac],
-	       [AC_MSG_ERROR([test compilation failed])])
-])
-libc_extra_cflags=
-if test $libc_cv_predef_stack_protector = yes; then
-  libc_extra_cflags="$libc_extra_cflags -fno-stack-protector"
-fi
-libc_extra_cppflags=
-
 # Some linkers on some architectures support __ehdr_start but with
 # bugs.  Make sure usage of it does not create relocations in the
 # output (as the linker should resolve them all for us).
@@ -1651,7 +1625,7 @@  old_LDFLAGS="$LDFLAGS"
 old_LIBS="$LIBS"
 CFLAGS="$CFLAGS -fPIC"
 LDFLAGS="$LDFLAGS -nostdlib -nostartfiles -shared"
-LIBS=
+LIBS=$libssp
 AC_LINK_IFELSE([AC_LANG_SOURCE([
 typedef struct {
   char foo;