diff mbox

[1/5,AArch64] Return address protection on AArch64

Message ID 3f1218be-51b4-23d9-3748-e0f4d0bd5170@foss.arm.com
State New
Headers show

Commit Message

Jiong Wang Jan. 13, 2017, 5:05 p.m. UTC
On 13/01/17 16:04, James Greenhalgh wrote:
> On Fri, Jan 06, 2017 at 11:47:07AM +0000, Jiong Wang wrote:

>> On 11/11/16 18:22, Jiong Wang wrote:

>> gcc/

>> 2017-01-06  Jiong Wang  <jiong.wang@arm.com>

>>

>>          * 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.

>>          ("<pauth_mnem_prefix>sp", "<pauth_mnem_prefix1716", "xpaclri"): New.

>>          * config/aarch64/iterators.md (PAUTH_LR_SP, PAUTH_17_16): New integer

>>          iterators.

>>          (pauth_mnem_prefix, pauth_hint_num_a): New integer attributes.

>>          * config/aarch64/aarch64.opt (msign-return-address=): New.

>>          * doc/extend.texi (AArch64 Function Attributes): Documents

>>          "sign-return-address=".

>>          * doc/invoke.texi (AArch64 Options): Documents "-msign-return-address=".

>>

>> gcc/testsuite/

>> 2017-01-06  Jiong Wang  <jiong.wang@arm.com>

>>

>>          * gcc.target/aarch64/return_address_sign_1.c: New testcase.

>>          * gcc.target/aarch64/return_address_sign_scope_1.c: New testcase.

> I have a few comments on this patch


All fixed.  New patch attached.

gcc/
2017-01-13  Jiong Wang  <jiong.wang@arm.com>

         * 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.
         ("<pauth_mnem_prefix>sp", "<pauth_mnem_prefix1716", "xpaclri"): New.
         * config/aarch64/iterators.md (PAUTH_LR_SP, PAUTH_17_16): New integer
         iterators.
         (pauth_mnem_prefix, pauth_hint_num_a): New integer attributes.
         * config/aarch64/aarch64.opt (msign-return-address=): New.
         * doc/extend.texi (AArch64 Function Attributes): Documents
         "sign-return-address=".
         * doc/invoke.texi (AArch64 Options): Documents "-msign-return-address=".

gcc/testsuite/
2017-01-13  Jiong Wang  <jiong.wang@arm.com>

         * gcc.target/aarch64/return_address_sign_1.c: New testcase for no
         combined instructions.
         * gcc.target/aarch64/return_address_sign_2.c: New testcase for combined
         instructions.
         * gcc.target/aarch64/return_address_sign_3.c: New testcase for disable
         of pointer authentication.

Comments

James Greenhalgh Jan. 16, 2017, 11:24 a.m. UTC | #1
On Fri, Jan 13, 2017 at 05:05:43PM +0000, Jiong Wang wrote:
> On 13/01/17 16:04, James Greenhalgh wrote:

> >On Fri, Jan 06, 2017 at 11:47:07AM +0000, Jiong Wang wrote:

> >>On 11/11/16 18:22, Jiong Wang wrote:

> >>gcc/

> >>2017-01-06  Jiong Wang  <jiong.wang@arm.com>

> >>

> >>         * 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.

> >>         ("<pauth_mnem_prefix>sp", "<pauth_mnem_prefix1716", "xpaclri"): New.

> >>         * config/aarch64/iterators.md (PAUTH_LR_SP, PAUTH_17_16): New integer

> >>         iterators.

> >>         (pauth_mnem_prefix, pauth_hint_num_a): New integer attributes.

> >>         * config/aarch64/aarch64.opt (msign-return-address=): New.

> >>         * doc/extend.texi (AArch64 Function Attributes): Documents

> >>         "sign-return-address=".

> >>         * doc/invoke.texi (AArch64 Options): Documents "-msign-return-address=".

> >>

> >>gcc/testsuite/

> >>2017-01-06  Jiong Wang  <jiong.wang@arm.com>

> >>

