Add a linker warning when creating potentially dangerous executable segments. Add...
authorNick Clifton <nickc@redhat.com>
Tue, 3 May 2022 10:42:24 +0000 (11:42 +0100)
committerNick Clifton <nickc@redhat.com>
Tue, 3 May 2022 10:42:24 +0000 (11:42 +0100)
21 files changed:
bfd/elf.c
bfd/elflink.c
binutils/testsuite/lib/binutils-common.exp
include/bfdlink.h
ld/NEWS
ld/aclocal.m4
ld/config.in
ld/configure
ld/configure.ac
ld/emultempl/elf.em
ld/ld.texi
ld/ldlex.h
ld/lexsup.c
ld/testsuite/ld-elf/changelma.d
ld/testsuite/ld-elf/elf.exp
ld/testsuite/ld-elf/flags1.d
ld/testsuite/ld-elf/maxpage5.d
ld/testsuite/ld-elf/note-2.d
ld/testsuite/ld-elf/rwx-segments-1.l [new file with mode: 0644]
ld/testsuite/ld-elf/rwx-segments-2.l [new file with mode: 0644]
ld/testsuite/ld-elf/rwx-segments-2.t [new file with mode: 0644]

index e9148dbecab21436e1d70b4c006b30a180ab4069..f046994e3a87fab4aa8fd68ca4fdc623f6118248 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -6461,6 +6461,29 @@ assign_file_positions_except_relocs (bfd *abfd,
   alloc = i_ehdrp->e_phnum;
   if (alloc != 0)
     {
+      if (link_info != NULL && ! link_info->no_warn_rwx_segments)
+       {
+         /* Memory resident segments with non-zero size and RWX permissions are a
+            security risk, so we generate a warning here if we are creating any.  */
+         unsigned int i;
+
+         for (i = 0; i < alloc; i++)
+           {
+             const Elf_Internal_Phdr * phdr = tdata->phdr + i;
+
+             if (phdr->p_memsz == 0)
+               continue;
+
+             if (phdr->p_type == PT_TLS && (phdr->p_flags & PF_X))
+               _bfd_error_handler (_("warning: %pB has a TLS segment with execute permission"),
+                                   abfd);
+             else if (phdr->p_type == PT_LOAD
+                      && (phdr->p_flags & (PF_R | PF_W | PF_X)) == (PF_R | PF_W | PF_X))
+               _bfd_error_handler (_("warning: %pB has a LOAD segment with RWX permissions"),
+                                   abfd);
+           }
+       }
+      
       if (bfd_seek (abfd, i_ehdrp->e_phoff, SEEK_SET) != 0
          || bed->s->write_out_phdrs (abfd, tdata->phdr, alloc) != 0)
        return false;
index b54ee517c754f51482818c1aeec1f60b5bb32ce7..4d6fe663f68ccb613c1c52abb2cf7250dd0e7aa2 100644 (file)
@@ -7168,7 +7168,7 @@ warning: enabling an executable stack because of -z execstack command line optio
                  break;
                }
            }
