From patchwork Fri May 12 05:42:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: liuhongt X-Patchwork-Id: 92940 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp4869714vqo; Thu, 11 May 2023 22:45:33 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ4+qrGTvP0h6ZeiShy/VNc6JRYvNe3oOIPLEY/YYiFgOX9fwbzPs6DGt0psMSmoKmggtvjh X-Received: by 2002:a17:907:26c8:b0:965:9f86:4fe4 with SMTP id bp8-20020a17090726c800b009659f864fe4mr19772322ejc.56.1683870333672; Thu, 11 May 2023 22:45:33 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1683870333; cv=none; d=google.com; s=arc-20160816; b=HLWlZTN+olldl7ueqCvBbscQE0xfD6P/qx6+T41BNb+P7IswfZbBEgUEY9v8hjf4RH Flr7Ds2UoKEQNtxE50LHet06GC9QvTkExmya4WL0etMyuNNR8S5VQmqVe0VPIppxBSZh BxzmQGolZbx4MryfeF4y26Oi5IU4OJbeg5Cirpivvx5bhkwMJ/pR9vlHA/ocTsGYe8rJ 9ruJeKzyHe2n/n/Q3DwuIXOEzdE7ndKePTvK+ytDFpe1ef/E9Hw2VyOlLQeNIyGtfwpY br5JtO5mztOkjW4xTDVVkhKiLS4vLBg15PQYNrtoxqP07S74nhpfQNb0X+5RDLGcGfEf IrbA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:from:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence :content-transfer-encoding:mime-version:message-id:date:subject:cc :to:dmarc-filter:delivered-to:dkim-signature:dkim-filter; bh=uciYk3xYE1+rGDU/IVrLH8Pb/M/lEhGoEmyCt57JAZ4=; b=Qlg0+ogeawMvJT8ozbOvA25VSUJHQG4co/R7FXLYrbZixs4LAU8ENpTEhhOvmGu0TD qqoPhXlRvSmJl7oqx0wXDYl8Gs5xsFWz8EId8PZgNmWcjBpvJBnY399khxtL7uDQ/rup q5RtxcbwX45JFjpIS9egyyHTq5OUrmdaOQdlJV9jf3+FC49p3x44gdmdJ0gM+K/bhykJ YC8IxfIHzBfitY1WuSAW+ovPNgUQ6ukNFZBc2EhsrQSQOtSHozokHX6c7HPIDDUrX803 uZXebjJV6WNzHS9btXWshVSIf6FnjblYnEOrYruRlHsfDSU0tzoWcdyepeqSD+7JKogy ZQPw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=h2ml0UqC; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id ss19-20020a170907c01300b009537bd2afb6si7208516ejc.20.2023.05.11.22.45.33 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 May 2023 22:45:33 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=h2ml0UqC; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 39F1F3856DE6 for ; Fri, 12 May 2023 05:45:32 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 39F1F3856DE6 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1683870332; bh=uciYk3xYE1+rGDU/IVrLH8Pb/M/lEhGoEmyCt57JAZ4=; h=To:Cc:Subject:Date:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From:Reply-To:From; b=h2ml0UqCiCA9SooUdLPjF+7P93bC0ubNzAb9jsaXrzYWHZw0A1Gx4ugEMWQ9WQt6m xZWRI4gCaTmMsiClBMKNYYTHHJFj2MRzzC4uAFZTdqPWfM04UyMKu5sKAtmHI1r+N9 Mwd0Cg1hxIbIeWQNRs3yvF7frxKvd084AjxZBOnA= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by sourceware.org (Postfix) with ESMTPS id D2398385694E for ; Fri, 12 May 2023 05:44:17 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D2398385694E X-IronPort-AV: E=McAfee;i="6600,9927,10707"; a="348204476" X-IronPort-AV: E=Sophos;i="5.99,269,1677571200"; d="scan'208";a="348204476" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 May 2023 22:44:16 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10707"; a="700033759" X-IronPort-AV: E=Sophos;i="5.99,269,1677571200"; d="scan'208";a="700033759" Received: from shvmail03.sh.intel.com ([10.239.245.20]) by orsmga002.jf.intel.com with ESMTP; 11 May 2023 22:44:14 -0700 Received: from shliclel4217.sh.intel.com (shliclel4217.sh.intel.com [10.239.240.127]) by shvmail03.sh.intel.com (Postfix) with ESMTP id 069761007BC8; Fri, 12 May 2023 13:44:14 +0800 (CST) To: gcc-patches@gcc.gnu.org Cc: crazylht@gmail.com, hjl.tools@gmail.com Subject: [PATCH] Provide -fcf-protection=branch,return. Date: Fri, 12 May 2023 13:42:13 +0800 Message-Id: <20230512054213.2211594-1-hongtao.liu@intel.com> X-Mailer: git-send-email 2.39.1.388.g2fc9e9ca3c MIME-Version: 1.0 X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, 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.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: liuhongt via Gcc-patches From: liuhongt Reply-To: liuhongt Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1765666019261924849?= X-GMAIL-MSGID: =?utf-8?q?1765666019261924849?= Bootstrapped and regtested on x86_64-pc-linux-gnu{-m32,}. Ok for trunk? gcc/ChangeLog: PR target/89701 * common.opt: Refactor -fcf-protection= to support combination of param. * lto-wrapper.c (merge_and_complain): Adjusted. * opts.c (parse_cf_protection_options): New. (common_handle_option): Decode argument for -fcf-protection=. * opts.h (parse_cf_protection_options): Declare. gcc/testsuite/ChangeLog: PR target/89701 * c-c++-common/fcf-protection-8.c: New test. * c-c++-common/fcf-protection-9.c: New test. * c-c++-common/fcf-protection-10.c: New test. * gcc.target/i386/pr89701-1.c: New test. * gcc.target/i386/pr89701-2.c: New test. * gcc.target/i386/pr89701-3.c: New test. * gcc.target/i386/pr89701-4.c: New test. --- gcc/common.opt | 24 ++---- gcc/lto-wrapper.cc | 21 +++-- gcc/opts.cc | 79 +++++++++++++++++++ gcc/opts.h | 1 + .../c-c++-common/fcf-protection-10.c | 3 + .../c-c++-common/fcf-protection-11.c | 2 + .../c-c++-common/fcf-protection-12.c | 2 + gcc/testsuite/c-c++-common/fcf-protection-8.c | 3 + gcc/testsuite/c-c++-common/fcf-protection-9.c | 3 + gcc/testsuite/gcc.target/i386/pr89701-1.c | 4 + gcc/testsuite/gcc.target/i386/pr89701-2.c | 4 + gcc/testsuite/gcc.target/i386/pr89701-3.c | 5 ++ gcc/testsuite/gcc.target/i386/pr89701-4.c | 5 ++ 13 files changed, 130 insertions(+), 26 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/fcf-protection-10.c create mode 100644 gcc/testsuite/c-c++-common/fcf-protection-11.c create mode 100644 gcc/testsuite/c-c++-common/fcf-protection-12.c create mode 100644 gcc/testsuite/c-c++-common/fcf-protection-8.c create mode 100644 gcc/testsuite/c-c++-common/fcf-protection-9.c create mode 100644 gcc/testsuite/gcc.target/i386/pr89701-1.c create mode 100644 gcc/testsuite/gcc.target/i386/pr89701-2.c create mode 100644 gcc/testsuite/gcc.target/i386/pr89701-3.c create mode 100644 gcc/testsuite/gcc.target/i386/pr89701-4.c diff --git a/gcc/common.opt b/gcc/common.opt index a28ca13385a..ac12da52733 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -229,6 +229,10 @@ bool dump_base_name_prefixed = false Variable unsigned int flag_zero_call_used_regs +;; What the CF check should instrument +Variable +unsigned int flag_cf_protection = 0 + ### Driver @@ -1886,28 +1890,10 @@ fcf-protection Common RejectNegative Alias(fcf-protection=,full) fcf-protection= -Common Joined RejectNegative Enum(cf_protection_level) Var(flag_cf_protection) Init(CF_NONE) +Common Joined -fcf-protection=[full|branch|return|none|check] Instrument functions with checks to verify jump/call/return control-flow transfer instructions have valid targets. -Enum -Name(cf_protection_level) Type(enum cf_protection_level) UnknownError(unknown Control-Flow Protection Level %qs) - -EnumValue -Enum(cf_protection_level) String(full) Value(CF_FULL) - -EnumValue -Enum(cf_protection_level) String(branch) Value(CF_BRANCH) - -EnumValue -Enum(cf_protection_level) String(return) Value(CF_RETURN) - -EnumValue -Enum(cf_protection_level) String(check) Value(CF_CHECK) - -EnumValue -Enum(cf_protection_level) String(none) Value(CF_NONE) - finstrument-functions Common Var(flag_instrument_function_entry_exit,1) Instrument function entry and exit with profiling calls. diff --git a/gcc/lto-wrapper.cc b/gcc/lto-wrapper.cc index 5186d040ce0..568c8af659d 100644 --- a/gcc/lto-wrapper.cc +++ b/gcc/lto-wrapper.cc @@ -359,26 +359,33 @@ merge_and_complain (vec &decoded_options, case OPT_fcf_protection_: /* Default to link-time option, else append or check identical. */ if (!cf_protection_option - || cf_protection_option->value == CF_CHECK) + || !memcmp (cf_protection_option->arg, "check", 5)) { + const char* parg = decoded_options[existing_opt].arg; if (existing_opt == -1) decoded_options.safe_push (*foption); - else if (decoded_options[existing_opt].value != foption->value) + else if ((strlen (parg) != strlen (foption->arg)) + || memcmp (parg, foption->arg, strlen (foption->arg))) { if (cf_protection_option - && cf_protection_option->value == CF_CHECK) + && !memcmp (cf_protection_option->arg, "check", 5)) fatal_error (input_location, "option %qs with mismatching values" " (%s, %s)", "-fcf-protection", - decoded_options[existing_opt].arg, + parg, foption->arg); else { /* Merge and update the -fcf-protection option. */ - decoded_options[existing_opt].value - &= (foption->value & CF_FULL); - switch (decoded_options[existing_opt].value) + HOST_WIDE_INT flags1 + = parse_cf_protection_options (foption->arg, + input_location); + HOST_WIDE_INT flags2 + = parse_cf_protection_options (parg, + input_location); + flags2 &= (flags1 & CF_FULL); + switch (flags2) { case CF_NONE: decoded_options[existing_opt].arg = "none"; diff --git a/gcc/opts.cc b/gcc/opts.cc index 86b94d62b58..6389383bc92 100644 --- a/gcc/opts.cc +++ b/gcc/opts.cc @@ -2187,6 +2187,81 @@ get_closest_sanitizer_option (const string_fragment &arg, return bm.get_best_meaningful_candidate (); } +unsigned int +parse_cf_protection_options (const char *p, location_t loc) +{ + unsigned int flags = 0; + bool combined = false; + while (*p != 0) + { + size_t len; + const char *comma = strchr (p, ','); + if (comma == NULL) + len = strlen (p); + else + { + combined = true; + len = comma - p; + } + + if (len == 0) + { + p = comma + 1; + continue; + } + + switch (len) + { + case 4: + if (!memcmp (p, "full", 4)) + { + if (combined && flags != CF_NONE) + warning_at (loc, 0, "better to use %<-fcf-protection=%> " + "option: full alone instead of in a combination"); + flags |= CF_FULL; + } + else if (!memcmp (p, "none", 4)) + { + if (combined && flags != CF_NONE) + warning_at (loc, 0, "combination of %<-fcf-protection=%> " + "option: none is ignored"); + } + else + error_at (loc, "unrecognized argument to %<-fcf-protection=%> " + "option: %.4s", p); + break; + case 5: + if (!memcmp (p, "check", 5)) + { + if (combined && flags != CF_CHECK) + error_at (loc, "Combination for %<-fcf-protection=%> " + "option: check is not valid"); + flags |= CF_CHECK; + } + else + error_at (loc, "unrecognized argument to %<-fcf-protection=%> " + "option: %.5s", p); + break; + case 6: + if (!memcmp (p, "branch", 6)) + flags |= CF_BRANCH; + else if (!memcmp (p, "return", 6)) + flags |= CF_RETURN; + else + error_at (loc, "unrecognized argument to %<-fcf-protection=%> " + "option: %.6s", p); + break; + default: + error_at (loc, "unrecognized argument to %<-fcf-protection=%> " + "option: %.*s", (int) len, p); + } + + if (comma == NULL) + break; + p = comma + 1; + } + return flags; +} /* Parse comma separated sanitizer suboptions from P for option SCODE, adjust previous FLAGS and return new ones. If COMPLAIN is false, don't issue diagnostics. */ @@ -2671,6 +2746,10 @@ common_handle_option (struct gcc_options *opts, case OPT__completion_: break; + case OPT_fcf_protection_: + opts->x_flag_cf_protection + = parse_cf_protection_options (arg, loc); + break; case OPT_fsanitize_: opts_set->x_flag_sanitize = true; opts->x_flag_sanitize diff --git a/gcc/opts.h b/gcc/opts.h index 9959a440ca1..00d396d95f8 100644 --- a/gcc/opts.h +++ b/gcc/opts.h @@ -425,6 +425,7 @@ extern void control_warning_option (unsigned int opt_index, int kind, extern char *write_langs (unsigned int mask); extern void print_ignored_options (void); extern void handle_common_deferred_options (void); +extern unsigned int parse_cf_protection_options (const char*, location_t); unsigned int parse_sanitizer_options (const char *, location_t, int, unsigned int, int, bool); diff --git a/gcc/testsuite/c-c++-common/fcf-protection-10.c b/gcc/testsuite/c-c++-common/fcf-protection-10.c new file mode 100644 index 00000000000..8692a08374b --- /dev/null +++ b/gcc/testsuite/c-c++-common/fcf-protection-10.c @@ -0,0 +1,3 @@ +/* { dg-do compile { target { "i?86-*-* x86_64-*-*" } } } */ +/* { dg-options "-fcf-protection=branch,check" } */ +/* { dg-error "Combination for '-fcf-protection=' option: check is not valid" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/c-c++-common/fcf-protection-11.c b/gcc/testsuite/c-c++-common/fcf-protection-11.c new file mode 100644 index 00000000000..2e566350ccd --- /dev/null +++ b/gcc/testsuite/c-c++-common/fcf-protection-11.c @@ -0,0 +1,2 @@ +/* { dg-do compile { target { "i?86-*-* x86_64-*-*" } } } */ +/* { dg-options "-fcf-protection=branch,return" } */ diff --git a/gcc/testsuite/c-c++-common/fcf-protection-12.c b/gcc/testsuite/c-c++-common/fcf-protection-12.c new file mode 100644 index 00000000000..b39c2f8e25d --- /dev/null +++ b/gcc/testsuite/c-c++-common/fcf-protection-12.c @@ -0,0 +1,2 @@ +/* { dg-do compile { target { "i?86-*-* x86_64-*-*" } } } */ +/* { dg-options "-fcf-protection=return,branch" } */ diff --git a/gcc/testsuite/c-c++-common/fcf-protection-8.c b/gcc/testsuite/c-c++-common/fcf-protection-8.c new file mode 100644 index 00000000000..33e46223b6b --- /dev/null +++ b/gcc/testsuite/c-c++-common/fcf-protection-8.c @@ -0,0 +1,3 @@ +/* { dg-do compile { target { "i?86-*-* x86_64-*-*" } } } */ +/* { dg-options "-fcf-protection=branch,none" } */ +/* { dg-warning "combination of '-fcf-protection=' option: none is ignored" "" { target { *-*-* } } 0 } */ diff --git a/gcc/testsuite/c-c++-common/fcf-protection-9.c b/gcc/testsuite/c-c++-common/fcf-protection-9.c new file mode 100644 index 00000000000..7848fe4b959 --- /dev/null +++ b/gcc/testsuite/c-c++-common/fcf-protection-9.c @@ -0,0 +1,3 @@ +/* { dg-do compile { target { "i?86-*-* x86_64-*-*" } } } */ +/* { dg-options "-fcf-protection=branch,full" } */ +/* { dg-warning "better to use '-fcf-protection=' option: full alone instead of in a combination" "" { target { *-*-* } } 0 } */ diff --git a/gcc/testsuite/gcc.target/i386/pr89701-1.c b/gcc/testsuite/gcc.target/i386/pr89701-1.c new file mode 100644 index 00000000000..1879c9ab4d8 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr89701-1.c @@ -0,0 +1,4 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-fcf-protection=branch,return" } */ +/* { dg-final { scan-assembler-times ".note.gnu.property" 1 } } */ +/* { dg-final { scan-assembler-times ".long 0x3" 1 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr89701-2.c b/gcc/testsuite/gcc.target/i386/pr89701-2.c new file mode 100644 index 00000000000..d5100575028 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr89701-2.c @@ -0,0 +1,4 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-fcf-protection=return,branch" } */ +/* { dg-final { scan-assembler-times ".note.gnu.property" 1 } } */ +/* { dg-final { scan-assembler-times ".long 0x3" 1 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr89701-3.c b/gcc/testsuite/gcc.target/i386/pr89701-3.c new file mode 100644 index 00000000000..1505051a2bb --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr89701-3.c @@ -0,0 +1,5 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-fcf-protection=return,none" } */ +/* { dg-warning "combination of '-fcf-protection=' option: none is ignored" "" { target { *-*-linux* } } 0 } */ +/* { dg-final { scan-assembler-times ".note.gnu.property" 1 } } */ +/* { dg-final { scan-assembler-times ".long 0x2" 1 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr89701-4.c b/gcc/testsuite/gcc.target/i386/pr89701-4.c new file mode 100644 index 00000000000..242b8810abb --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr89701-4.c @@ -0,0 +1,5 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-fcf-protection=branch,none" } */ +/* { dg-warning "combination of '-fcf-protection=' option: none is ignored" "" { target { *-*-* } } 0 } */ +/* { dg-final { scan-assembler-times ".note.gnu.property" 1 } } */ +/* { dg-final { scan-assembler-times ".long 0x1" 1 } } */