> >>         * gcc.target/aarch64/return_address_sign_1.c: New testcase.

> >>         * gcc.target/aarch64/return_address_sign_scope_1.c: New testcase.

> >I have a few comments on this patch

> 

> All fixed.  New patch attached.


OK with two trivial changes (see below).

We're late in stage 3, but as this option is default off and doesn't affect
the rest of the AArch64 port I think it will be OK to take at this stage.
Because of the timing, please give Richard/Marcus a 24hr chance to comment
on whether they think this is acceptable.

> gcc/

> 2017-01-13  Jiong Wang  <jiong.wang@arm.com>

> 

>         * 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.

>         ("<pauth_mnem_prefix>sp", "<pauth_mnem_prefix1716", "xpaclri"): New.

>         * config/aarch64/iterators.md (PAUTH_LR_SP, PAUTH_17_16): New integer

>         iterators.

>         (pauth_mnem_prefix, pauth_hint_num_a): New integer attributes.

>         * config/aarch64/aarch64.opt (msign-return-address=): New.

>         * doc/extend.texi (AArch64 Function Attributes): Documents

>         "sign-return-address=".

>         * doc/invoke.texi (AArch64 Options): Documents "-msign-return-address=".

> 

> gcc/testsuite/

> 2017-01-13  Jiong Wang  <jiong.wang@arm.com>

> 

>         * gcc.target/aarch64/return_address_sign_1.c: New testcase for no

>         combined instructions.

>         * gcc.target/aarch64/return_address_sign_2.c: New testcase for combined

>         instructions.

>         * gcc.target/aarch64/return_address_sign_3.c: New testcase for disable

>         of pointer authentication.

> 


> diff --git a/gcc/config/aarch64/aarch64-opts.h b/gcc/config/aarch64/aarch64-opts.h

> index 9f37b9b..ba5d052 100644

> --- a/gcc/config/aarch64/aarch64-opts.h

> +++ b/gcc/config/aarch64/aarch64-opts.h

> @@ -71,4 +71,14 @@ enum aarch64_code_model {

>    AARCH64_CMODEL_LARGE

>  };

>  

> +/* Function types -msign-return-address should sign.  */

> +enum aarch64_function_type {

> +  /* Don't sign any function.  */

> +  AARCH64_FUNCTION_NONE,

> +  /* Non-leaf functions.  */

> +  AARCH64_FUNCTION_NON_LEAF,

> +  /* All functions.  */

> +  AARCH64_FUNCTION_ALL

> +};

> +

>  #endif

> diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h

> index 29a3bd7..632dd47 100644

> --- a/gcc/config/aarch64/aarch64-protos.h

> +++ b/gcc/config/aarch64/aarch64-protos.h

> @@ -386,6 +386,7 @@ void aarch64_emit_call_insn (rtx);

>  void aarch64_register_pragmas (void);

>  void aarch64_relayout_simd_types (void);

>  void aarch64_reset_previous_fndecl (void);

> +bool aarch64_return_address_signing_enabled (void);

>  void aarch64_save_restore_target_globals (tree);

>  

>  /* Initialize builtins for SIMD intrinsics.  */

> diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c

> index 9dd75b0..3bcad76 100644

> --- a/gcc/config/aarch64/aarch64.c

> +++ b/gcc/config/aarch64/aarch64.c

> @@ -3117,6 +3117,22 @@ aarch64_gen_load_pair (machine_mode mode, rtx reg1, rtx mem1, rtx reg2,

>      }

>  }

>  

> +/* Return TRUE if return address signing should be enabled for one function,


s/one/the current/

> +   otherwise return FALSE.  */

> +

> +bool

> +aarch64_return_address_signing_enabled (void)

> +{

> +  /* This function should only be called after frame laid out.   */

> +  gcc_assert (cfun->machine->frame.laid_out);

> +

> +  /* If signing scope is AARCH64_FUNCTION_NON_LEAF, we only sign a leaf function

> +     if it's LR is pushed onto stack.  */

> +  return (aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL

> +	  || (aarch64_ra_sign_scope == AARCH64_FUNCTION_NON_LEAF

> +	      && cfun->machine->frame.reg_offset[LR_REGNUM] >= 0));

> +}

