aboutsummaryrefslogtreecommitdiff
path: root/gcc/gcc.cc
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2023-08-01 17:30:13 -0400
committerMarek Polacek <polacek@redhat.com>2023-11-23 11:54:17 -0500
commit24592abd68e6efd4ab00c23d4702a046e63f24aa (patch)
tree6c8cf9935b66dbd28ad3f5891037b0f7da8c5433 /gcc/gcc.cc
parent2eb833534c7e715c276658ecb810715e8718e5c3 (diff)
downloadgcc-24592abd68e6efd4ab00c23d4702a046e63f24aa.zip
gcc-24592abd68e6efd4ab00c23d4702a046e63f24aa.tar.gz
gcc-24592abd68e6efd4ab00c23d4702a046e63f24aa.tar.bz2
gcc: Introduce -fhardened
In <https://gcc.gnu.org/pipermail/gcc-patches/2023-August/628748.html> I proposed -fhardened, a new umbrella option that enables a reasonable set of hardening flags. The read of the room seems to be that the option would be useful. So here's a patch implementing that option. Currently, -fhardened enables: -D_FORTIFY_SOURCE=3 (or =2 for older glibcs) -D_GLIBCXX_ASSERTIONS -ftrivial-auto-var-init=zero -fPIE -pie -Wl,-z,relro,-z,now -fstack-protector-strong -fstack-clash-protection -fcf-protection=full (x86 GNU/Linux only) -fhardened will not override options that were specified on the command line (before or after -fhardened). For example, -D_FORTIFY_SOURCE=1 -fhardened means that _FORTIFY_SOURCE=1 will be used. Similarly, -fhardened -fstack-protector will not enable -fstack-protector-strong. Currently, -fhardened is only supported on GNU/Linux. In DW_AT_producer it is reflected only as -fhardened; it doesn't expand to anything. This patch provides -Whardened, enabled by default, which warns when -fhardened couldn't enable a particular option. I think most often it will say that _FORTIFY_SOURCE wasn't enabled because optimization were not enabled. gcc/c-family/ChangeLog: * c-opts.cc: Include "target.h". (c_finish_options): Maybe cpp_define _FORTIFY_SOURCE and _GLIBCXX_ASSERTIONS. gcc/ChangeLog: * common.opt (Whardened, fhardened): New options. * config.in: Regenerate. * config/bpf/bpf.cc: Include "opts.h". (bpf_option_override): If flag_stack_protector_set_by_fhardened_p, do not inform that -fstack-protector does not work. * config/i386/i386-options.cc (ix86_option_override_internal): When -fhardened, maybe enable -fcf-protection=full. * config/linux-protos.h (linux_fortify_source_default_level): Declare. * config/linux.cc (linux_fortify_source_default_level): New. * config/linux.h (TARGET_FORTIFY_SOURCE_DEFAULT_LEVEL): Redefine. * configure: Regenerate. * configure.ac: Check if the linker supports '-z now' and '-z relro'. Check if -fhardened is supported on $target_os. * doc/invoke.texi: Document -fhardened and -Whardened. * doc/tm.texi: Regenerate. * doc/tm.texi.in (TARGET_FORTIFY_SOURCE_DEFAULT_LEVEL): Add. * gcc.cc (driver_handle_option): Remember if any link options or -static were specified on the command line. (process_command): When -fhardened, maybe enable -pie and -Wl,-z,relro,-z,now. * opts.cc (flag_stack_protector_set_by_fhardened_p): New global. (finish_options): When -fhardened, enable -ftrivial-auto-var-init=zero and -fstack-protector-strong. (print_help_hardened): New. (print_help): Call it. * opts.h (flag_stack_protector_set_by_fhardened_p): Declare. * target.def (fortify_source_default_level): New target hook. * targhooks.cc (default_fortify_source_default_level): New. * targhooks.h (default_fortify_source_default_level): Declare. * toplev.cc (process_options): When -fhardened, enable -fstack-clash-protection. If flag_stack_protector_set_by_fhardened_p, do not warn that -fstack-protector not supported for this target. Don't enable -fhardened when !HAVE_FHARDENED_SUPPORT. gcc/testsuite/ChangeLog: * gcc.misc-tests/help.exp: Test -fhardened. * c-c++-common/fhardened-1.S: New test. * c-c++-common/fhardened-1.c: New test. * c-c++-common/fhardened-10.c: New test. * c-c++-common/fhardened-11.c: New test. * c-c++-common/fhardened-12.c: New test. * c-c++-common/fhardened-13.c: New test. * c-c++-common/fhardened-14.c: New test. * c-c++-common/fhardened-15.c: New test. * c-c++-common/fhardened-2.c: New test. * c-c++-common/fhardened-3.c: New test. * c-c++-common/fhardened-4.c: New test. * c-c++-common/fhardened-5.c: New test. * c-c++-common/fhardened-6.c: New test. * c-c++-common/fhardened-7.c: New test. * c-c++-common/fhardened-8.c: New test. * c-c++-common/fhardened-9.c: New test. * gcc.target/i386/cf_check-6.c: New test.
Diffstat (limited to 'gcc/gcc.cc')
-rw-r--r--gcc/gcc.cc48
1 files changed, 47 insertions, 1 deletions
diff --git a/gcc/gcc.cc b/gcc/gcc.cc
index 51120c1..9f21ad9 100644
--- a/gcc/gcc.cc
+++ b/gcc/gcc.cc
@@ -302,6 +302,13 @@ static size_t dumpdir_length = 0;
driver added to dumpdir after dumpbase or linker output name. */
static bool dumpdir_trailing_dash_added = false;
+/* True if -r, -shared, -pie, or -no-pie were specified on the command
+ line. */
+static bool any_link_options_p;
+
+/* True if -static was specified on the command line. */
+static bool static_p;
+
/* Basename of dump and aux outputs, computed from dumpbase (given or
derived from output name), to override input_basename in non-%w %b
et al. */
@@ -4605,10 +4612,20 @@ driver_handle_option (struct gcc_options *opts,
save_switch ("-o", 1, &arg, validated, true);
return true;
-#ifdef ENABLE_DEFAULT_PIE
case OPT_pie:
+#ifdef ENABLE_DEFAULT_PIE
/* -pie is turned on by default. */
+ validated = true;
#endif
+ case OPT_r:
+ case OPT_shared:
+ case OPT_no_pie:
+ any_link_options_p = true;
+ break;
+
+ case OPT_static:
+ static_p = true;
+ break;
case OPT_static_libgcc:
case OPT_shared_libgcc:
@@ -4984,6 +5001,35 @@ process_command (unsigned int decoded_options_count,
#endif
}
+ /* TODO: check if -static -pie works and maybe use it. */
+ if (flag_hardened)
+ {
+ if (!any_link_options_p && !static_p)
+ {
+#ifdef HAVE_LD_PIE
+ save_switch (LD_PIE_SPEC, 0, NULL, /*validated=*/true, /*known=*/false);
+#endif
+ /* These are passed straight down to collect2 so we have to break
+ it up like this. */
+ if (HAVE_LD_NOW_SUPPORT)
+ {
+ add_infile ("-z", "*");
+ add_infile ("now", "*");
+ }
+ if (HAVE_LD_RELRO_SUPPORT)
+ {
+ add_infile ("-z", "*");
+ add_infile ("relro", "*");
+ }
+ }
+ /* We can't use OPT_Whardened yet. Sigh. */
+ else if (warn_hardened)
+ warning_at (UNKNOWN_LOCATION, 0,
+ "linker hardening options not enabled by %<-fhardened%> "
+ "because other link options were specified on the command "
+ "line");
+ }
+
/* Handle -gtoggle as it would later in toplev.cc:process_options to
make the debug-level-gt spec function work as expected. */
if (flag_gtoggle)