-         else if (bed->default_execstack)
+         else if (bed->default_execstack && info->default_execstack)
            {
              exec = PF_X;
              emptyobj = inputobj;
index a76a310c199b919f0fb683371e16648e587716cf..ccc33a827b4271da49dacdb3addd96c4fdd5a5bc 100644 (file)
@@ -639,6 +639,8 @@ proc prune_warnings_extra { text } {
     regsub -all "(^|\n)(\[^\n\]*: Warning: Gap in build notes detected from\[^\n\]*\n?)+" $text "\\1" text
     regsub -all "(^|\n)(\[^\n\]*: warning:\[^\n\]*missing \\.note\\.GNU-stack section\[^\n\]*\n?)+" $text "\\1" text
     regsub -all "(^|\n)(\[^\n\]*: NOTE: This behaviour is deprecated\[^\n\]*\n?)+" $text "\\1" text
+    regsub -all "(^|\n)(\[^\n\]*: warning:\[^\n\]*has a LOAD segment with RWX permissions\[^\n\]*\n?)+" $text "\\1" text
+    regsub -all "(^|\n)(\[^\n\]*: warning:\[^\n\]*has a TLS segment with execute permission\[^\n\]*\n?)+" $text "\\1" text
     return $text
 }
 
index b16f3f44ca5d023f2459930c340ac15fead1b365..88cc8e2618397a6c873d0acd257b87251903607d 100644 (file)
@@ -489,10 +489,25 @@ struct bfd_link_info
      flags.  */
   unsigned int noexecstack: 1;
 
-  /* Tri-state variable: 0 => not set by user; 1 => set, warnings
-     enabled; 2 => warnings disabled; 3 => unused.  */
+  /* Tri-state variable:
+     0 => warn if the linker is creating an executable stack, but
+     execstack (above) is 0.
+     1 => warn if the linker is creating an executable stack; ignores
+     the value of execstack.
+     2 => do not warn.
+     3 => not used.  */
   unsigned int warn_execstack: 2;
 
+  /* TRUE if warnings should not be generated for TLS segments with eXecute
+     permission or LOAD segments with RWX permissions.  */
+  unsigned int no_warn_rwx_segments: 1;
+
+  /* TRUE if the stack can be made executable because of the absence of a
+     .note.GNU-stack section in an input file.  Note - even if this field
+     is set, some targets may choose to ignore the setting and not create
+     an executable stack.  */
+  unsigned int default_execstack : 1;
+  
   /* TRUE if we want to produced optimized output files.  This might
      need much more time and therefore must be explicitly selected.  */
   unsigned int optimize: 1;
diff --git a/ld/NEWS b/ld/NEWS
index b84553109d2bc134a171f5113173c5ae6b4737e4..514d1d9f20763a8f784ee2293f4e9cc0265dedc4 100644 (file)
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,6 +1,6 @@
 -*- text -*-
 
-* The linker will now generate a warning message if the stack is made
+* The ELF linker will now generate a warning message if the stack is made
   executable.  By default this warning is not issued if the user has
   specifically requested an executable stack via the "-z execstack"
   command line option, but the warning can be forced via the new
@@ -8,6 +8,28 @@
   an executable stack can be suppressed via the "--no-warn-execstack"
   option.
 
+  In addition the ELF linker will also warn if it creates a memory resident
+  segment with all three of the Read, Write and eXecute permissions set, or
+  if it creates a thread local data segment with the eXecute permission set.
+  These warnings can be disabled via --no-warn-rwx-segments option and
+  re-enabled via the --warn-rwx-segments option.
+
+  New configure options can also control these new features:
+  
+  --enable-warn-execstack=no
+     will disable the warnings about creating an executable stack.
+     
+  --enable-warn-execstack=yes
+     will make --warn-execstack enabled by default.
+     
+  --enable-warn-rwx-segments=no
+     will make --no-warn-rwx-segments enabled by default.
+     
+  --enable-defaul-execstack=no
+     will stop the creation of an executable stack simply because an input file
+     is missing a .note.GNU-stack section, even on architectures where this
+     ehaviour is the default.
+
 * TYPE=<type> is now supported in an output section description to set the
   section type value.
 
index 631ead7b2cab1a66c8856fb4ec071988d7957250..314969c6dd8b66394224e8d386649d7c5ffe9f88 100644 (file)
@@ -1,6 +1,6 @@
-# generated automatically by aclocal 1.15.1 -*- Autoconf -*-
+# generated automatically by aclocal 1.16.2 -*- Autoconf -*-
 
-# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+# Copyright (C) 1996-2020 Free Software Foundation, Inc.
 
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -20,7 +20,7 @@ You have another version of autoconf.  It may work, but is not guaranteed to.
 If you have problems, you may need to regenerate the build system entirely.
 To do so, use the procedure documented by the package, typically 'autoreconf'.])])
 