> +

>  /* Emit code to save the callee-saved registers from register number START

>     to LIMIT to the stack at the location starting at offset START_OFFSET,

>     skipping any write-back candidates if SKIP_WB is true.  */

> @@ -3535,6 +3551,10 @@ aarch64_expand_prologue (void)

>    unsigned reg2 = cfun->machine->frame.wb_candidate2;

>    rtx_insn *insn;

>  

> +  /* Sign return address for functions.  */

> +  if (aarch64_return_address_signing_enabled ())

> +    emit_insn (gen_pacisp ());

> +

>    if (flag_stack_usage_info)

>      current_function_static_stack_size = frame_size;

>  

> @@ -3670,6 +3690,25 @@ aarch64_expand_epilogue (bool for_sibcall)

>        RTX_FRAME_RELATED_P (insn) = 1;

>      }

>  

> +  /* We prefer to emit the combined return/authenticate instruction RETAA,

> +     however there are three cases in which we must instead emit an explicit

> +     authentication instruction.

> +

> +	1) Sibcalls don't return in a normal way, so if we're about to call one

> +	   we must authenticate.

> +

> +	2) The RETAA instruction is not available before ARMv8.3-A, so if we are

> +	   generating code for !TARGET_ARMV8_3 we can't use it and must

> +	   explicitly authenticate.

> +

> +	3) On an eh_return path we make extra stack adjustments to update the

> +	   canonical frame address to be the exception handler's CFA.  We want

> +	   to authenticate using the CFA of the function which calls eh_return.

> +    */

> +  if (aarch64_return_address_signing_enabled ()

> +      && (for_sibcall || !TARGET_ARMV8_3 || crtl->calls_eh_return))

> +    emit_insn (gen_autisp ());

> +

>    /* Stack adjustment for exception handler.  */

>    if (crtl->calls_eh_return)

>      {

> @@ -8894,6 +8933,9 @@ aarch64_override_options (void)

>      error ("Assembler does not support -mabi=ilp32");

>  #endif

>  

> +  if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE && TARGET_ILP32)

> +    sorry ("Return address signing is only supported for -mabi=lp64");

> +

>    /* Make sure we properly set up the explicit options.  */

>    if ((aarch64_cpu_string && valid_cpu)

>         || (aarch64_tune_string && valid_tune))

> @@ -9277,6 +9319,8 @@ static const struct aarch64_attribute_info aarch64_attributes[] =

>    { "cpu", aarch64_attr_custom, false, aarch64_handle_attr_cpu, OPT_mcpu_ },

>    { "tune", aarch64_attr_custom, false, aarch64_handle_attr_tune,

>       OPT_mtune_ },

> +  { "sign-return-address", aarch64_attr_enum, false, NULL,

> +     OPT_msign_return_address_ },

>    { NULL, aarch64_attr_custom, false, NULL, OPT____ }

>  };

>  

> diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md

> index bde4231..5dc68b7 100644

> --- a/gcc/config/aarch64/aarch64.md

> +++ b/gcc/config/aarch64/aarch64.md

> @@ -67,6 +67,8 @@

>  )

>  

>  (define_c_enum "unspec" [

> +    UNSPEC_AUTI1716

> +    UNSPEC_AUTISP

>      UNSPEC_CASESI

>      UNSPEC_CRC32B

>      UNSPEC_CRC32CB

> @@ -106,6 +108,8 @@

>      UNSPEC_LD4_LANE

>      UNSPEC_MB

>      UNSPEC_NOP

> +    UNSPEC_PACI1716

> +    UNSPEC_PACISP

>      UNSPEC_PRLG_STK

>      UNSPEC_RBIT

>      UNSPEC_SCVTF

> @@ -135,6 +139,7 @@

>      UNSPEC_RSQRTE

>      UNSPEC_RSQRTS

>      UNSPEC_NZCV

> +    UNSPEC_XPACLRI

>  ])

