From patchwork Fri Jan 6 11:47:07 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiong Wang X-Patchwork-Id: 90147 Delivered-To: patch@linaro.org Received: by 10.182.224.138 with SMTP id rc10csp295065obc; Fri, 6 Jan 2017 03:47:41 -0800 (PST) X-Received: by 10.84.232.137 with SMTP id i9mr130330758plk.95.1483703261505; Fri, 06 Jan 2017 03:47:41 -0800 (PST) Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id m23si44898989plk.231.2017.01.06.03.47.41 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 06 Jan 2017 03:47:41 -0800 (PST) Received-SPF: pass (google.com: domain of gcc-patches-return-445522-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org; spf=pass (google.com: domain of gcc-patches-return-445522-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=gcc-patches-return-445522-patch=linaro.org@gcc.gnu.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :subject:to:references:cc:from:message-id:date:mime-version :in-reply-to:content-type; q=dns; s=default; b=IvVsMTGAzPmdrEq2H NG872cFhSjrPkiptYuLjMlKDVSNG+VahlAVjT10b8XzV7X54xmHu5b20oAR1diBv Wd++KYx8IDtySreGYIpXz8ReAFg617ULDKqtyMnSAtckv/vS4wM/rXiIFaEeMzIk XN8/RlWaGnWvci4KCiH78Kh0+c= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :subject:to:references:cc:from:message-id:date:mime-version :in-reply-to:content-type; s=default; bh=tAheqrtFkcz+vhxULrMbEb0 yd9o=; b=Ve7K5adknSFa9mmZIj1v/Siuz1FsH4lbuCbwkD9Mw9X/OwX9fC7DBYK Qqg9g6iGrBYxQUy0TAnDKg844Y7WByBDnqATrnrddCtSQ33w7JiRHajIHhtHTH4a UuL6y+h52aC/puizw0NbNM4R8fzuHyd16JdqGTjEeBRz2ZqhrD90= Received: (qmail 18278 invoked by alias); 6 Jan 2017 11:47:22 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 18252 invoked by uid 89); 6 Jan 2017 11:47:22 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.3 required=5.0 tests=BAYES_00, KAM_INSURE, KAM_LAZY_DOMAIN_SECURITY, KAM_LOTSOFHASH, RP_MATCHES_RCVD autolearn=no version=3.3.2 spammy=trn, architectural, cie, asp X-HELO: foss.arm.com Received: from foss.arm.com (HELO foss.arm.com) (217.140.101.70) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 06 Jan 2017 11:47:11 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 662A6152D; Fri, 6 Jan 2017 03:47:09 -0800 (PST) Received: from [10.2.206.198] (e104437-lin.cambridge.arm.com [10.2.206.198]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id C84373F220; Fri, 6 Jan 2017 03:47:08 -0800 (PST) Subject: [1/5][AArch64] Return address protection on AArch64 To: gcc-patches References: <4cf21d03-0a88-c6fa-df37-59ec4edf1d89@foss.arm.com> <6f8e65e0-643d-d0b0-26ad-4a20c3daf421@foss.arm.com> Cc: James Greenhalgh , "Richard Earnshaw (lists)" From: Jiong Wang Message-ID: Date: Fri, 6 Jan 2017 11:47:07 +0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.6.0 MIME-Version: 1.0 In-Reply-To: <6f8e65e0-643d-d0b0-26ad-4a20c3daf421@foss.arm.com> X-IsSubscribed: yes On 11/11/16 18:22, Jiong Wang wrote: > As described in the cover letter, this patch implements return address signing > for AArch64, it's controlled by the new option: > > -msign-return-address=[none | non-leaf | all] > > "none" means don't do return address signing at all on any function. "non-leaf" > means only sign non-leaf function. "all" means sign all functions. Return > address signing is currently disabled on ILP32. I haven't tested it. > > The instructions added in the architecture are of 2 kinds. > > * In the NOP instruction space, which allows binaries to run without any traps > on older versions of the architecture. This doesn't give any additional > protection on older hardware but allows for the same binary to be used on > earlier versions of the architecture and newer versions of the architecture. > > * New instructions that are only valid for v8.3 and will trap if used on earlier > versions of the architecture. > > At default, once return address signing is enabled, it will only generates NOP > instruction. > > While if -march=armv8.3-a specified, GCC will try to use the most efficient > pointer authentication instruction as it can. > > The architecture has 2 user invisible system keys for signing and creating > signed addresses as part of these instructions. For some use case, the user > might want to use difference key for different functions. The new option > "-msign-return-address-key=key_name" let GCC select the key used for return > address signing. Permissible values are "a_key" for A key and "b_key" for B > key, and this option are supported by function target attribute and LTO will > hopefully just work. > > > > gcc/ > 2016-11-09 Jiong Wang > > * config/aarch64/aarch64-opts.h (aarch64_pauth_key_index): New enum. > (aarch64_function_type): New enum. > * config/aarch64/aarch64-protos.h (aarch64_output_sign_auth_reg): New > declaration. > * config/aarch64/aarch64.c (aarch64_expand_prologue): Sign return > address before it's pushed onto stack. > (aarch64_expand_epilogue): Authenticate return address fetched from > stack. > (aarch64_output_sign_auth_reg): New function. > (aarch64_override_options): Sanity check for ILP32 and ISA level. > (aarch64_attributes): New function attributes for "sign-return-address", > "pauth-key". > * config/aarch64/aarch64.md (UNSPEC_AUTH_REG, UNSPEC_AUTH_REG1716, > UNSPEC_SIGN_REG, UNSPEC_SIGN_REG1716, UNSPEC_STRIP_REG_SIGN, > UNSPEC_STRIP_X30_SIGN): New unspecs. > ("*do_return"): Generate combined instructions according to key index. > ("sign_reg", "sign_reg1716", "auth_reg", "auth_reg1716", > "strip_reg_sign", "strip_lr_sign"): New. > * config/aarch64/aarch64.opt (msign-return-address, mpauth-key): New. > * config/aarch64/predicates.md (aarch64_const0_const1): New predicate. > * doc/extend.texi (AArch64 Function Attributes): Documents > "sign-return-address=", "pauth-key". > * doc/invoke.texi (AArch64 Options): Documents "-msign-return-address=", > "-pauth-key". > > gcc/testsuite/ > 2016-11-09 Jiong Wang > > * gcc.target/aarch64/return_address_sign_1.c: New testcase. > * gcc.target/aarch64/return_address_sign_scope_1.c: New testcase. Update the patchset according to new DWARF proposal described at https://gcc.gnu.org/ml/gcc-patches/2016-11/msg03010.html While A key support for return address signing using DW_CFA_GNU_window_save only needs simple modifications on code and associated DWARF generation, B key support is complexer, it needs multiple CIE support in GCC and Binutils, so currently we fall back to DWARF value expression which fully works although requires longer encodings. Value expression also requires a few changes on AArch64 prologue and epilogue hooks that code review will not be easy. Therefore I have removed all B key support code in the initial support patch set, and will organize them into a seperate follow up patchset so that we can do A key code review first. This patch is an update on the return address signing code generation. gcc/ 2017-01-06 Jiong Wang * config/aarch64/aarch64-opts.h (aarch64_function_type): New enum. * config/aarch64/aarch64-protos.h (aarch64_return_address_signing_enabled): New declaration. * config/aarch64/aarch64.c (aarch64_return_address_signing_enabled): New function. (aarch64_expand_prologue): Sign return address before it's pushed onto stack. (aarch64_expand_epilogue): Authenticate return address fetched from stack. (aarch64_override_options): Sanity check for ILP32 and ISA level. (aarch64_attributes): New function attributes for "sign-return-address". * config/aarch64/aarch64.md (UNSPEC_AUTI1716, UNSPEC_AUTISP, UNSPEC_PACI1716, UNSPEC_PACISP, UNSPEC_XPACLRI): New unspecs. ("*do_return"): Generate combined instructions according to key index. ("sp", "calls_eh_return) + return "retaa"; + + return "ret"; + } [(set_attr "type" "branch")] ) @@ -5341,6 +5353,31 @@ [(set_attr "length" "0")] ) +;; Pointer authentication patterns are available for all architectures. On +;; pre-ARMv8.3-A architectures they are NOP. This let the user write portable +;; software which can get pointer authentication on new hardware while still +;; runs correctly on old hardware though no pointer authentication protection. + +(define_insn "sp" + [(set (reg:DI R30_REGNUM) + (unspec:DI [(reg:DI R30_REGNUM) (reg:DI SP_REGNUM)] PAUTH_LR_SP))] + "" + "hint\t // asp"; +) + +(define_insn "1716" + [(set (reg:DI R17_REGNUM) + (unspec:DI [(reg:DI R17_REGNUM) (reg:DI R16_REGNUM)] PAUTH_17_16))] + "" + "hint\t // a1716"; +) + +(define_insn "xpaclri" + [(set (reg:DI R30_REGNUM) (unspec:DI [(reg:DI R30_REGNUM)] UNSPEC_XPACLRI))] + "" + "hint\t7 // xpaclri" +) + ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and ;; all of memory. This blocks insns from being moved across this point. diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt index 56b920dfe5abda1349c441c2188e5ac3ca05ab5a..54368848bbb249949921a3018d927c4bd61b1fbd 100644 --- a/gcc/config/aarch64/aarch64.opt +++ b/gcc/config/aarch64/aarch64.opt @@ -149,6 +149,23 @@ mpc-relative-literal-loads Target Report Save Var(pcrelative_literal_loads) Init(2) Save PC relative literal loads. +msign-return-address= +Target RejectNegative Report Joined Enum(aarch64_ra_sign_scope_t) Var(aarch64_ra_sign_scope) Init(AARCH64_FUNCTION_NONE) Save +Select return address signing scope. + +Enum +Name(aarch64_ra_sign_scope_t) Type(enum aarch64_function_type) +Supported AArch64 return address signing scope (for use with -msign-return-address= option): + +EnumValue +Enum(aarch64_ra_sign_scope_t) String(none) Value(AARCH64_FUNCTION_NONE) + +EnumValue +Enum(aarch64_ra_sign_scope_t) String(non-leaf) Value(AARCH64_FUNCTION_NON_LEAF) + +EnumValue +Enum(aarch64_ra_sign_scope_t) String(all) Value(AARCH64_FUNCTION_ALL) + mlow-precision-recip-sqrt Common Var(flag_mrecip_low_precision_sqrt) Optimization Enable the reciprocal square root approximation. Enabling this reduces diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md index e2377c1cb2161c52ccadec3804294c494819cbb8..c59d31e5053a28fa31259341e82b6696f6ac8781 100644 --- a/gcc/config/aarch64/iterators.md +++ b/gcc/config/aarch64/iterators.md @@ -1032,6 +1032,10 @@ (define_int_iterator FMAXMIN_UNS [UNSPEC_FMAX UNSPEC_FMIN UNSPEC_FMAXNM UNSPEC_FMINNM]) +(define_int_iterator PAUTH_LR_SP [UNSPEC_PACISP UNSPEC_AUTISP]) + +(define_int_iterator PAUTH_17_16 [UNSPEC_PACI1716 UNSPEC_AUTI1716]) + (define_int_iterator VQDMULH [UNSPEC_SQDMULH UNSPEC_SQRDMULH]) (define_int_iterator USSUQADD [UNSPEC_SUQADD UNSPEC_USQADD]) @@ -1218,6 +1222,18 @@ (UNSPEC_FCVTZS "fcvtzs") (UNSPEC_FCVTZU "fcvtzu")]) +;; Pointer authentication mnemonic prefix. +(define_int_attr pauth_mnem_prefix [(UNSPEC_PACISP "paci") + (UNSPEC_AUTISP "auti") + (UNSPEC_PACI1716 "paci") + (UNSPEC_AUTI1716 "auti")]) + +;; Pointer authentication HINT number for NOP space instructions using A Key. +(define_int_attr pauth_hint_num_a [(UNSPEC_PACISP "25") + (UNSPEC_AUTISP "29") + (UNSPEC_PACI1716 "8") + (UNSPEC_AUTI1716 "12")]) + (define_int_attr perm_insn [(UNSPEC_ZIP1 "zip") (UNSPEC_ZIP2 "zip") (UNSPEC_TRN1 "trn") (UNSPEC_TRN2 "trn") (UNSPEC_UZP1 "uzp") (UNSPEC_UZP2 "uzp")]) diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 30bdcf07ad8b1bd086bbb87acb36fb0333944087..47250ebb149bbde021ef64eba8e96e35c2623284 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -3513,6 +3513,12 @@ Specifies the core for which to tune the performance of this function and also whose architectural features to use. The behavior and valid arguments are the same as for the @option{-mcpu=} command-line option. +@item sign-return-address +@cindex @code{sign-return-address} function attribute, AArch64 +Select the function scope we want to do return address signing on. The behavior +and permissible arguments are the same as for the command-line option +@option{-msign-return-address=}. The default value is @code{none} + @end table The above target attributes can be specified as follows: diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index aa0ac8b41128483be53645b91bdcead096582e23..2792dbd0a2d0ed9e3f46237685f8ae65a5d8bcf5 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -14044,6 +14044,13 @@ accessed using a single instruction and emitted after each function. This limits the maximum size of functions to 1MB. This is enabled by default for @option{-mcmodel=tiny}. +@item -msign-return-address=@var{scope} +@opindex msign-return-address +Select the function scope we want to do return address signing on. Permissible +values are @samp{none}, @samp{none-leaf} and @samp{all}. @samp{none} means +return address signing is disabled. @samp{non-leaf} enables it for non-leaf +functions. @samp{all} for all functions and is the default value. + @end table @subsubsection @option{-march} and @option{-mcpu} Feature Modifiers diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c new file mode 100644 index 0000000000000000000000000000000000000000..9a0332abd41ca6ae994e6ed72771fca8ee532cd0 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c @@ -0,0 +1,56 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -msign-return-address=all" } */ + +int foo (int); +int bar (int, int); + +/* sibcall only. */ +int __attribute__ ((target ("arch=armv8.3-a"))) +func1 (int a, int b) +{ + /* paciasp */ + return foo (a + b); + /* autiasp */ +} + +/* non-leaf function with sibcall. */ +int __attribute__ ((target ("arch=armv8.3-a"))) +func2 (int a, int b) +{ + /* paciasp */ + if (a < b) + return b; + + a = foo (b); + + return foo (a); + /* autiasp */ +} + +/* non-leaf function, legacy arch. */ +int __attribute__ ((target ("arch=armv8.2-a"))) +func3 (int a, int b, int c) +{ + /* paciasp */ + return a + foo (b) + c; + /* autiasp */ +} + +/* non-leaf function. */ +int __attribute__ ((target ("arch=armv8.3-a"))) +func4 (int a, int b, int c) +{ + /* paciasp */ + return a + foo (b) + c; + /* retab */ +} + +int __attribute__ ((target ("arch=armv8.3-a, sign-return-address=none"))) +func4_disable (int a, int b, int c, int d) +{ + return c + bar (a, b) + d; +} + +/* { dg-final { scan-assembler-times "autiasp" 3 } } */ +/* { dg-final { scan-assembler-times "paciasp" 4 } } */ +/* { dg-final { scan-assembler-times "retaa" 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_scope_1.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_scope_1.c new file mode 100644 index 0000000000000000000000000000000000000000..6876e26a6a38eb670f8676f8f06dd74dfc18f41d --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_scope_1.c @@ -0,0 +1,55 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -msign-return-address=non-leaf" } */ + +int foo (int); +int bar (int, int); + +/* sibcall only. */ +int __attribute__ ((target ("arch=armv8.3-a, sign-return-address=non-leaf"))) +func1 (int a, int b) +{ + /* No authentication. */ + return foo (a + b); +} + +/* non-leaf function with sibcall. */ +int __attribute__ ((target ("arch=armv8.3-a"))) +func2 (int a, int b) +{ + /* paciasp */ + if (a < b) + return b; + + a = foo (b); + + return foo (a); + /* autiasp */ +} + +/* non-leaf function, legacy arch. */ +int __attribute__ ((target ("arch=armv8.2-a"))) +func3 (int a, int b, int c) +{ + /* pacibsp */ + return a + foo (b) + c; + /* autibsp */ +} + +/* non-leaf function. */ +int __attribute__ ((target ("arch=armv8.3-a"))) +func4 (int a, int b, int c) +{ + /* pacibsp */ + return a + foo (b) + c; + /* retab */ +} + +int __attribute__ ((target ("arch=armv8.3-a, sign-return-address=none"))) +func4_disable (int a, int b, int c, int d) +{ + return c + bar (a, b) + d; +} + +/* { dg-final { scan-assembler-times "paciasp" 3 } } */ +/* { dg-final { scan-assembler-times "autiasp" 2 } } */ +/* { dg-final { scan-assembler-times "retaa" 1 } } */