-# Copyright (C) 2002-2017 Free Software Foundation, Inc.
+# Copyright (C) 2002-2020 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -32,10 +32,10 @@ To do so, use the procedure documented by the package, typically 'autoreconf'.])
 # generated from the m4 files accompanying Automake X.Y.
 # (This private macro should not be called outside this file.)
 AC_DEFUN([AM_AUTOMAKE_VERSION],
-[am__api_version='1.15'
+[am__api_version='1.16'
 dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
 dnl require some minimum version.  Point them to the right macro.
-m4_if([$1], [1.15.1], [],
+m4_if([$1], [1.16.2], [],
       [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
 ])
 
@@ -51,14 +51,14 @@ m4_define([_AM_AUTOCONF_VERSION], [])
 # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
 # This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
 AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
-[AM_AUTOMAKE_VERSION([1.15.1])dnl
+[AM_AUTOMAKE_VERSION([1.16.2])dnl
 m4_ifndef([AC_AUTOCONF_VERSION],
   [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
 _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
 
 # AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
 
-# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -110,7 +110,7 @@ am_aux_dir=`cd "$ac_aux_dir" && pwd`
 
 # AM_CONDITIONAL                                            -*- Autoconf -*-
 
-# Copyright (C) 1997-2017 Free Software Foundation, Inc.
+# Copyright (C) 1997-2020 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -141,7 +141,7 @@ AC_CONFIG_COMMANDS_PRE(
 Usually this means the macro was only invoked conditionally.]])
 fi])])
 
-# Copyright (C) 1999-2017 Free Software Foundation, Inc.
+# Copyright (C) 1999-2020 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -332,13 +332,12 @@ _AM_SUBST_NOTMAKE([am__nodep])dnl
 
 # Generate code to set up dependency tracking.              -*- Autoconf -*-
 
-# Copyright (C) 1999-2017 Free Software Foundation, Inc.
+# Copyright (C) 1999-2020 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-
 # _AM_OUTPUT_DEPENDENCY_COMMANDS
 # ------------------------------
 AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
@@ -346,49 +345,43 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
   # Older Autoconf quotes --file arguments for eval, but not when files
   # are listed without --file.  Let's play safe and only enable the eval
   # if we detect the quoting.
-  case $CONFIG_FILES in
-  *\'*) eval set x "$CONFIG_FILES" ;;
-  *)   set x $CONFIG_FILES ;;
-  esac
+  # TODO: see whether this extra hack can be removed once we start
+  # requiring Autoconf 2.70 or later.
+  AS_CASE([$CONFIG_FILES],
+          [*\'*], [eval set x "$CONFIG_FILES"],
+          [*], [set x $CONFIG_FILES])
   shift
-  for mf
+  # Used to flag and report bootstrapping failures.
+  am_rc=0
+  for am_mf
   do
     # Strip MF so we end up with the name of the file.
-    mf=`echo "$mf" | sed -e 's/:.*$//'`
-    # Check whether this is an Automake generated Makefile or not.
-    # We used to match only the files named 'Makefile.in', but
-    # some people rename them; so instead we look at the file content.
-    # Grep'ing the first line is not enough: some people post-process
-    # each Makefile.in and add a new line on top of each file to say so.
-    # Grep'ing the whole file is not good either: AIX grep has a line
+    am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'`
+    # Check whether this is an Automake generated Makefile which includes
+    # dependency-tracking related rules and includes.
+    # Grep'ing the whole file directly is not great: AIX grep has a line
     # limit of 2048, but all sed's we know have understand at least 4000.
-    if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
-      dirpart=`AS_DIRNAME("$mf")`
-    else
-      continue
-    fi
-    # Extract the definition of DEPDIR, am__include, and am__quote
-    # from the Makefile without running 'make'.
-    DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
-    test -z "$DEPDIR" && continue
-    am__include=`sed -n 's/^am__include = //p' < "$mf"`
-    test -z "$am__include" && continue
-    am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
-    # Find all dependency output files, they are included files with
-    # $(DEPDIR) in their names.  We invoke sed twice because it is the
-    # simplest approach to changing $(DEPDIR) to its actual value in the
-    # expansion.
-    for file in `sed -n "
-      s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
-        sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
-      # Make sure the directory exists.
-      test -f "$dirpart/$file" && continue
-      fdir=`AS_DIRNAME(["$file"])`
-      AS_MKDIR_P([$dirpart/$fdir])
-      # echo "creating $dirpart/$file"
-      echo '# dummy' > "$dirpart/$file"
-    done
+    sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
+      || continue
+    am_dirpart=`AS_DIRNAME(["$am_mf"])`
+    am_filepart=`AS_BASENAME(["$am_mf"])`
+    AM_RUN_LOG([cd "$am_dirpart" \
+      && sed -e '/# am--include-marker/d' "$am_filepart" \
+        | $MAKE -f - am--depfiles]) || am_rc=$?
   done
+  if test $am_rc -ne 0; then
+    AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments
+    for automatic dependency tracking.  If GNU make was not used, consider
+    re-running the configure script with MAKE="gmake" (or whatever is
+    necessary).  You can also try re-running configure with the
+    '--disable-dependency-tracking' option to at least be able to build
+    the package (albeit without support for automatic dependency tracking).])
+  fi
+  AS_UNSET([am_dirpart])
+  AS_UNSET([am_filepart])
+  AS_UNSET([am_mf])
+  AS_UNSET([am_rc])
+  rm -f conftest-deps.mk
 }
 ])# _AM_OUTPUT_DEPENDENCY_COMMANDS
 
@@ -397,18 +390,17 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
 # -----------------------------
 # This macro should only be invoked once -- use via AC_REQUIRE.
 #
-# This code is only required when automatic dependency tracking
-# is enabled.  FIXME.  This creates each '.P' file that we will
-# need in order to bootstrap the dependency handling code.
+# This code is only required when automatic dependency tracking is enabled.
+# This creates each '.Po' and '.Plo' makefile fragment that we'll need in
+# order to bootstrap the dependency handling code.
 AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
 [AC_CONFIG_COMMANDS([depfiles],
      [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
-     [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
-])
+     [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])])
 
 # Do all the work for Automake.                             -*- Autoconf -*-
 
-# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+# Copyright (C) 1996-2020 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -495,8 +487,8 @@ AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
 AC_REQUIRE([AC_PROG_MKDIR_P])dnl
 # For better backward compatibility.  To be removed once Automake 1.9.x
 # dies out for good.  For more background, see:
-# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
-# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
+# <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
+# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
 AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
 # We need awk for the "check" target (and possibly the TAP driver).  The
 # system "awk" is bad on some platforms.
@@ -563,7 +555,7 @@ END
 Aborting the configuration process, to ensure you take notice of the issue.
 
 You can download and install GNU coreutils to get an 'rm' implementation
-that behaves properly: <http://www.gnu.org/software/coreutils/>.
+that behaves properly: <https://www.gnu.org/software/coreutils/>.
 
 If you want to complete the configuration process using your problematic
 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
@@ -605,7 +597,7 @@ for _am_header in $config_headers :; do
 done
 echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
 
-# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -626,7 +618,7 @@ if test x"${install_sh+set}" != xset; then
 fi
 AC_SUBST([install_sh])])
 
-# Copyright (C) 1998-2017 Free Software Foundation, Inc.
+# Copyright (C) 1998-2020 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -647,7 +639,7 @@ fi])
 # Add --enable-maintainer-mode option to configure.         -*- Autoconf -*-
 # From Jim Meyering
 
-# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+# Copyright (C) 1996-2020 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -682,7 +674,7 @@ AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
 
 # Check to see how 'make' treats includes.                 -*- Autoconf -*-
 
-# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -690,49 +682,42 @@ AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
 
 # AM_MAKE_INCLUDE()
 # -----------------
-# Check to see how make treats includes.
+# Check whether make has an 'include' directive that can support all
+# the idioms we need for our automatic dependency tracking code.
 AC_DEFUN([AM_MAKE_INCLUDE],
-[am_make=${MAKE-make}
-cat > confinc << 'END'
+[AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive])
+cat > confinc.mk << 'END'
 am__doit:
-       @echo this is the am__doit target
+       @echo this is the am__doit target >confinc.out
 .PHONY: am__doit
 END
-# If we don't find an include directive, just comment out the code.
-AC_MSG_CHECKING([for style of include used by $am_make])
 am__include="#"
 am__quote=
-_am_result=none
-# First try GNU make style include.
-echo "include confinc" > confmf
-# Ignore all kinds of additional output from 'make'.
-case `$am_make -s -f confmf 2> /dev/null` in #(
-*the\ am__doit\ target*)
-  am__include=include
-  am__quote=
-  _am_result=GNU
-  ;;
-esac
-# Now try BSD make style include.
-if test "$am__include" = "#"; then
-   echo '.include "confinc"' > confmf
-   case `$am_make -s -f confmf 2> /dev/null` in #(
-   *the\ am__doit\ target*)
-     am__include=.include
-     am__quote="\""
-     _am_result=BSD
-     ;;
-   esac
-fi
-AC_SUBST([am__include])
-AC_SUBST([am__quote])
-AC_MSG_RESULT([$_am_result])
-rm -f confinc confmf
-])
+# BSD make does it like this.
+echo '.include "confinc.mk" # ignored' > confmf.BSD
+# Other make implementations (GNU, Solaris 10, AIX) do it like this.
+echo 'include confinc.mk # ignored' > confmf.GNU
+_am_result=no
+for s in GNU BSD; do
+  AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out])
+  AS_CASE([$?:`cat confinc.out 2>/dev/null`],
+      ['0:this is the am__doit target'],
+      [AS_CASE([$s],
+          [BSD], [am__include='.include' am__quote='"'],
+          [am__include='include' am__quote=''])])
+  if test "$am__include" != "#"; then
+    _am_result="yes ($s style)"
+    break
+  fi
+done
+rm -f confinc.* confmf.*
+AC_MSG_RESULT([${_am_result}])
+AC_SUBST([am__include])])
+AC_SUBST([am__quote])])
 
 # Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
 
-# Copyright (C) 1997-2017 Free Software Foundation, Inc.
+# Copyright (C) 1997-2020 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -771,7 +756,7 @@ fi
 
 # Helper functions for option handling.                     -*- Autoconf -*-
 
-# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -800,7 +785,7 @@ AC_DEFUN([_AM_SET_OPTIONS],
 AC_DEFUN([_AM_IF_OPTION],
 [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
 
-# Copyright (C) 1999-2017 Free Software Foundation, Inc.
+# Copyright (C) 1999-2020 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -847,7 +832,7 @@ AC_LANG_POP([C])])
 # For backward compatibility.
 AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
 
-# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -866,7 +851,7 @@ AC_DEFUN([AM_RUN_LOG],
 
 # Check to make sure that the build environment is sane.    -*- Autoconf -*-
 
-# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+# Copyright (C) 1996-2020 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -947,7 +932,7 @@ AC_CONFIG_COMMANDS_PRE(
 rm -f conftest.file
 ])
 
-# Copyright (C) 2009-2017 Free Software Foundation, Inc.
+# Copyright (C) 2009-2020 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -1007,7 +992,7 @@ AC_SUBST([AM_BACKSLASH])dnl
 _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
 ])
 
-# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -1035,7 +1020,7 @@ fi
 INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
 AC_SUBST([INSTALL_STRIP_PROGRAM])])
 
-# Copyright (C) 2006-2017 Free Software Foundation, Inc.
+# Copyright (C) 2006-2020 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -1054,7 +1039,7 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
 
 # Check how to create a tarball.                            -*- Autoconf -*-
 
-# Copyright (C) 2004-2017 Free Software Foundation, Inc.
+# Copyright (C) 2004-2020 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
index 26d55a00d47b97d55046ec69711626ce48e2f6b3..cc5b476f009347d92601dac256491f790eca549b 100644 (file)
 /* Define if you want compressed debug sections by default. */
 #undef DEFAULT_FLAG_COMPRESS_DEBUG
 
+/* Define to 0 if you want to disable the generation of an executable stack
+   when a .note-GNU-stack section is missing. */
+#undef DEFAULT_LD_EXECSTACK
+
 /* The default method for DT_TEXTREL check in ELF linker. */
 #undef DEFAULT_LD_TEXTREL_CHECK
 
 /* Define to 1 if DT_TEXTREL check is warning in ELF linker by default. */
 #undef DEFAULT_LD_TEXTREL_CHECK_WARNING
 
+/* Define to 1 if you want to enable --warn-execstack in ELF linker by
+   default. */
+#undef DEFAULT_LD_WARN_EXECSTACK
+
+/* Define to 0 if you want to disable --warn-rwx-segments in ELF linker by
+   default. */
+#undef DEFAULT_LD_WARN_RWX_SEGMENTS
+
 /* Define to 1 if you want to enable -z relro in ELF linker by default. */
 #undef DEFAULT_LD_Z_RELRO
 
index bab2d083ca85dfa65483946014c429f1a9f2bbcd..b4b0ce14ed9e0b93c2d3bd9f57dd8ac5bd5abfb4 100755 (executable)
@@ -838,6 +838,9 @@ enable_new_dtags
 enable_relro
 enable_textrel_check
 enable_separate_code
+enable_warn_execstack
+enable_warn_rwx_segments
+enable_default_execstack
 enable_error_handling_script
 enable_default_hash_style
 enable_initfini_array
@@ -1510,6 +1513,13 @@ Optional Features:
   --enable-textrel-check=[yes|no|warning|error]
                           enable DT_TEXTREL check in ELF linker
   --enable-separate-code  enable -z separate-code in ELF linker by default
+  --enable-warn-execstack enable warnings when creating an executable stack
+  --enable-warn-rwx-segments
+                          enable warnings when creating segements with RWX
+                          permissions
+  --enable-default-execstack
+                          create an executable stack if an input file is
+                          missing a .note.GNU-stack section
   --enable-error-handling-script
                           enable/disable support for the
                           --error-handling-script option
@@ -11460,7 +11470,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11463 "configure"
+#line 11473 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11566,7 +11576,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11569 "configure"
+#line 11579 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -15427,6 +15437,38 @@ esac
 fi
 
 
+
+ac_default_ld_warn_execstack=unset
+# Check whether --enable-warn-execstack was given.
+if test "${enable_warn_execstack+set}" = set; then :
+  enableval=$enable_warn_execstack; case "${enableval}" in
+  yes) ac_default_ld_warn_execstack=1 ;;
+  no)  ac_default_ld_warn_execstack=-1 ;;
+esac
+fi
+
+
+ac_default_ld_warn_rwx_segments=unset
+# Check whether --enable-warn-rwx-segments was given.
+if test "${enable_warn_rwx_segments+set}" = set; then :
+  enableval=$enable_warn_rwx_segments; case "${enableval}" in
+  yes) ac_default_ld_warn_rwx_segments=1 ;;
+  no)  ac_default_ld_warn_rwx_segments=0 ;;
+esac
+fi
+
+
+ac_default_ld_default_execstack=unset
+# Check whether --enable-default-execstack was given.
+if test "${enable_default_execstack+set}" = set; then :
+  enableval=$enable_default_execstack; case "${enableval}" in
+  yes) ac_default_ld_default_execstack=1 ;;
+  no)  ac_default_ld_default_execstack=0 ;;
+esac
+fi
+
+
+
 # Decide if --error-handling-script should be supported.
 ac_support_error_handling_script=unset
 # Check whether --enable-error-handling-script was given.
@@ -16954,6 +16996,35 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
+
+if test "${ac_default_ld_warn_execstack}" = unset; then
+  ac_default_ld_warn_execstack=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define DEFAULT_LD_WARN_EXECSTACK $ac_default_ld_warn_execstack
+_ACEOF
+
+
+if test "${ac_default_ld_warn_rwx_segments}" = unset; then
+  ac_default_ld_warn_rwx_segments=1
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define DEFAULT_LD_WARN_RWX_SEGMENTS $ac_default_ld_warn_rwx_segments
+_ACEOF
+
+
+if test "${ac_default_ld_default_execstack}" = unset; then
+  ac_default_ld_default_execstack=1
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define DEFAULT_LD_EXECSTACK $ac_default_ld_default_execstack
+_ACEOF
+
+
+
 if test "${ac_support_error_handling_script}" = unset; then
   ac_support_error_handling_script=1
 fi
index 7f4cff079b7f241930c89578de857857898d87a5..0b29e810ddef2ab0a62d63e6deec1c823eb98731 100644 (file)
@@ -203,6 +203,35 @@ AC_ARG_ENABLE(separate-code,
   no) ac_default_ld_z_separate_code=0 ;;
 esac])
 
+
+ac_default_ld_warn_execstack=unset
+AC_ARG_ENABLE(warn-execstack,
+             AS_HELP_STRING([--enable-warn-execstack],
+             [enable warnings when creating an executable stack]),
+[case "${enableval}" in
+  yes) ac_default_ld_warn_execstack=1 ;;
+  no)  ac_default_ld_warn_execstack=-1 ;;
+esac])
+
+ac_default_ld_warn_rwx_segments=unset
+AC_ARG_ENABLE(warn-rwx-segments,
+             AS_HELP_STRING([--enable-warn-rwx-segments],
+             [enable warnings when creating segements with RWX permissions]),
+[case "${enableval}" in
+  yes) ac_default_ld_warn_rwx_segments=1 ;;
+  no)  ac_default_ld_warn_rwx_segments=0 ;;
+esac])
+
+ac_default_ld_default_execstack=unset
+AC_ARG_ENABLE(default-execstack,
+             AS_HELP_STRING([--enable-default-execstack],
+             [create an executable stack if an input file is missing a .note.GNU-stack section]),
+[case "${enableval}" in
+  yes) ac_default_ld_default_execstack=1 ;;
+  no)  ac_default_ld_default_execstack=0 ;;
+esac])
+
+
 # Decide if --error-handling-script should be supported.
 ac_support_error_handling_script=unset
 AC_ARG_ENABLE(error-handling-script,
@@ -501,6 +530,29 @@ AC_DEFINE_UNQUOTED(DEFAULT_LD_Z_SEPARATE_CODE,
   $ac_default_ld_z_separate_code,
   [Define to 1 if you want to enable -z separate-code in ELF linker by default.])
 
+
+if test "${ac_default_ld_warn_execstack}" = unset; then
+  ac_default_ld_warn_execstack=0
+fi
+AC_DEFINE_UNQUOTED(DEFAULT_LD_WARN_EXECSTACK,
+  $ac_default_ld_warn_execstack,
+  [Define to 1 if you want to enable --warn-execstack in ELF linker by default.])
+
+if test "${ac_default_ld_warn_rwx_segments}" = unset; then
+  ac_default_ld_warn_rwx_segments=1
+fi
+AC_DEFINE_UNQUOTED(DEFAULT_LD_WARN_RWX_SEGMENTS,
+  $ac_default_ld_warn_rwx_segments,
+  [Define to 0 if you want to disable --warn-rwx-segments in ELF linker by default.])
+
+if test "${ac_default_ld_default_execstack}" = unset; then
+  ac_default_ld_default_execstack=1
+fi
+AC_DEFINE_UNQUOTED(DEFAULT_LD_EXECSTACK,
+  $ac_default_ld_default_execstack,
+  [Define to 0 if you want to disable the generation of an executable stack when a .note-GNU-stack section is missing.])
+
+
 if test "${ac_support_error_handling_script}" = unset; then
   ac_support_error_handling_script=1
 fi
index 7ae6f6d50e180e408c44b22cb6d9af7cd0233ae2..c027559908cf1b2127036579fe3f38210c16cb10 100644 (file)
@@ -92,6 +92,9 @@ EOF
 fi
 fragment <<EOF
   link_info.separate_code = DEFAULT_LD_Z_SEPARATE_CODE;
+  link_info.warn_execstack = DEFAULT_LD_WARN_EXECSTACK;
+  link_info.no_warn_rwx_segments = ! DEFAULT_LD_WARN_RWX_SEGMENTS;
+  link_info.default_execstack = DEFAULT_LD_EXECSTACK;
 }
 
 EOF
index 6ac5344ebf4d1a16d8a530b37a5f2c169e984f35..8cad84781404b9eb6402c7807708996785543216 100644 (file)
@@ -2701,6 +2701,22 @@ option causes a warning to be issued whenever this case occurs.
 Only warn once for each undefined symbol, rather than once per module
 which refers to it.
 
+@kindex --warn-rwx-segments
+@cindex warnings, on writeable and exectuable segments
+@cindex executable segments, warnings on
+@item --warn-rwx-segments
+@itemx --no-warn-rwx-segments
+Warn if the linker creates a loadable, non-zero sized segment that has
+all three of the read, write and execute permission flags set.  Such a
+segment represents a potential security vulnerability.  In addition
+warnings will be generated if a thread local storage segment is
+created with the execute permission flag set, regardless of whether or
+not it has the read and/or write flags set.
+
+These warnings are enabled by default.  They can be disabled via the
+@option{--no-warn-rwx-segments} option and re-enabled via the
+@option{--warn-rwx-segments} option.
+
 @kindex --warn-section-align
 @cindex warnings, on section alignment
 @cindex section alignment, warnings on
index 1d42dc8672ea2af4e3afe1fa382edfab7543a794..57ade1f754b419223d5b299aa912db8b8e7da641 100644 (file)
@@ -166,10 +166,13 @@ enum option_values
   OPTION_CTF_SHARE_TYPES,
   OPTION_WARN_EXECSTACK,
   OPTION_NO_WARN_EXECSTACK,
+  OPTION_WARN_RWX_SEGMENTS,
+  OPTION_NO_WARN_RWX_SEGMENTS,
 };
 
 /* The initial parser states.  */
-typedef enum input_enum {
+typedef enum input_enum
+{
   input_selected,              /* We've set the initial state.  */
   input_script,
   input_mri_script,
index 2929fecb6042997bd092c16e1b5891e2e41db7a1..78190472907351eeec19ec62ed5f3fdb155955f2 100644 (file)
@@ -540,6 +540,10 @@ static const struct ld_option ld_options[] =
     '\0', NULL, N_("Warn when creating an executable stack"), TWO_DASHES },
   { {"no-warn-execstack", no_argument, NULL, OPTION_NO_WARN_EXECSTACK},
     '\0', NULL, N_("Do not warn when creating an executable stack"), TWO_DASHES },
+  { {"warn-rwx-segments", no_argument, NULL, OPTION_WARN_RWX_SEGMENTS},
+    '\0', NULL, N_("Warn when creating executable segments"), TWO_DASHES },
+  { {"no-warn-rwx-segments", no_argument, NULL, OPTION_NO_WARN_RWX_SEGMENTS},
+    '\0', NULL, N_("Do not warn when creating executable segments"), TWO_DASHES },
   { {"warn-multiple-gp", no_argument, NULL, OPTION_WARN_MULTIPLE_GP},
     '\0', NULL, N_("Warn if the multiple GP values are used"), TWO_DASHES },
   { {"warn-once", no_argument, NULL, OPTION_WARN_ONCE},
@@ -925,6 +929,12 @@ parse_args (unsigned argc, char **argv)
        case OPTION_NO_WARN_EXECSTACK:
          link_info.warn_execstack = 2;
          break;
+       case OPTION_WARN_RWX_SEGMENTS:
+         link_info.no_warn_rwx_segments = 0;
+         break;
+       case OPTION_NO_WARN_RWX_SEGMENTS:
+         link_info.no_warn_rwx_segments = 1;
+         break;
        case 'e':
          lang_add_entry (optarg, true);
          break;
@@ -2159,10 +2169,31 @@ elf_static_list_options (FILE *file)
   -z execstack                Mark executable as requiring executable stack\n"));
   fprintf (file, _("\
   -z noexecstack              Mark executable as not requiring executable stack\n"));
+#if DEFAULT_LD_WARN_EXECSTACK > 0
+  fprintf (file, _("\
+  --warn-execstack            Generate a warning if the stack is executable (default)\n"));
+#else
   fprintf (file, _("\
   --warn-execstack            Generate a warning if the stack is executable\n"));
+#endif
+#if DEFAULT_LD_WARN_EXECSTACK < 0
+  fprintf (file, _("\
+  --no-warn-execstack         Do not generate a warning if the stack is executable (default)\n"));
+#else
   fprintf (file, _("\
   --no-warn-execstack         Do not generate a warning if the stack is executable\n"));
+#endif
+#if DEFAULT_LD_WARN_RWX_SEGMENTS
+  fprintf (file, _("\
+  --warn-rwx-segments         Generate a warning if a LOAD segment has RWX permissions (default)\n"));
+  fprintf (file, _("\
+  --no-warn-rwx-segments      Do not generate a warning if a LOAD segments has RWX permissions\n"));
+#else
+  fprintf (file, _("\
+  --warn-rwx-segments         Generate a warning if a LOAD segment has RWX permissions\n"));
+  fprintf (file, _("\
+  --no-warn-rwx-segments      Do not generate a warning if a LOAD segments has RWX permissions (default)\n"));
+#endif
   fprintf (file, _("\
   -z unique-symbol            Avoid duplicated local symbol names\n"));
   fprintf (file, _("\
index 858a8db37ae64fcffc7f74361bdc1deb02f4fcf9..567e72d33019599dc9dcce330715e9aa729d21cf 100644 (file)
@@ -1,5 +1,5 @@
 #name: changelma (pr20659)
-#ld: -T changelma.lnk
+#ld: -T changelma.lnk --no-warn-rwx-segments
 #objcopy_linked_file: --change-section-lma .dynamic+0x80000000
 #readelf: -l --wide
 #xfail: rx-*-*
index d56154011b339cb158311b6ba65d34a389e09e1e..1b300117ad12342921d29f5247d6abb6c3df6509 100644 (file)
@@ -182,6 +182,7 @@ if { [check_gc_sections_available] && ![istarget "v850-*-*"] } {
 
 proc target_defaults_to_execstack {} {
     if {   [istarget "aarch64*-*-*"]
+       || [istarget "*-*-nacl"]
        || [istarget "arc*-*-*"]
        || [istarget "ia64*-*-*"]
        || [istarget "loongarch*-*-*"]
@@ -226,7 +227,18 @@ if {   [istarget *-*-*linux*]
            "" \
            {pr23900-1.s} \
            [list [list "readelf" {-Wl} $pr23900_1_exp]] \
-           "pr23900-1.exe"] \
+            "pr23900-1.exe"] \
+         ]
+
+    # Test the linker's generation of execstack and executable segment warnings.
+    # Since these are normally pruned from the linker's output we temporarily
+    # disable tha action here.
+    rename prune_warnings_extra old_prune_warnings_extra
+    proc prune_warnings_extra { text } {
+       return $text
+    }
+    
+    run_ld_link_tests [list \
        [list "PR ld/29072 (warn about an executable .note.GNU-stack)" \
            "-e 0" \
            "" \
@@ -248,23 +260,39 @@ if {   [istarget *-*-*linux*]
            {pr29072-a.s} \
            {} \
            "pr29072-d.exe"] \
-       ]
+       [list "Ensure that a warning issued when creating a segment with RWX permissions" \
+           "-e 0 -Tnobits-1.t --warn-rwx-segments" \
+           "" \
+           "" \
+           {nobits-1.s} \
+            {{ld rwx-segments-1.l}} \
+           "rwx-segments-1.exe"] \
+       [list "Ensure that a warning issued when creating a TLS segment with execute permission" \
+           "-e 0 -T rwx-segments-2.t --warn-rwx-segments" \
+           "" \
+           "" \
+           {size-2.s} \
+            {{ld rwx-segments-2.l}} \
+           "rwx-segments-2.exe"] \
+       [list "Ensure that the warning can be suppressed" \
+           "-e 0 -Tnobits-1.t --no-warn-rwx-segments" \
+           "" \
+           "" \
+           {nobits-1.s} \
+            {} \
+           "rwx-segments-3.exe"] \
+         ]
+
     if { [target_defaults_to_execstack] } {
-       rename prune_warnings_extra old_prune_warnings_extra
-       proc prune_warnings_extra { text } {
-           return $text
-       }
        run_ld_link_tests [list \
           [list "PR ld/29072 (warn about absent .note.GNU-stack)" \
-           "-e 0 -z stack-size=0x123400" \
+           "-e 0 -z stack-size=0x123400  --warn-execstack" \
            "" \
            "" \
            {pr29072-b.s} \
            {{ld pr29072.b.warn}} \
            "pr29072-b.exe"] \
        ]
-       rename prune_warnings_extra ""
-       rename old_prune_warnings_extra prune_warnings_extra
     } else {
        run_ld_link_tests [list \
           [list "PR ld/29072 (ignore absent .note.GNU-stack)" \
@@ -276,6 +304,10 @@ if {   [istarget *-*-*linux*]
            "pr29072-b.exe"] \
        ]
     }
+
+    # Restore the normal pruning behaviour.
+    rename prune_warnings_extra ""
+    rename old_prune_warnings_extra prune_warnings_extra
 }
 
 if [check_gc_sections_available] {
index 6cd8b3f3832bea949992a6a031af562c5fac04ff..d9034e25dc77eab42f26c8401337665c01e74655 100644 (file)
@@ -1,5 +1,5 @@
 #name: --set-section-flags test 1 (sections)
-#ld: -Tflags1.ld
+#ld: -Tflags1.ld --no-warn-rwx-segments
 #objcopy_linked_file: --set-section-flags .post_text_reserve=contents,alloc,load,readonly,code
 #readelf: -S --wide
 
index 9d9b57a853ab18aba0a838272c0fca9d77e0b5cb..843a976111ad1e7d517eb8ae806d29f464b3f41f 100644 (file)
@@ -1,6 +1,6 @@
 #source: maxpage5.s
 #as: --32
-#ld: -z max-page-size=0x200000 -T maxpage5.t
+#ld: -z max-page-size=0x200000 -T maxpage5.t --no-warn-rwx-segments
 #objcopy_linked_file: -R .foo
 #readelf: -l --wide
 #target: x86_64-*-linux* i?86-*-linux-gnu i?86-*-gnu*
index aff32406de20e0b6585b5f7b9675f454fe99ebc8..ed81703dc2de2893b9ccf0933af1d838984a2ae5 100644 (file)
@@ -1,4 +1,4 @@
-#ld: -Tnote-2.t
+#ld: -Tnote-2.t --no-warn-rwx-segments
 #objcopy_linked_file: -R .foo 
 #readelf: -l --wide
 
diff --git a/ld/testsuite/ld-elf/rwx-segments-1.l b/ld/testsuite/ld-elf/rwx-segments-1.l
new file mode 100644 (file)
index 0000000..432fceb
--- /dev/null
@@ -0,0 +1 @@
+.*warning: .* has a LOAD segment with RWX permissions
diff --git a/ld/testsuite/ld-elf/rwx-segments-2.l b/ld/testsuite/ld-elf/rwx-segments-2.l
new file mode 100644 (file)
index 0000000..b830de6
--- /dev/null
@@ -0,0 +1 @@
+.*: warning: .* has a TLS segment with execute permission
diff --git a/ld/testsuite/ld-elf/rwx-segments-2.t b/ld/testsuite/ld-elf/rwx-segments-2.t
new file mode 100644 (file)
index 0000000..f3aef1d
--- /dev/null
@@ -0,0 +1,20 @@
+PHDRS
+{
+  header PT_PHDR PHDRS ;
+        
+  image PT_LOAD FLAGS (5) PHDRS;
+  tls   PT_TLS  FLAGS (7);
+  
+}
+SECTIONS
+{
+  .text 0x100 : { *(.text) } :image
+  .tdata : { *(.tdata) } :image :tls
+  .tbss : { *(.tbss) } :image : tls
+  .map : {
+    LONG (SIZEOF (.text))
+    LONG (SIZEOF (.tdata))
+    LONG (SIZEOF (.tbss))
+  } :image
+  /DISCARD/ : { *(*) }
+}