>  

>  (define_c_enum "unspecv" [

> @@ -575,7 +580,14 @@

>  (define_insn "*do_return"

>    [(return)]

>    ""

> -  "ret"

> +  {

> +    if (aarch64_return_address_signing_enabled ()

> +	&& TARGET_ARMV8_3

> +	&& !crtl->calls_eh_return)

> +      return "retaa";

> +

> +    return "ret";

> +  }

>    [(set_attr "type" "branch")]

>  )

>  

> @@ -5341,6 +5353,36 @@

>    [(set_attr "length" "0")]

>  )

>  

> +;; Pointer authentication patterns are always provided.  In architecture

> +;; revisions prior to ARMv8.3-A these HINT instructions operate as NOPs.

> +;; This lets the user write portable software which authenticates pointers

> +;; when run on something which implements ARMv8.3-A, and which runs

> +;; correctly, but does not authenticate pointers, where ARMv8.3-A is not

> +;; implemented.

> +

> +;; Signing/Authenticating R30 using SP as the salt.


Newline between comment and pattern.

> +(define_insn "<pauth_mnem_prefix>sp"

> +  [(set (reg:DI R30_REGNUM)

> +	(unspec:DI [(reg:DI R30_REGNUM) (reg:DI SP_REGNUM)] PAUTH_LR_SP))]

> +  ""

> +  "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>asp";

> +)

> +

> +;; Signing/Authenticating X17 using X16 as the salt.


Newline between comment and pattern.

> +(define_insn "<pauth_mnem_prefix>1716"

> +  [(set (reg:DI R17_REGNUM)

> +	(unspec:DI [(reg:DI R17_REGNUM) (reg:DI R16_REGNUM)] PAUTH_17_16))]

> +  ""

> +  "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>a1716";

> +)

> +

> +;; Stripping the signature in R30.


Newline between comment and pattern.

> +(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.

  
Thanks,
James
diff mbox

Patch

diff --git a/gcc/config/aarch64/aarch64-opts.h b/gcc/config/aarch64/aarch64-opts.h
index 9f37b9b..ba5d052 100644
--- a/gcc/config/aarch64/aarch64-opts.h
+++ b/gcc/config/aarch64/aarch64-opts.h
@@ -71,4 +71,14 @@  enum aarch64_code_model {
   AARCH64_CMODEL_LARGE
 };
 
+/* Function types -msign-return-address should sign.  */
+enum aarch64_function_type {
+  /* Don't sign any function.  */
+  AARCH64_FUNCTION_NONE,
+  /* Non-leaf functions.  */
+  AARCH64_FUNCTION_NON_LEAF,
+  /* All functions.  */
+  AARCH64_FUNCTION_ALL
+};
+
 #endif
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 29a3bd7..632dd47 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -386,6 +386,7 @@  void aarch64_emit_call_insn (rtx);
 void aarch64_register_pragmas (void);
 void aarch64_relayout_simd_types (void);
 void aarch64_reset_previous_fndecl (void);
+bool aarch64_return_address_signing_enabled (void);
 void aarch64_save_restore_target_globals (tree);
 
 /* Initialize builtins for SIMD intrinsics.  */
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 9dd75b0..3bcad76 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -3117,6 +3117,22 @@  aarch64_gen_load_pair (machine_mode mode, rtx reg1, rtx mem1, rtx reg2,
     }
 }
 
+/* Return TRUE if return address signing should be enabled for one function,
+   otherwise return FALSE.  */
+
+bool
+aarch64_return_address_signing_enabled (void)
+{
+  /* This function should only be called after frame laid out.   */
+  gcc_assert (cfun->machine->frame.laid_out);
+
+  /* If signing scope is AARCH64_FUNCTION_NON_LEAF, we only sign a leaf function
+     if it's LR is pushed onto stack.  */
+  return (aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL
+	  || (aarch64_ra_sign_scope == AARCH64_FUNCTION_NON_LEAF
+	      && cfun->machine->frame.reg_offset[LR_REGNUM] >= 0));
+}
+
 /* Emit code to save the callee-saved registers from register number START
    to LIMIT to the stack at the location starting at offset START_OFFSET,
    skipping any write-back candidates if SKIP_WB is true.  */
@@ -3535,6 +3551,10 @@  aarch64_expand_prologue (void)
   unsigned reg2 = cfun->machine->frame.wb_candidate2;
   rtx_insn *insn;
 
+  /* Sign return address for functions.  */
+  if (aarch64_return_address_signing_enabled ())
+    emit_insn (gen_pacisp ());
+
   if (flag_stack_usage_info)
     current_function_static_stack_size = frame_size;
 
@@ -3670,6 +3690,25 @@  aarch64_expand_epilogue (bool for_sibcall)
       RTX_FRAME_RELATED_P (insn) = 1;
     }
 
