From patchwork Fri Nov 3 22:51:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Marek Polacek X-Patchwork-Id: 1859185 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=LGKqSWG5; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4SMbbF6dgFz1yQs for ; Sat, 4 Nov 2023 09:51:48 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 6F2F03858C41 for ; Fri, 3 Nov 2023 22:51:46 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 8DDFA3858D28 for ; Fri, 3 Nov 2023 22:51:23 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 8DDFA3858D28 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 8DDFA3858D28 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699051888; cv=none; b=Pq4kerh9Bx4rdlamaowwJmtGzzWSl8XhH3ZXJu8jtPOsu6TBz7xFcPJq7U78HsobFdFHWRmCHli+eFBMzgKOFAzlbsvwwjUmp434aOZldAsQcrzo0kHpuD9mEPdJKO2yYVdqHMKap5g1Z92p/QD8nb05L3Hu0hOAwDzILUphJHg= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699051888; c=relaxed/simple; bh=HJXCxFwgKNVRdhYb0OBm76b7v9t/dRd4Q2IA3Ezd6BE=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=MwYjjPPXR7tdGc+IwFEwtG8pIHV1GbhZ6yVEeM76OC6bInH1GlGJ5l8LACjHWcN3naPhwfrexW767qSR0X31boBXNtFfOfFyHE2qHcThqfA3kJITajjB3jkaq1AMK/hkRxqJDZwolm2S3cjutbJjTZ9YoxvsXcI3gFgoqc/upPA= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1699051883; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=0nv74OETTjcIGQWyD1KTQPj6lypswqT2ouKPK6tduXE=; b=LGKqSWG5+tQa8K+u2Kup/9pf6iWf0dVZtGINp0dSchOalcRc5DJq2ZzMFGO8RiwLjJsBmi +dJdVQ26mc5EhkTHEgwnHBfV6krbtNcli/Kq3uNl7ZeFd6DXOOZoMG15CQ8lGqWXWapSRP XkfNZpBwr7NbcV/KZlmg9oCHy6C7vF4= Received: from mail-qv1-f71.google.com (mail-qv1-f71.google.com [209.85.219.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-259-WasbbNpmPbOAdUsrG0oocg-1; Fri, 03 Nov 2023 18:51:21 -0400 X-MC-Unique: WasbbNpmPbOAdUsrG0oocg-1 Received: by mail-qv1-f71.google.com with SMTP id 6a1803df08f44-670991f8b5cso56058656d6.1 for ; Fri, 03 Nov 2023 15:51:21 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699051881; x=1699656681; h=user-agent:in-reply-to:content-transfer-encoding :content-disposition:mime-version:references:message-id:subject:cc :to:from:date:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=0nv74OETTjcIGQWyD1KTQPj6lypswqT2ouKPK6tduXE=; b=lIsdV4itYKZZCspWQ3tOKBX0cycNRVeUvdfNQw3wSumNRfw8I6hAUQopGNcumxN7dC uW7ALmtQj448U2j5TR37qld942PS6isuewisOJVQF7bTDW8E/ds6MSh56rszeTlBmx+A 1cbPr5alGmQ1l3U2BP2Du0jCyelIpppjOvLUmHSOs/Cmys15Q1V/ZddgjAOmVefXjv+2 gvoOmvVX3FA8ZsRM30GD5kixs0B7xnzDuRxx13n9HvS0ScUu0tozJ4oRwv2fNLVMWJxt pAg7lxCLSOaf6SGyaUj/MqczXbCXetXwjcUrANzLzvLMupbxI0tJuRulcBwXcbchd+Mg 46Bw== X-Gm-Message-State: AOJu0Yze8DNpKqK9sxXL91v+B88NrqRiUX9N7lox0/4tlu1DAUV9TPUf ru/+syyN2Ss7d4wsa1Bqwl+PX/2MYzI8GsgPS7qKlGsoru7yIqbXX5SMgM56Pm4YaNWzdlC4lnz IbY5xLczupM6sgtBMNSjEPrtImw== X-Received: by 2002:a05:6214:1c8c:b0:65a:feb1:ec46 with SMTP id ib12-20020a0562141c8c00b0065afeb1ec46mr7061849qvb.6.1699051880075; Fri, 03 Nov 2023 15:51:20 -0700 (PDT) X-Google-Smtp-Source: AGHT+IH89bT6E/8N/pEqEd+OSG9NOYP1ERF4z5nDHtMrAYmj96cHsKb7FBWEo99VvfMw00xaBtgQZQ== X-Received: by 2002:a05:6214:1c8c:b0:65a:feb1:ec46 with SMTP id ib12-20020a0562141c8c00b0065afeb1ec46mr7061812qvb.6.1699051879257; Fri, 03 Nov 2023 15:51:19 -0700 (PDT) Received: from redhat.com (2603-7000-9500-34a5-0000-0000-0000-1db4.res6.spectrum.com. [2603:7000:9500:34a5::1db4]) by smtp.gmail.com with ESMTPSA id a12-20020a05620a124c00b0076db1caab16sm1123771qkl.22.2023.11.03.15.51.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 03 Nov 2023 15:51:18 -0700 (PDT) Date: Fri, 3 Nov 2023 18:51:16 -0400 From: Marek Polacek To: Richard Biener Cc: iain@sandoe.co.uk, GCC Patches Subject: [PATCH v4] gcc: Introduce -fhardened Message-ID: References: <8A3E5AA3-0785-4C2E-B75B-9388B703FFEA@gmail.com> MIME-Version: 1.0 In-Reply-To: <8A3E5AA3-0785-4C2E-B75B-9388B703FFEA@gmail.com> User-Agent: Mutt/2.2.9 (2022-11-12) X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-12.6 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org On Thu, Oct 26, 2023 at 05:55:56PM +0200, Richard Biener wrote: > > > > Am 24.10.2023 um 21:09 schrieb Marek Polacek : > > > > On Tue, Oct 24, 2023 at 09:22:25AM +0200, Richard Biener wrote: > >>> On Mon, Oct 23, 2023 at 9:26 PM Marek Polacek wrote: > >>> > >>> On Thu, Oct 19, 2023 at 02:24:11PM +0200, Richard Biener wrote: > >>>> Can you see how our > >>>> primary and secondary targets (+ host OS) behave here? > >>> > >>> That's very reasonable. I tried to build gcc on Compile Farm 119 (AIX) but > >>> that fails with: > >>> > >>> ar -X64 x ../ppc64/libgcc/libgcc_s.a shr.o > >>> ar: 0707-100 ../ppc64/libgcc/libgcc_s.a does not exist. > >>> make[2]: *** [/home/polacek/gcc/libgcc/config/rs6000/t-slibgcc-aix:98: all] Error 1 > >>> make[2]: Leaving directory '/home/polacek/x/trunk/powerpc-ibm-aix7.3.1.0/libgcc' > >>> > >>> and I tried Darwin (104) and that fails with > >>> > >>> *** Configuration aarch64-apple-darwin21.6.0 not supported > >>> > >>> Is anyone else able to build gcc on those machines, or test the attached > >>> patch? > >>> > >>>> I think the > >>>> documentation should elaborate a bit on expectations for non-Linux/GNU > >>>> targets, specifically I think the default configuration for a target should > >>>> with -fhardened _not_ have any -Whardened diagnostics. Maybe we can > >>>> have a testcase for this? > >>> > >>> Sorry, I'm not sure how to test that. I suppose if -fhardened enables > >>> something not supported on those systems, and it's something for which > >>> we have a configure test, then we shouldn't warn. This is already the > >>> case for -pie, -z relro, and -z now. > >> > >> I was thinking of > >> > >> /* { dg-do compile } */ > >> /* { dg-additional-options "-fhardened -Whardened" } */ > >> > >> int main () {} > >> > >> and excess errors should catch "misconfigurations"? > > > > I see. fhardened-3.c is basically just like this (-Whardened is on by default). > > > >>> Should the docs say something like the following for features without > >>> configure checks? > >>> > >>> @option{-fhardened} can, on certain systems, attempt to enable features > >>> not supported on that particular system. In that case, it's possible to > >>> prevent the warning using the @option{-Wno-hardened} option. > >> > >> Yeah, but ideally > >> > >> @option{-fhardened} can, on certain systems, not enable features not > >> available on those systems and @option{-Whardened} will not diagnose > >> those as missing. > >> > >> But I understand it doesn't work like that? > > > > Right. It will not diagnose missing features if they have a configure > > check, otherwise it will. And I don't know if we want a configure check > > for every feature. Maybe we can add them in the future if the current > > patch turns out to be problematical in practice? > > Maybe we can have a switch on known target triples and statically configure based > On that, eventually even not support -fhardened for targets not listed. That’s certainly easier than detecting the target system features (think of cross compilers) You mean like the following? The only difference is the addition of HAVE_FHARDENED_SUPPORT and updating the tests to only run on gnu/linux targets. If other OSs want to use -fhardened, they need to update the configure test. Thanks, Bootstrapped/regtested on x86_64-pc-linux-gnu and powerpc64le-unknown-linux-gnu. -- >8 -- In 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 (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. * 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. * 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. * 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. --- gcc/c-family/c-opts.cc | 42 +++++++++++++ gcc/common.opt | 8 +++ gcc/config.in | 18 ++++++ gcc/config/bpf/bpf.cc | 8 ++- gcc/config/i386/i386-options.cc | 17 ++++- gcc/configure | 72 +++++++++++++++++++++- gcc/configure.ac | 57 ++++++++++++++++- gcc/doc/invoke.texi | 49 ++++++++++++++- gcc/gcc.cc | 48 ++++++++++++++- gcc/opts.cc | 67 +++++++++++++++++++- gcc/opts.h | 1 + gcc/testsuite/c-c++-common/fhardened-1.S | 6 ++ gcc/testsuite/c-c++-common/fhardened-1.c | 14 +++++ gcc/testsuite/c-c++-common/fhardened-10.c | 12 ++++ gcc/testsuite/c-c++-common/fhardened-11.c | 10 +++ gcc/testsuite/c-c++-common/fhardened-12.c | 11 ++++ gcc/testsuite/c-c++-common/fhardened-13.c | 6 ++ gcc/testsuite/c-c++-common/fhardened-14.c | 6 ++ gcc/testsuite/c-c++-common/fhardened-15.c | 5 ++ gcc/testsuite/c-c++-common/fhardened-2.c | 12 ++++ gcc/testsuite/c-c++-common/fhardened-3.c | 14 +++++ gcc/testsuite/c-c++-common/fhardened-4.c | 4 ++ gcc/testsuite/c-c++-common/fhardened-5.c | 11 ++++ gcc/testsuite/c-c++-common/fhardened-6.c | 12 ++++ gcc/testsuite/c-c++-common/fhardened-7.c | 7 +++ gcc/testsuite/c-c++-common/fhardened-8.c | 7 +++ gcc/testsuite/c-c++-common/fhardened-9.c | 9 +++ gcc/testsuite/gcc.misc-tests/help.exp | 2 + gcc/testsuite/gcc.target/i386/cf_check-6.c | 12 ++++ gcc/toplev.cc | 25 +++++++- 30 files changed, 556 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/fhardened-1.S create mode 100644 gcc/testsuite/c-c++-common/fhardened-1.c create mode 100644 gcc/testsuite/c-c++-common/fhardened-10.c create mode 100644 gcc/testsuite/c-c++-common/fhardened-11.c create mode 100644 gcc/testsuite/c-c++-common/fhardened-12.c create mode 100644 gcc/testsuite/c-c++-common/fhardened-13.c create mode 100644 gcc/testsuite/c-c++-common/fhardened-14.c create mode 100644 gcc/testsuite/c-c++-common/fhardened-15.c create mode 100644 gcc/testsuite/c-c++-common/fhardened-2.c create mode 100644 gcc/testsuite/c-c++-common/fhardened-3.c create mode 100644 gcc/testsuite/c-c++-common/fhardened-4.c create mode 100644 gcc/testsuite/c-c++-common/fhardened-5.c create mode 100644 gcc/testsuite/c-c++-common/fhardened-6.c create mode 100644 gcc/testsuite/c-c++-common/fhardened-7.c create mode 100644 gcc/testsuite/c-c++-common/fhardened-8.c create mode 100644 gcc/testsuite/c-c++-common/fhardened-9.c create mode 100644 gcc/testsuite/gcc.target/i386/cf_check-6.c base-commit: ae8abcb81ed81456c0fe5ff8e0c060c9fb9c82d7 diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc index e9f7e6d424d..26f009f2da5 100644 --- a/gcc/c-family/c-opts.cc +++ b/gcc/c-family/c-opts.cc @@ -1556,6 +1556,9 @@ c_finish_options (void) cb_file_change (parse_in, cmd_map); linemap_line_start (line_table, 0, 1); + bool fortify_seen_p = false; + bool cxx_assert_seen_p = false; + /* All command line defines must have the same location. */ cpp_force_token_locations (parse_in, line_table->highest_line); for (size_t i = 0; i < deferred_count; i++) @@ -1573,6 +1576,45 @@ c_finish_options (void) else cpp_assert (parse_in, opt->arg); } + + if (UNLIKELY (flag_hardened) + && (opt->code == OPT_D || opt->code == OPT_U)) + { + if (!fortify_seen_p) + fortify_seen_p + = (!strncmp (opt->arg, "_FORTIFY_SOURCE", 15) + && (opt->arg[15] == '\0' || opt->arg[15] == '=')); + if (!cxx_assert_seen_p) + cxx_assert_seen_p + = (!strncmp (opt->arg, "_GLIBCXX_ASSERTIONS", 19) + && (opt->arg[19] == '\0' || opt->arg[19] == '=')); + } + } + + if (flag_hardened) + { + if (!fortify_seen_p && optimize > 0) + { + if (TARGET_GLIBC_MAJOR == 2 && TARGET_GLIBC_MINOR >= 35) + cpp_define (parse_in, "_FORTIFY_SOURCE=3"); + else + cpp_define (parse_in, "_FORTIFY_SOURCE=2"); + } + else if (optimize == 0) + warning_at (UNKNOWN_LOCATION, OPT_Whardened, + "%<_FORTIFY_SOURCE%> is not enabled by %<-fhardened%> " + "because optimizations are turned off"); + else + warning_at (UNKNOWN_LOCATION, OPT_Whardened, + "%<_FORTIFY_SOURCE%> is not enabled by %<-fhardened%> " + "because it was specified in %<-D%> or %<-U%>"); + if (!cxx_assert_seen_p) + cpp_define (parse_in, "_GLIBCXX_ASSERTIONS"); + else + warning_at (UNKNOWN_LOCATION, OPT_Whardened, + "%<_GLIBCXX_ASSERTIONS%> is not enabled by " + "%<-fhardened%> because it was specified in %<-D%> " + "or %<-U%>"); } cpp_stop_forcing_token_locations (parse_in); diff --git a/gcc/common.opt b/gcc/common.opt index 1cf3bdd3b51..48a15f077ef 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -634,6 +634,10 @@ Wfree-nonheap-object Common Var(warn_free_nonheap_object) Init(1) Warning Warn when attempting to free a non-heap object. +Whardened +Common Var(warn_hardened) Init(1) Warning +Warn when -fhardened did not enable an option from its set. + Whsa Common Ignore Warning Does nothing. Preserved for backward compatibility. @@ -1823,6 +1827,10 @@ fguess-branch-probability Common Var(flag_guess_branch_prob) Optimization Enable guessing of branch probabilities. +fhardened +Common Driver Var(flag_hardened) +Enable various security-relevant flags. + fharden-compares Common Var(flag_harden_compares) Optimization Harden conditionals not used in branches, checking reversed conditions. diff --git a/gcc/config.in b/gcc/config.in index 03faee1c6ac..97b483ddd97 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -1293,6 +1293,12 @@ #endif +/* Define 0/1 if -fhardened is supported */ +#ifndef USED_FOR_TARGET +#undef HAVE_FHARDENED_SUPPORT +#endif + + /* Define to 1 if you have the `fileno_unlocked' function. */ #ifndef USED_FOR_TARGET #undef HAVE_FILENO_UNLOCKED @@ -1695,6 +1701,12 @@ #endif +/* Define 0/1 if your linker supports -z now */ +#ifndef USED_FOR_TARGET +#undef HAVE_LD_NOW_SUPPORT +#endif + + /* Define if your PowerPC64 linker only needs function descriptor syms. */ #ifndef USED_FOR_TARGET #undef HAVE_LD_NO_DOT_SYMS @@ -1738,6 +1750,12 @@ #endif +/* Define 0/1 if your linker supports -z relro */ +#ifndef USED_FOR_TARGET +#undef HAVE_LD_RELRO_SUPPORT +#endif + + /* Define if your linker links a mix of read-only and read-write sections into a read-write section. */ #ifndef USED_FOR_TARGET diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc index 63637ece78e..804f6f3304a 100644 --- a/gcc/config/bpf/bpf.cc +++ b/gcc/config/bpf/bpf.cc @@ -70,6 +70,7 @@ along with GCC; see the file COPYING3. If not see #include "gimplify-me.h" #include "core-builtins.h" +#include "opts.h" /* Per-function machine data. */ struct GTY(()) machine_function @@ -250,9 +251,10 @@ bpf_option_override (void) /* Disable -fstack-protector as it is not supported in BPF. */ if (flag_stack_protect) { - inform (input_location, - "%<-fstack-protector%> does not work " - "on this architecture"); + if (!flag_stack_protector_set_by_fhardened_p) + inform (input_location, + "%<-fstack-protector%> does not work " + "on this architecture"); flag_stack_protect = 0; } diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc index df7d24352d1..76adba672b9 100644 --- a/gcc/config/i386/i386-options.cc +++ b/gcc/config/i386/i386-options.cc @@ -3072,10 +3072,25 @@ ix86_option_override_internal (bool main_args_p, = build_target_option_node (opts, opts_set); } + const bool cf_okay_p = (TARGET_64BIT || TARGET_CMOV); + /* When -fhardened, enable -fcf-protection=full, but only when it's + compatible with this target, and when it wasn't already specified + on the command line. */ + if (opts->x_flag_hardened && cf_okay_p) + { + if (opts->x_flag_cf_protection == CF_NONE) + opts->x_flag_cf_protection = CF_FULL; + else if (opts->x_flag_cf_protection != CF_FULL) + warning_at (UNKNOWN_LOCATION, OPT_Whardened, + "%<-fcf-protection=full%> is not enabled by " + "%<-fhardened%> because it was specified on the command " + "line"); + } + if (opts->x_flag_cf_protection != CF_NONE) { if ((opts->x_flag_cf_protection & CF_BRANCH) == CF_BRANCH - && !TARGET_64BIT && !TARGET_CMOV) + && !cf_okay_p) error ("%<-fcf-protection%> is not compatible with this target"); opts->x_flag_cf_protection diff --git a/gcc/configure b/gcc/configure index d4ad988000f..e701f6be063 100755 --- a/gcc/configure +++ b/gcc/configure @@ -20000,7 +20000,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 19995 "configure" +#line 20003 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -20106,7 +20106,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 20101 "configure" +#line 20109 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -32903,7 +32903,7 @@ if test x"$ld_is_gold" = xno; then ld_bndplt_support=yes fi elif test x$gcc_cv_ld != x; then - # Check if linker supports -a bndplt option + # Check if linker supports -z bndplt option if $gcc_cv_ld --help 2>&1 | grep -- '-z bndplt' > /dev/null; then ld_bndplt_support=yes fi @@ -33032,6 +33032,72 @@ $as_echo "#define ENABLE_S390_EXCESS_FLOAT_PRECISION 1" >>confdefs.h ;; esac +# Check if the linker supports '-z now' +ld_now_support=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker -z now option" >&5 +$as_echo_n "checking linker -z now option... " >&6; } +if test x"$ld_is_gold" = xyes; then + ld_now_support=yes +elif test $in_tree_ld = yes ; then + if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 14 -o "$gcc_cv_gld_major_version" -gt 2; then + ld_now_support=yes + fi +elif test x$gcc_cv_ld != x; then + # Check if linker supports -z now + if $gcc_cv_ld --help 2>&1 | grep -- '-z now' > /dev/null; then + ld_now_support=yes + fi +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_LD_NOW_SUPPORT `if test x"$ld_now_support" = xyes; then echo 1; else echo 0; fi` +_ACEOF + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_now_support" >&5 +$as_echo "$ld_now_support" >&6; } + +# Check if the linker supports '-z relro' +ld_relro_support=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker -z relro option" >&5 +$as_echo_n "checking linker -z relro option... " >&6; } +if test x"$ld_is_gold" = xyes; then + ld_relro_support=yes +elif test $in_tree_ld = yes ; then + if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 15 -o "$gcc_cv_gld_major_version" -gt 2; then + ld_relro_support=yes + fi +elif test x$gcc_cv_ld != x; then + # Check if linker supports -z relro + if $gcc_cv_ld --help 2>&1 | grep -- '-z relro' > /dev/null; then + ld_relro_support=yes + fi +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_LD_RELRO_SUPPORT `if test x"$ld_relro_support" = xyes; then echo 1; else echo 0; fi` +_ACEOF + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_relro_support" >&5 +$as_echo "$ld_relro_support" >&6; } + +case $target_os in +linux* | gnu*) + # -fhardened is only supported on GNU/Linux. + fhardened_support=yes + ;; +*) + fhardened_support=no + ;; +esac + + +cat >>confdefs.h <<_ACEOF +#define HAVE_FHARDENED_SUPPORT `if test x"$fhardened_support" = xyes; then echo 1; else echo 0; fi` +_ACEOF + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $fhardened_support" >&5 +$as_echo "$fhardened_support" >&6; } + # Configure the subdirectories # AC_CONFIG_SUBDIRS($subdirs) diff --git a/gcc/configure.ac b/gcc/configure.ac index dc8cb6a33de..feb81b114b4 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -7714,7 +7714,7 @@ if test x"$ld_is_gold" = xno; then ld_bndplt_support=yes fi elif test x$gcc_cv_ld != x; then - # Check if linker supports -a bndplt option + # Check if linker supports -z bndplt option if $gcc_cv_ld --help 2>&1 | grep -- '-z bndplt' > /dev/null; then ld_bndplt_support=yes fi @@ -7815,6 +7815,61 @@ standards-compatible mode on s390 targets.]) ;; esac +# Check if the linker supports '-z now' +ld_now_support=no +AC_MSG_CHECKING(linker -z now option) +if test x"$ld_is_gold" = xyes; then + ld_now_support=yes +elif test $in_tree_ld = yes ; then + if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 14 -o "$gcc_cv_gld_major_version" -gt 2; then + ld_now_support=yes + fi +elif test x$gcc_cv_ld != x; then + # Check if linker supports -z now + if $gcc_cv_ld --help 2>&1 | grep -- '-z now' > /dev/null; then + ld_now_support=yes + fi +fi +AC_DEFINE_UNQUOTED(HAVE_LD_NOW_SUPPORT, + [`if test x"$ld_now_support" = xyes; then echo 1; else echo 0; fi`], + [Define 0/1 if your linker supports -z now]) +AC_MSG_RESULT($ld_now_support) + +# Check if the linker supports '-z relro' +ld_relro_support=no +AC_MSG_CHECKING(linker -z relro option) +if test x"$ld_is_gold" = xyes; then + ld_relro_support=yes +elif test $in_tree_ld = yes ; then + if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 15 -o "$gcc_cv_gld_major_version" -gt 2; then + ld_relro_support=yes + fi +elif test x$gcc_cv_ld != x; then + # Check if linker supports -z relro + if $gcc_cv_ld --help 2>&1 | grep -- '-z relro' > /dev/null; then + ld_relro_support=yes + fi +fi +AC_DEFINE_UNQUOTED(HAVE_LD_RELRO_SUPPORT, + [`if test x"$ld_relro_support" = xyes; then echo 1; else echo 0; fi`], + [Define 0/1 if your linker supports -z relro]) +AC_MSG_RESULT($ld_relro_support) + +case $target_os in +linux* | gnu*) + # -fhardened is only supported on GNU/Linux. + fhardened_support=yes + ;; +*) + fhardened_support=no + ;; +esac + +AC_DEFINE_UNQUOTED(HAVE_FHARDENED_SUPPORT, + [`if test x"$fhardened_support" = xyes; then echo 1; else echo 0; fi`], + [Define 0/1 if -fhardened is supported]) +AC_MSG_RESULT($fhardened_support) + # Configure the subdirectories # AC_CONFIG_SUBDIRS($subdirs) diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 6e776a0faa1..7f145468950 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -366,7 +366,7 @@ Objective-C and Objective-C++ Dialects}. -Wformat-y2k -Wframe-address -Wframe-larger-than=@var{byte-size} -Wno-free-nonheap-object -Wno-if-not-aligned -Wno-ignored-attributes --Wignored-qualifiers -Wno-incompatible-pointer-types +-Wignored-qualifiers -Wno-incompatible-pointer-types -Whardened -Wimplicit -Wimplicit-fallthrough -Wimplicit-fallthrough=@var{n} -Wno-implicit-function-declaration -Wno-implicit-int -Winfinite-recursion @@ -641,7 +641,7 @@ Objective-C and Objective-C++ Dialects}. -fasan-shadow-offset=@var{number} -fsanitize-sections=@var{s1},@var{s2},... -fsanitize-undefined-trap-on-error -fbounds-check -fcf-protection=@r{[}full@r{|}branch@r{|}return@r{|}none@r{|}check@r{]} --fharden-compares -fharden-conditional-branches +-fharden-compares -fharden-conditional-branches -fhardened -fharden-control-flow-redundancy -fhardcfr-skip-leaf -fhardcfr-check-exceptions -fhardcfr-check-returning-calls -fhardcfr-check-noreturn-calls=@r{[}always@r{|}no-xthrow@r{|}nothrow@r{|}never@r{]} @@ -6860,6 +6860,18 @@ This warning is upgraded to an error by @option{-pedantic-errors}. Same as @option{-Wimplicit-int} and @option{-Wimplicit-function-declaration}. This warning is enabled by @option{-Wall}. +@opindex Whardened +@opindex Wno-hardened +@item -Whardened +Warn when @option{-fhardened} did not enable an option from its set (for +which see @option{-fhardened}). For instance, using @option{-fhardened} +and @option{-fstack-protector} at the same time on the command line causes +@option{-Whardened} to warn because @option{-fstack-protector-strong} is +not enabled by @option{-fhardened}. + +This warning is enabled by default and has effect only when @option{-fhardened} +is enabled. + @opindex Wimplicit-fallthrough @opindex Wno-implicit-fallthrough @item -Wimplicit-fallthrough @@ -17552,6 +17564,39 @@ made @option{no-xthrow} the default setting for this option: it excludes from the @code{noreturn} treatment only internal functions used to (re)raise exceptions, that are not affected by these optimizations. +@opindex fhardened +@item -fhardened +Enable a set of flags for C and C++ that improve the security of the +generated code without affecting its ABI. The precise flags enabled +may change between major releases of GCC, but are currently: + +@c Keep this in sync with print_help_hardened! +@gccoptlist{ +-D_FORTIFY_SOURCE=3 +-D_GLIBCXX_ASSERTIONS +-ftrivial-auto-var-init=zero +-fPIE -pie -Wl,-z,relro,-z,now +-fstack-protector-strong +-fstack-clash-protection +-fcf-protection=full @r{(x86 GNU/Linux only)} +} + +The list of options enabled by @option{-fhardened} can be generated using +the @option{--help=hardened} option. + +When the system glibc is older than 2.35, @option{-D_FORTIFY_SOURCE=2} +is used instead. + +This option is intended to be used in production builds, not merely +in debug builds. + +Currently, @option{-fhardened} is only supported on GNU/Linux targets. + +@option{-fhardened} only enables a particular option if it wasn't +already specified anywhere on the command line. For instance, +@option{-fhardened} @option{-fstack-protector} will only enable +@option{-fstack-protector}, but not @option{-fstack-protector-strong}. + @opindex fstack-protector @item -fstack-protector Emit extra code to check for buffer overflows, such as stack smashing diff --git a/gcc/gcc.cc b/gcc/gcc.cc index 884284e66b4..a7e5774dcfa 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. */ @@ -4606,10 +4613,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: @@ -4985,6 +5002,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) diff --git a/gcc/opts.cc b/gcc/opts.cc index f54cf8305ca..787f3f47db3 100644 --- a/gcc/opts.cc +++ b/gcc/opts.cc @@ -43,6 +43,10 @@ along with GCC; see the file COPYING3. If not see /* Set by -fcanon-prefix-map. */ bool flag_canon_prefix_map; +/* Set by finish_options when flag_stack_protector was set only because of + -fhardened. Yuck. */ +bool flag_stack_protector_set_by_fhardened_p; + static void set_Wstrict_aliasing (struct gcc_options *opts, int onoff); /* Names of fundamental debug info formats indexed by enum @@ -1093,6 +1097,17 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set, opts->x_flag_section_anchors = 0; } + if (opts->x_flag_hardened) + { + if (!opts_set->x_flag_auto_var_init) + opts->x_flag_auto_var_init = AUTO_INIT_ZERO; + else if (opts->x_flag_auto_var_init != AUTO_INIT_ZERO) + warning_at (loc, OPT_Whardened, + "%<-ftrivial-auto-var-init=zero%> is not enabled by " + "%<-fhardened%> because it was specified on the command " + "line"); + } + if (!opts->x_flag_opts_finished) { /* We initialize opts->x_flag_pie to -1 so that targets can set a @@ -1102,7 +1117,8 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set, /* We initialize opts->x_flag_pic to -1 so that we can tell if -fpic, -fPIC, -fno-pic or -fno-PIC is used. */ if (opts->x_flag_pic == -1) - opts->x_flag_pie = DEFAULT_FLAG_PIE; + opts->x_flag_pie = (opts->x_flag_hardened + ? /*-fPIE*/ 2 : DEFAULT_FLAG_PIE); else opts->x_flag_pie = 0; } @@ -1117,9 +1133,29 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set, } /* We initialize opts->x_flag_stack_protect to -1 so that targets - can set a default value. */ + can set a default value. With --enable-default-ssp or -fhardened + the default is -fstack-protector-strong. */ if (opts->x_flag_stack_protect == -1) - opts->x_flag_stack_protect = DEFAULT_FLAG_SSP; + { + /* This should check FRAME_GROWS_DOWNWARD, but on some targets it's + defined in such a way that it uses flag_stack_protect which can't + be used here. Moreover, some targets like BPF don't support + -fstack-protector at all but we don't know that here. So remember + that flag_stack_protect was set at the behest of -fhardened. */ + if (opts->x_flag_hardened) + { + opts->x_flag_stack_protect = SPCT_FLAG_STRONG; + flag_stack_protector_set_by_fhardened_p = true; + } + else + opts->x_flag_stack_protect = DEFAULT_FLAG_SSP; + } + else if (opts->x_flag_hardened + && opts->x_flag_stack_protect != SPCT_FLAG_STRONG) + warning_at (UNKNOWN_LOCATION, OPT_Whardened, + "%<-fstack-protector-strong%> is not enabled by " + "%<-fhardened%> because it was specified on the command " + "line"); if (opts->x_optimize == 0) { @@ -2461,6 +2497,29 @@ parse_and_check_patch_area (const char *arg, bool report_error, free (patch_area_arg); } +/* Print options enabled by -fhardened. Keep this in sync with the manual! */ + +static void +print_help_hardened () +{ + printf ("%s\n", "The following options are enabled by -fhardened:"); + printf (" %s=%d\n", "-D_FORTIFY_SOURCE", + (TARGET_GLIBC_MAJOR == 2 && TARGET_GLIBC_MINOR >= 35) ? 3 : 2); + printf (" %s\n", "-D_GLIBCXX_ASSERTIONS"); + printf (" %s\n", "-ftrivial-auto-var-init=zero"); +#ifdef HAVE_LD_PIE + printf (" %s %s\n", "-fPIE", "-pie"); +#endif + if (HAVE_LD_NOW_SUPPORT) + printf (" %s\n", "-Wl,-z,now"); + if (HAVE_LD_RELRO_SUPPORT) + printf (" %s\n", "-Wl,-z,relro"); + printf (" %s\n", "-fstack-protector-strong"); + printf (" %s\n", "-fstack-clash-protection"); + printf (" %s\n", "-fcf-protection=full"); + putchar ('\n'); +} + /* Print help when OPT__help_ is set. */ void @@ -2576,6 +2635,8 @@ print_help (struct gcc_options *opts, unsigned int lang_mask, } else if (lang_flag != 0) *pflags |= lang_flag; + else if (strncasecmp (a, "hardened", len) == 0) + print_help_hardened (); else warning (0, "unrecognized argument to %<--help=%> option: %q.*s", diff --git a/gcc/opts.h b/gcc/opts.h index 00f377f9ca7..d89c5de8114 100644 --- a/gcc/opts.h +++ b/gcc/opts.h @@ -344,6 +344,7 @@ struct cl_option_handlers /* Hold command-line options associated with stack limitation. */ extern const char *opt_fstack_limit_symbol_arg; extern int opt_fstack_limit_register_no; +extern bool flag_stack_protector_set_by_fhardened_p; /* Input file names. */ diff --git a/gcc/testsuite/c-c++-common/fhardened-1.S b/gcc/testsuite/c-c++-common/fhardened-1.S new file mode 100644 index 00000000000..9d0a5772d9e --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-1.S @@ -0,0 +1,6 @@ +/* { dg-do preprocess { target { { *-*-linux* *-*-gnu* } && pie } } } */ +/* { dg-options "-fhardened -O" } */ + +#if __PIE__ != 2 +# error "-fPIE not enabled" +#endif diff --git a/gcc/testsuite/c-c++-common/fhardened-1.c b/gcc/testsuite/c-c++-common/fhardened-1.c new file mode 100644 index 00000000000..7e6740655fe --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-1.c @@ -0,0 +1,14 @@ +/* { dg-do compile { target *-*-linux* *-*-gnu* } } */ +/* { dg-options "-fhardened -O" } */ + +#ifndef __SSP_STRONG__ +# error "-fstack-protector-strong not enabled" +#endif + +#if _FORTIFY_SOURCE < 2 +# error "_FORTIFY_SOURCE not enabled" +#endif + +#ifndef _GLIBCXX_ASSERTIONS +# error "_GLIBCXX_ASSERTIONS not enabled" +#endif diff --git a/gcc/testsuite/c-c++-common/fhardened-10.c b/gcc/testsuite/c-c++-common/fhardened-10.c new file mode 100644 index 00000000000..badebc56440 --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-10.c @@ -0,0 +1,12 @@ +/* { dg-do compile { target *-*-linux* *-*-gnu* } } */ +/* { dg-options "-fhardened -D_FORTIFY_SOURCE=1" } */ + +#if _FORTIFY_SOURCE != 1 +# error "_FORTIFY_SOURCE != 1" +#endif + +#ifndef _GLIBCXX_ASSERTIONS +# error "_GLIBCXX_ASSERTIONS disabled when it should not be" +#endif + +/* { dg-warning "._FORTIFY_SOURCE. is not enabled" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/c-c++-common/fhardened-11.c b/gcc/testsuite/c-c++-common/fhardened-11.c new file mode 100644 index 00000000000..d1a973d177a --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-11.c @@ -0,0 +1,10 @@ +/* { dg-do compile { target *-*-linux* *-*-gnu* } } */ +/* { dg-options "-fhardened -O -D_FORTIFY_SOURCE_ -D_GLIBCXX_ASSERTIONS_" } */ + +#ifndef _FORTIFY_SOURCE +# error "_FORTIFY_SOURCE disabled when it should not be" +#endif + +#ifndef _GLIBCXX_ASSERTIONS +# error "_GLIBCXX_ASSERTIONS disabled when it should not be" +#endif diff --git a/gcc/testsuite/c-c++-common/fhardened-12.c b/gcc/testsuite/c-c++-common/fhardened-12.c new file mode 100644 index 00000000000..eb128f61ba3 --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-12.c @@ -0,0 +1,11 @@ +/* { dg-do compile { target *-*-linux* *-*-gnu* } } */ +/* { dg-options "-fhardened -O -fdump-tree-gimple" } */ + +int +foo () +{ + int i; + return i; +} + +/* { dg-final { scan-tree-dump ".DEFERRED_INIT" "gimple" } } */ diff --git a/gcc/testsuite/c-c++-common/fhardened-13.c b/gcc/testsuite/c-c++-common/fhardened-13.c new file mode 100644 index 00000000000..8722e6d4b1a --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-13.c @@ -0,0 +1,6 @@ +/* { dg-do compile { target { { *-*-linux* *-*-gnu* } && pie } } } */ +/* { dg-options "-fhardened -O" } */ + +#if __PIE__ != 2 +# error "-fPIE not enabled" +#endif diff --git a/gcc/testsuite/c-c++-common/fhardened-14.c b/gcc/testsuite/c-c++-common/fhardened-14.c new file mode 100644 index 00000000000..04d6c8ff954 --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-14.c @@ -0,0 +1,6 @@ +/* { dg-do compile { target { { *-*-linux* *-*-gnu* } && pie } } } */ +/* { dg-options "-fhardened -O -fno-PIE" } */ + +#ifdef __PIE__ +# error "PIE enabled when it should not be" +#endif diff --git a/gcc/testsuite/c-c++-common/fhardened-15.c b/gcc/testsuite/c-c++-common/fhardened-15.c new file mode 100644 index 00000000000..86dc5220159 --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-15.c @@ -0,0 +1,5 @@ +/* { dg-do compile { target *-*-linux* *-*-gnu* } } */ +/* { dg-require-stack-check "specific" } */ +/* { dg-options "-fhardened -O -fstack-check" } */ + +/* { dg-warning ".-fstack-clash-protection. is not enabled by .-fhardened. because .-fstack-check. was specified" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/c-c++-common/fhardened-2.c b/gcc/testsuite/c-c++-common/fhardened-2.c new file mode 100644 index 00000000000..280ff96eb15 --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-2.c @@ -0,0 +1,12 @@ +/* { dg-do compile { target *-*-linux* *-*-gnu* } } */ +/* { dg-options "-fhardened -fstack-protector" } */ + +#ifdef __SSP_STRONG__ +# error "-fstack-protector-strong enabled when it should not be" +#endif +#ifndef __SSP__ +# error "-fstack-protector not enabled" +#endif + +/* { dg-warning ".-fstack-protector-strong. is not enabled" "" { target *-*-* } 0 } */ +/* { dg-warning "._FORTIFY_SOURCE. is not enabled" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/c-c++-common/fhardened-3.c b/gcc/testsuite/c-c++-common/fhardened-3.c new file mode 100644 index 00000000000..f2306ca5d33 --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-3.c @@ -0,0 +1,14 @@ +/* { dg-do compile { target *-*-linux* *-*-gnu* } } */ +/* { dg-options "-fhardened -O0" } */ +/* Test that we don't get any diagnostic coming from libc headers. */ + +#include + +/* The most useful C program known to man. */ + +int +main () +{ +} + +/* { dg-warning "._FORTIFY_SOURCE. is not enabled" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/c-c++-common/fhardened-4.c b/gcc/testsuite/c-c++-common/fhardened-4.c new file mode 100644 index 00000000000..312fabb95a5 --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-4.c @@ -0,0 +1,4 @@ +/* { dg-do compile { target *-*-linux* *-*-gnu* } } */ +/* { dg-options "-fhardened -O0 -Wno-hardened" } */ + +/* { dg-bogus "._FORTIFY_SOURCE. is not enabled" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/c-c++-common/fhardened-5.c b/gcc/testsuite/c-c++-common/fhardened-5.c new file mode 100644 index 00000000000..eb128f61ba3 --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-5.c @@ -0,0 +1,11 @@ +/* { dg-do compile { target *-*-linux* *-*-gnu* } } */ +/* { dg-options "-fhardened -O -fdump-tree-gimple" } */ + +int +foo () +{ + int i; + return i; +} + +/* { dg-final { scan-tree-dump ".DEFERRED_INIT" "gimple" } } */ diff --git a/gcc/testsuite/c-c++-common/fhardened-6.c b/gcc/testsuite/c-c++-common/fhardened-6.c new file mode 100644 index 00000000000..d3cb7c8b353 --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-6.c @@ -0,0 +1,12 @@ +/* { dg-do compile { target *-*-linux* *-*-gnu* } } */ +/* { dg-options "-fhardened -O -ftrivial-auto-var-init=uninitialized -fdump-tree-gimple" } */ + +int +foo () +{ + int i; + return i; +} + +/* { dg-final { scan-tree-dump-not ".DEFERRED_INIT" "gimple" } } */ +/* { dg-warning ".-ftrivial-auto-var-init=zero. is not enabled" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/c-c++-common/fhardened-7.c b/gcc/testsuite/c-c++-common/fhardened-7.c new file mode 100644 index 00000000000..b47bf43f360 --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-7.c @@ -0,0 +1,7 @@ +/* { dg-do compile { target { { *-*-linux* *-*-gnu* } && pie } } } */ +/* { dg-options "-fhardened -O -fpie" } */ + +/* -fpie takes precedence over -fhardened */ +#if __PIE__ != 1 +# error "__PIE__ != 1" +#endif diff --git a/gcc/testsuite/c-c++-common/fhardened-8.c b/gcc/testsuite/c-c++-common/fhardened-8.c new file mode 100644 index 00000000000..85c9ad9103f --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-8.c @@ -0,0 +1,7 @@ +/* { dg-do compile { target { { *-*-linux* *-*-gnu* } && pie } } } */ +/* { dg-options "-fhardened -O -fPIC" } */ + +/* -fPIC takes precedence over -fhardened */ +#ifdef __PIE__ +# error "PIE enabled when it should not be" +#endif diff --git a/gcc/testsuite/c-c++-common/fhardened-9.c b/gcc/testsuite/c-c++-common/fhardened-9.c new file mode 100644 index 00000000000..4e4131f0bdd --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-9.c @@ -0,0 +1,9 @@ +/* { dg-do compile { target *-*-linux* *-*-gnu* } } */ +/* { dg-options "-fhardened -U_FORTIFY_SOURCE -U_GLIBCXX_ASSERTIONS" } */ + +#if defined(_FORTIFY_SOURCE) || defined(_GLIBCXX_ASSERTIONS) +# error "hardening enabled when it should not be" +#endif + +/* { dg-warning "._FORTIFY_SOURCE. is not enabled" "" { target *-*-* } 0 } */ +/* { dg-warning "._GLIBCXX_ASSERTIONS. is not enabled" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/gcc.misc-tests/help.exp b/gcc/testsuite/gcc.misc-tests/help.exp index 52b9cb0ab90..15d618a2528 100644 --- a/gcc/testsuite/gcc.misc-tests/help.exp +++ b/gcc/testsuite/gcc.misc-tests/help.exp @@ -151,6 +151,8 @@ foreach cls { "ada" "c" "c++" "d" "fortran" "go" \ # Listing only excludes gives empty results. check_for_options c "--help=^joined,^separate" "" "" "" +check_for_options c "--help=hardened" "The following options are enabled by -fhardened" "" "" + if [ info exists prev_columns ] { # Reset the enviroment variable to its oriuginal value. set env(COLUMNS) $prev_columns diff --git a/gcc/testsuite/gcc.target/i386/cf_check-6.c b/gcc/testsuite/gcc.target/i386/cf_check-6.c new file mode 100644 index 00000000000..73b78dce889 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/cf_check-6.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fhardened -mno-manual-endbr" } */ +/* { dg-final { scan-assembler-times {\mendbr} 1 } } */ +/* Test that -fhardened enables CET. */ + +extern void bar (void) __attribute__((__cf_check__)); + +void +foo (void) +{ + bar (); +} diff --git a/gcc/toplev.cc b/gcc/toplev.cc index 9a734890a18..841444d545c 100644 --- a/gcc/toplev.cc +++ b/gcc/toplev.cc @@ -1567,6 +1567,13 @@ process_options () flag_associative_math = 0; } + if (flag_hardened && !HAVE_FHARDENED_SUPPORT) + { + warning_at (UNKNOWN_LOCATION, 0, + "%<-fhardened%> not supported for this target"); + flag_hardened = 0; + } + /* -fstack-clash-protection is not currently supported on targets where the stack grows up. */ if (flag_stack_clash_protection && !STACK_GROWS_DOWNWARD) @@ -1576,6 +1583,19 @@ process_options () "where the stack grows from lower to higher addresses"); flag_stack_clash_protection = 0; } + else if (flag_hardened) + { + if (!flag_stack_clash_protection + /* Don't enable -fstack-clash-protection when -fstack-check= + is used: it would result in confusing errors. */ + && flag_stack_check == NO_STACK_CHECK) + flag_stack_clash_protection = 1; + else if (flag_stack_check != NO_STACK_CHECK) + warning_at (UNKNOWN_LOCATION, OPT_Whardened, + "%<-fstack-clash-protection%> is not enabled by " + "%<-fhardened%> because %<-fstack-check%> was " + "specified on the command line"); + } /* We cannot support -fstack-check= and -fstack-clash-protection at the same time. */ @@ -1591,8 +1611,9 @@ process_options () target already uses a soft frame pointer, the transition is trivial. */ if (!FRAME_GROWS_DOWNWARD && flag_stack_protect) { - warning_at (UNKNOWN_LOCATION, 0, - "%<-fstack-protector%> not supported for this target"); + if (!flag_stack_protector_set_by_fhardened_p) + warning_at (UNKNOWN_LOCATION, 0, + "%<-fstack-protector%> not supported for this target"); flag_stack_protect = 0; } if (!flag_stack_protect)