+  /* We prefer to emit the combined return/authenticate instruction RETAA,
+     however there are three cases in which we must instead emit an explicit
+     authentication instruction.
+
+	1) Sibcalls don't return in a normal way, so if we're about to call one
+	   we must authenticate.
+
+	2) The RETAA instruction is not available before ARMv8.3-A, so if we are
+	   generating code for !TARGET_ARMV8_3 we can't use it and must
+	   explicitly authenticate.
+
+	3) On an eh_return path we make extra stack adjustments to update the
+	   canonical frame address to be the exception handler's CFA.  We want
+	   to authenticate using the CFA of the function which calls eh_return.
+    */
+  if (aarch64_return_address_signing_enabled ()
+      && (for_sibcall || !TARGET_ARMV8_3 || crtl->calls_eh_return))
+    emit_insn (gen_autisp ());
+
   /* Stack adjustment for exception handler.  */
   if (crtl->calls_eh_return)
     {
@@ -8894,6 +8933,9 @@  aarch64_override_options (void)
     error ("Assembler does not support -mabi=ilp32");
 #endif
 
+  if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE && TARGET_ILP32)
+    sorry ("Return address signing is only supported for -mabi=lp64");
+
   /* Make sure we properly set up the explicit options.  */
   if ((aarch64_cpu_string && valid_cpu)
        || (aarch64_tune_string && valid_tune))
@@ -9277,6 +9319,8 @@  static const struct aarch64_attribute_info aarch64_attributes[] =
   { "cpu", aarch64_attr_custom, false, aarch64_handle_attr_cpu, OPT_mcpu_ },
   { "tune", aarch64_attr_custom, false, aarch64_handle_attr_tune,
      OPT_mtune_ },
+  { "sign-return-address", aarch64_attr_enum, false, NULL,
+     OPT_msign_return_address_ },
   { NULL, aarch64_attr_custom, false, NULL, OPT____ }
 };
 
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index bde4231..5dc68b7 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -67,6 +67,8 @@ 
 )
 
 (define_c_enum "unspec" [
+    UNSPEC_AUTI1716
+    UNSPEC_AUTISP
     UNSPEC_CASESI
     UNSPEC_CRC32B
     UNSPEC_CRC32CB
@@ -106,6 +108,8 @@ 
     UNSPEC_LD4_LANE
     UNSPEC_MB
     UNSPEC_NOP
+    UNSPEC_PACI1716
+    UNSPEC_PACISP
     UNSPEC_PRLG_STK
     UNSPEC_RBIT
     UNSPEC_SCVTF
@@ -135,6 +139,7 @@ 
     UNSPEC_RSQRTE
     UNSPEC_RSQRTS
     UNSPEC_NZCV
+    UNSPEC_XPACLRI
 ])
 
 (define_c_enum "unspecv" [
@@ -575,7 +580,14 @@ 
 (define_insn "*do_return"
   [(return)]
   ""
-  "ret"
+  {
+    if (aarch64_return_address_signing_enabled ()
+	&& TARGET_ARMV8_3
+	&& !crtl->calls_eh_return)
+      return "retaa";
+
+    return "ret";
+  }
   [(set_attr "type" "branch")]
 )
 
@@ -5341,6 +5353,36 @@ 
   [(set_attr "length" "0")]
 )
 
+;; Pointer authentication patterns are always provided.  In architecture
+;; revisions prior to ARMv8.3-A these HINT instructions operate as NOPs.
+;; This lets the user write portable software which authenticates pointers
+;; when run on something which implements ARMv8.3-A, and which runs
+;; correctly, but does not authenticate pointers, where ARMv8.3-A is not
+;; implemented.
+
+;; Signing/Authenticating R30 using SP as the salt.
+(define_insn "<pauth_mnem_prefix>sp"
+  [(set (reg:DI R30_REGNUM)
+	(unspec:DI [(reg:DI R30_REGNUM) (reg:DI SP_REGNUM)] PAUTH_LR_SP))]
+  ""
+  "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>asp";
+)
+
+;; Signing/Authenticating X17 using X16 as the salt.
+(define_insn "<pauth_mnem_prefix>1716"
+  [(set (reg:DI R17_REGNUM)
+	(unspec:DI [(reg:DI R17_REGNUM) (reg:DI R16_REGNUM)] PAUTH_17_16))]
+  ""
+  "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>a1716";
+)
+
+;; Stripping the signature in R30.
+(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 56b920d..5436884 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 e2377c1..c59d31e 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 30bdcf0..4516a86 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 on which return address signing will be applied.  The
+behaviour 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 aa0ac8b..c75d4b3 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -14044,6 +14044,14 @@  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 on which return address signing will be applied.
+Permissible values are @samp{none}, which disables return address signing,
+@samp{non-leaf}, which enables pointer signing for functions which are not leaf
+functions, and @samp{all}, which enables pointer signing for all functions.  The
+default value is @samp{none}.
+
 @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 0000000..fda72a4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c
@@ -0,0 +1,51 @@ 
+/* Testing return address signing where no combined instructions used.  */
+/* { dg-do compile } */
+/* { dg-options "-O2 -msign-return-address=all" } */
+
+int foo (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 */
+}
+
+/* eh_return.  */
+void __attribute__ ((target ("arch=armv8.3-a")))
+func4 (long offset, void *handler, int *ptr, int imm1, int imm2)
+{
+  /* paciasp */
+  *ptr = imm1 + foo (imm1) + imm2;
+  __builtin_eh_return (offset, handler);
+  /* autiasp */
+  return;
+}
+
+/* { dg-final { scan-assembler-times "autiasp" 4 } } */
+/* { dg-final { scan-assembler-times "paciasp" 4 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_2.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_2.c
new file mode 100644
index 0000000..54fe47a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_2.c
@@ -0,0 +1,17 @@ 
+/* Testing return address signing where combined instructions used.  */
+/* { dg-do compile } */
+/* { dg-options "-O2 -msign-return-address=all" } */
+
+int foo (int);
+int bar (int, int);
+
+int __attribute__ ((target ("arch=armv8.3-a")))
+func1 (int a, int b, int c)
+{
+  /* paciasp */
+  return a + foo (b) + c;
+  /* retaa */
+}
+
+/* { dg-final { scan-assembler-times "paciasp" 1 } } */
+/* { dg-final { scan-assembler-times "retaa" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_3.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_3.c
new file mode 100644
index 0000000..adc5eff
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_3.c
@@ -0,0 +1,21 @@ 
+/* Testing the disable of return address signing.  */
+/* { dg-do compile } */
+/* { dg-options "-O2 -msign-return-address=all" } */
+
+int bar (int, int);
+
+int __attribute__ ((target ("arch=armv8.3-a, sign-return-address=non-leaf")))
+func1_leaf (int a, int b, int c, int d)
+{
+  return a + b + c + d;
+}
+
+int __attribute__ ((target ("arch=armv8.3-a, sign-return-address=none")))
+func2_none (int a, int b, int c, int d)
+{
+  return c + bar (a, b) + d;
+}
+
+/* { dg-final { scan-assembler-not "paciasp" } } */
+/* { dg-final { scan-assembler-not "autiasp" } } */
+/* { dg-final { scan-assembler-not "retaa" } } */