diff mbox

[9/9,RFC,AArch64] Accelerate -fstack-protector through pointer authentication extension

Message ID f402afd5-ca4e-3726-8a6d-97e08f27a4fb@foss.arm.com
State New
Headers show

Commit Message

Jiong Wang Nov. 11, 2016, 6:37 p.m. UTC
This patch accelerates GCC's existed -fstack-protector using ARMv8.3-A pointer
authentication instructions.

Given AArch64 currently has the following stack layout:

   | caller's LR
   | ....
   |------------
   | canary        <- sentinel for -fstack-protector
   | locals (buffer located here)
   |------------
   |
   | other callees
   |
   | callee's LR  <- sentinel for -msign-return-address
   |------------
   |

we can switch locals and callees,

     | ...
     | vararg
     |------------
     | other callee
     |------------
     | LR
     |------------
     | locals (buffer located here)

We then sign LR and make it serve as canary value.  There are several benefits
of this approach:

   *  It's evetually -msign-return-address + swap locals and callees areas.
   *  Require nearly no modifications on prologue and epilogue, avoid making them
      complexer.
   *  No need of any other runtime support, libssp is not required.

The runtime overhead before and after this patch will be:

   o canary insert

     GCC default SSP runtime was loading from global variable "__stack_chk_guard"
     initilized in libssp:

       adrp    x19, _GLOBAL_OFFSET_TABLE_
       ldr     x19, [x19, #:gotpage_lo15:__stack_chk_guard]
       ldr     x2, [x19]
       str     x2, [x29, 56]

     this patch accelerats into:

       sign lr

   o canary check

     GCC default SSP runtime was reloading from stack, then comparing with
     original value and branch to abort function:

       ldr     x2, [x29, 56]
       ldr     x1, [x19]
       eor     x1, x2, x1
       cbnz    x1, .L5
       ...
       ret
       .L5:
       bl      __stack_chk_fail

     acclerated into:

       aut lr + ret or retaa
     the the canary value (signed LR) fails authentication, the return to invalid
     address will cause exception.

NOTE, this approach however requires DWARF change as the original LR is signed,
the binary needs new libgcc to make sure c++ eh works correctly.  Given this
acceleration already needs the user specify -mstack-protector-dialect=pauth
which means the target platform largely should have install new libgcc, otherwise
you can't utilize new pointer authentication features.

gcc/
2016-11-11  Jiong Wang  <jiong.wang@arm.com>

         * config/aarch64/aarch64-opts.h (aarch64_stack_protector_type): New
         enum.
         (aarch64_layout_frame): Swap callees and locals when
         -mstack-protector-dialect=pauth specified.
         (aarch64_expand_prologue): Use AARCH64_PAUTH_SSP_OR_RA_SIGN instead
         of AARCH64_ENABLE_RETURN_ADDRESS_SIGN.
         (aarch64_expand_epilogue): Likewise.
         * config/aarch64/aarch64.md (*do_return): Likewise.
         (aarch64_override_options): Sanity check for ILP32 and TARGET_PAUTH.
         * config/aarch64/aarch64.h (AARCH64_PAUTH_SSP_OPTION, AARCH64_PAUTH_SSP,
         AARCH64_PAUTH_SSP_OR_RA_SIGN, LINK_SSP_SPEC): New defines.
         * config/aarch64/aarch64.opt (-mstack-protector-dialect=): New option.
         * doc/invoke.texi (AArch64 Options): Documents
         -mstack-protector-dialect=.

Comments

Richard Earnshaw (lists) Feb. 15, 2017, 3:45 p.m. UTC | #1
On 18/01/17 17:10, Jiong Wang wrote:
>> NOTE, this approach however requires DWARF change as the original LR

>> is signed,

>> the binary needs new libgcc to make sure c++ eh works correctly. 

>> Given this

>> acceleration already needs the user specify

>> -mstack-protector-dialect=pauth

>> which means the target platform largely should have install new

>> libgcc, otherwise

>> you can't utilize new pointer authentication features.

>>

>> gcc/

>> 2016-11-11  Jiong Wang  <jiong.wang@arm.com>

>>

>>         * config/aarch64/aarch64-opts.h

>> (aarch64_stack_protector_type): New

>>         enum.

>>         (aarch64_layout_frame): Swap callees and locals when

>>         -mstack-protector-dialect=pauth specified.

>>         (aarch64_expand_prologue): Use AARCH64_PAUTH_SSP_OR_RA_SIGN

>> instead

>>         of AARCH64_ENABLE_RETURN_ADDRESS_SIGN.

>>         (aarch64_expand_epilogue): Likewise.

>>         * config/aarch64/aarch64.md (*do_return): Likewise.

>>         (aarch64_override_options): Sanity check for ILP32 and

>> TARGET_PAUTH.

>>         * config/aarch64/aarch64.h (AARCH64_PAUTH_SSP_OPTION,

>> AARCH64_PAUTH_SSP,

>>         AARCH64_PAUTH_SSP_OR_RA_SIGN, LINK_SSP_SPEC): New defines.

>>         * config/aarch64/aarch64.opt (-mstack-protector-dialect=): New

>> option.

>>         * doc/invoke.texi (AArch64 Options): Documents

>>         -mstack-protector-dialect=.

>>

>                                                          Patch updated

> to migrate to TARGET_STACK_PROTECT_RUNTIME_ENABLED_P.

> 

> aarch64 cross check OK with the following options enabled on all testcases.

>     -fstack-protector-all -mstack-protector-pauth

> 

> OK for trunk?

>                                                                     gcc/

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

>            * config/aarch64/aarch64-protos.h

>         (aarch64_pauth_stack_protector_enabled): New declaration.

>         * config/aarch64/aarch64.c (aarch64_layout_frame): Swap

> callee-save area

>         and locals area when aarch64_pauth_stack_protector_enabled

> returns true.

>         (aarch64_stack_protect_runtime_enabled): New function.

>         (aarch64_pauth_stack_protector_enabled): New function.

>         (aarch64_return_address_signing_enabled): Enabled by

>         aarch64_pauth_stack_protector_enabled.

>         (aarch64_override_options): Sanity check for

> -mstack-protector-pauth.

>         (TARGET_STACK_PROTECT_RUNTIME_ENABLED_P): Define.

>         * config/aarch64/aarch64.h (LINK_SSP_SPEC): Likewise.

>         * config/aarch64/aarch64.opt (-mstack-protector-pauth): New option.

>         * doc/invoke.texi (AArch64 Options): Documents

> -mstack-protector-pauth.

> 

> gcc/testsuite/

>         * gcc.target/aarch64/stack_protector_1.c: New test.

> 

> 

> 1.patch

> 

> 

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

> index 632dd4768d82c340ae4e9b4a93206743756c06e7..a3ad623eef498d00b52d24bf02a5748fad576c3d 100644

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

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

> @@ -383,6 +383,7 @@ void aarch64_init_cumulative_args (CUMULATIVE_ARGS *, const_tree, rtx,

>  void aarch64_init_expanders (void);

>  void aarch64_init_simd_builtins (void);

>  void aarch64_emit_call_insn (rtx);

> +bool aarch64_pauth_stack_protector_enabled (void);

>  void aarch64_register_pragmas (void);

>  void aarch64_relayout_simd_types (void);

>  void aarch64_reset_previous_fndecl (void);

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

> index 3718ad1b3bf27c6bdb9e74831fd660e617cccbde..dd742d37ab6fc6fb5085e1c6b5d86d5ce1ce5f8a 100644

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

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

> @@ -958,4 +958,11 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);

>  extern tree aarch64_fp16_type_node;

>  extern tree aarch64_fp16_ptr_type_node;

>  

> +#ifndef TARGET_LIBC_PROVIDES_SSP

> +#define LINK_SSP_SPEC "%{!mstack-protector-pauth:\

> +			 %{fstack-protector|fstack-protector-all\

> +			   |fstack-protector-strong|fstack-protector-explicit:\

> +			   -lssp_nonshared -lssp}}"

> +#endif

> +


I don't think we want to suppress this.  PAUTH pased stack protections
isn't an all-or-nothing solution.  What if some object files are built
with traditional -fstack-protector code?

If the library isn't referenced by any of the input objects we won't
pull anything useful in from the library, so leaving it in the link list
should be harmless.


>  #endif /* GCC_AARCH64_H */

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

> index 6451b08191cf1a44aed502930da8603111f6e8ca..461f7b59584af9315accaecc0256abc9a2df4350 100644

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

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

> @@ -2884,8 +2884,28 @@ aarch64_layout_frame (void)

>    else if (cfun->machine->frame.wb_candidate1 != INVALID_REGNUM)

>      max_push_offset = 256;

>  

> -  if (cfun->machine->frame.frame_size < max_push_offset

> -      && crtl->outgoing_args_size == 0)

> +  /* Swap callee-save and local variables area to make callee-save which

> +     includes return address register X30/LR position above local variables

> +     that any local buffer overflow will override return address.  */

> +  if (aarch64_pauth_stack_protector_enabled ())

> +    {

> +      if (varargs_and_saved_regs_size < max_push_offset)

> +	/* stp reg1, reg2, [sp, -varargs_and_saved_regs_size]!.  */

> +	cfun->machine->frame.callee_adjust = varargs_and_saved_regs_size;

> +      else

> +	/* sub sp, sp, varargs_and_saved_regs_size.  */

> +	cfun->machine->frame.initial_adjust = varargs_and_saved_regs_size;

> +

> +      /* Any final_adjust needed.  */

> +      cfun->machine->frame.final_adjust

> +	= cfun->machine->frame.frame_size - varargs_and_saved_regs_size;

> +

> +      /* Point hard_fp_offset and locals_offset to correct offsets.  */

> +      cfun->machine->frame.hard_fp_offset = varargs_and_saved_regs_size;

> +      cfun->machine->frame.locals_offset = cfun->machine->frame.hard_fp_offset;

> +    }

> +  else if (cfun->machine->frame.frame_size < max_push_offset

> +	   && crtl->outgoing_args_size == 0)

>      {

>        /* Simple, small frame with no outgoing arguments:

>  	 stp reg1, reg2, [sp, -frame_size]!

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

>      }

>  }

>  

> +/* Implement the TARGET_STACK_PROTECT_RUNTIME_ENABLED_P.  */

> +

> +static bool

> +aarch64_stack_protect_runtime_enabled (void)

> +{

> +  return !(TARGET_AARCH64_SSP_PAUTH && TARGET_ARMV8_3);

> +}

> +

> +/* Return TRUE if pointer authentication accelerated -fstack-protector is

> +   enabled.  */

> +

> +bool

> +aarch64_pauth_stack_protector_enabled (void)

> +{

> +  /* Enable if this function is identified by GCC to be with buffer over flow

> +     risk and we are not using GCC's standard libssp runtime.  */

> +  return (crtl->stack_protect_guard

> +	  && !aarch64_stack_protect_runtime_enabled ());

> +}

> +

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

>     otherwise return FALSE.  */

>  

> @@ -3127,10 +3167,12 @@ aarch64_return_address_signing_enabled (void)

>    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));

> +     if it's LR is pushed onto stack.  Pointer authentication based stack

> +     protector also implies return address signing.  */

> +  return ((aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL

> +	   || (aarch64_ra_sign_scope == AARCH64_FUNCTION_NON_LEAF

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

> +	  || aarch64_pauth_stack_protector_enabled ());

>  }


Do we really want to force signing of ALL leaf functions if using PAUTH
based signing?  Surely we only need to check those that might be
vulnerable to buffer overruns.

R.

>  

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

> @@ -8944,6 +8986,14 @@ aarch64_override_options (void)

>    if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE && TARGET_ILP32)

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

>  

> +  if (TARGET_AARCH64_SSP_PAUTH && TARGET_ILP32)

> +    sorry ("Pointer authentication based -fstack-protector is only supported "

> +	   "on -mabi=lp64.");

> +

> +  if (TARGET_AARCH64_SSP_PAUTH && !TARGET_ARMV8_3)

> +    error ("Pointer authentication based -fstack-protector is only supported "

> +	   "on architecture with pointer authentication extension.");

> +

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

>    if ((aarch64_cpu_string && valid_cpu)

>         || (aarch64_tune_string && valid_tune))

> @@ -14859,6 +14909,10 @@ aarch64_libgcc_floating_mode_supported_p

>  #undef TARGET_SETUP_INCOMING_VARARGS

>  #define TARGET_SETUP_INCOMING_VARARGS aarch64_setup_incoming_varargs

>  

> +#undef TARGET_STACK_PROTECT_RUNTIME_ENABLED_P

> +#define TARGET_STACK_PROTECT_RUNTIME_ENABLED_P \

> +  aarch64_stack_protect_runtime_enabled

> +

>  #undef TARGET_STRUCT_VALUE_RTX

>  #define TARGET_STRUCT_VALUE_RTX   aarch64_struct_value_rtx

>  

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

> index 54368848bbb249949921a3018d927c4bd61b1fbd..b157e51fd37d9040ca0a63c1f823f2ad70c8c17e 100644

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

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

> @@ -188,3 +188,7 @@ single precision and to 32 bits for double precision.

>  mverbose-cost-dump

>  Common Undocumented Var(flag_aarch64_verbose_cost)

>  Enables verbose cost model dummping in the debug dump files.

> +

> +mstack-protector-pauth

> +Target Report RejectNegative Mask(AARCH64_SSP_PAUTH) Save

> +Enable pointer authentication accelerated stack protector.

> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi

> index c75d4b3697bae8805e13168d47066a1d0dd28df7..4eaefb4fc5e4eee92ba429ca5d23d314aa6f3d29 100644

> --- a/gcc/doc/invoke.texi

> +++ b/gcc/doc/invoke.texi

> @@ -14052,6 +14052,11 @@ Permissible values are @samp{none}, which disables return address signing,

>  functions, and @samp{all}, which enables pointer signing for all functions.  The

>  default value is @samp{none}.

>  

> +@item -mstack-protector-pauth

> +@opindex mstack-protector-pauth

> +Use ARMv8.3-A Pointer Authentication Extension to accelerate GCC

> +-fstack-protector.

> +

>  @end table

>  

>  @subsubsection @option{-march} and @option{-mcpu} Feature Modifiers

> diff --git a/gcc/testsuite/gcc.target/aarch64/stack_protector_1.c b/gcc/testsuite/gcc.target/aarch64/stack_protector_1.c

> new file mode 100644

> index 0000000000000000000000000000000000000000..56741bb38f4a2e95b82f04fe8009bcd6b1eb3f26

> --- /dev/null

> +++ b/gcc/testsuite/gcc.target/aarch64/stack_protector_1.c

> @@ -0,0 +1,23 @@

> +/* { dg-do compile } */

> +/* { dg-options "-O2 -fstack-protector-all -mstack-protector-pauth" } */

> +

> +int foo (int);

> +

> +int __attribute__ ((target ("arch=armv8.3-a")))

> +func1 (int a, int b, int c)

> +{

> +  /* paciasp */

> +  return a + foo (b) + c;

> +  /* retaa */

> +}

> +

> +/* Shouldn't enable pauth acceleration as it's ARMv8.2-A.  */

> +

> +int __attribute__ ((target ("arch=armv8.2-a")))

> +func2 (int a, int b, int c)

> +{

> +  return a + foo (b) + c;

> +}

> +

> +/* { dg-final { scan-assembler-times "paciasp" 1 } } */

> +/* { dg-final { scan-assembler-times "retaa" 1 } } */

>
Jiong Wang Feb. 15, 2017, 5:07 p.m. UTC | #2
On 15/02/17 15:45, Richard Earnshaw (lists) wrote:
> On 18/01/17 17:10, Jiong Wang wrote:

>>> NOTE, this approach however requires DWARF change as the original LR

>>> is signed,

>>> the binary needs new libgcc to make sure c++ eh works correctly.

>>> Given this

>>> acceleration already needs the user specify

>>> -mstack-protector-dialect=pauth

>>> which means the target platform largely should have install new

>>> libgcc, otherwise

>>> you can't utilize new pointer authentication features.

>>>

>>> gcc/

>>> 2016-11-11  Jiong Wang  <jiong.wang@arm.com>

>>>

>>>          * config/aarch64/aarch64-opts.h

>>> (aarch64_stack_protector_type): New

>>>          enum.

>>>          (aarch64_layout_frame): Swap callees and locals when

>>>          -mstack-protector-dialect=pauth specified.

>>>          (aarch64_expand_prologue): Use AARCH64_PAUTH_SSP_OR_RA_SIGN

>>> instead

>>>          of AARCH64_ENABLE_RETURN_ADDRESS_SIGN.

>>>          (aarch64_expand_epilogue): Likewise.

>>>          * config/aarch64/aarch64.md (*do_return): Likewise.

>>>          (aarch64_override_options): Sanity check for ILP32 and

>>> TARGET_PAUTH.

>>>          * config/aarch64/aarch64.h (AARCH64_PAUTH_SSP_OPTION,

>>> AARCH64_PAUTH_SSP,

>>>          AARCH64_PAUTH_SSP_OR_RA_SIGN, LINK_SSP_SPEC): New defines.

>>>          * config/aarch64/aarch64.opt (-mstack-protector-dialect=): New

>>> option.

>>>          * doc/invoke.texi (AArch64 Options): Documents

>>>          -mstack-protector-dialect=.

>>>

>>                                                           Patch updated

>> to migrate to TARGET_STACK_PROTECT_RUNTIME_ENABLED_P.

>>

>> aarch64 cross check OK with the following options enabled on all testcases.

>>      -fstack-protector-all -mstack-protector-pauth

>>

>> OK for trunk?

>>                                                                      gcc/

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

>>             * config/aarch64/aarch64-protos.h

>>          (aarch64_pauth_stack_protector_enabled): New declaration.

>>          * config/aarch64/aarch64.c (aarch64_layout_frame): Swap

>> callee-save area

>>          and locals area when aarch64_pauth_stack_protector_enabled

>> returns true.

>>          (aarch64_stack_protect_runtime_enabled): New function.

>>          (aarch64_pauth_stack_protector_enabled): New function.

>>          (aarch64_return_address_signing_enabled): Enabled by

>>          aarch64_pauth_stack_protector_enabled.

>>          (aarch64_override_options): Sanity check for

>> -mstack-protector-pauth.

>>          (TARGET_STACK_PROTECT_RUNTIME_ENABLED_P): Define.

>>          * config/aarch64/aarch64.h (LINK_SSP_SPEC): Likewise.

>>          * config/aarch64/aarch64.opt (-mstack-protector-pauth): New option.

>>          * doc/invoke.texi (AArch64 Options): Documents

>> -mstack-protector-pauth.

>>

>> gcc/testsuite/

>>          * gcc.target/aarch64/stack_protector_1.c: New test.

>>

>>

>> 1.patch

>>

>>

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

>> index 632dd4768d82c340ae4e9b4a93206743756c06e7..a3ad623eef498d00b52d24bf02a5748fad576c3d 100644

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

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

>> @@ -383,6 +383,7 @@ void aarch64_init_cumulative_args (CUMULATIVE_ARGS *, const_tree, rtx,

>>   void aarch64_init_expanders (void);

>>   void aarch64_init_simd_builtins (void);

>>   void aarch64_emit_call_insn (rtx);

>> +bool aarch64_pauth_stack_protector_enabled (void);

>>   void aarch64_register_pragmas (void);

>>   void aarch64_relayout_simd_types (void);

>>   void aarch64_reset_previous_fndecl (void);

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

>> index 3718ad1b3bf27c6bdb9e74831fd660e617cccbde..dd742d37ab6fc6fb5085e1c6b5d86d5ce1ce5f8a 100644

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

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

>> @@ -958,4 +958,11 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);

>>   extern tree aarch64_fp16_type_node;

>>   extern tree aarch64_fp16_ptr_type_node;

>>   

>> +#ifndef TARGET_LIBC_PROVIDES_SSP

>> +#define LINK_SSP_SPEC "%{!mstack-protector-pauth:\

>> +			 %{fstack-protector|fstack-protector-all\

>> +			   |fstack-protector-strong|fstack-protector-explicit:\

>> +			   -lssp_nonshared -lssp}}"

>> +#endif

>> +

> I don't think we want to suppress this.  PAUTH pased stack protections

> isn't an all-or-nothing solution.  What if some object files are built

> with traditional -fstack-protector code?


I had done a decription on this in the ping email (changed summary may caused
trouble to email client)

--
Code compiled with "-mstack-protector-pauth" can co-work with code compiled
without "-mstack-protector-pauth".  The only problem is when
"-mstack-protector-pauth" is specified, "-lssp/-lssp_nonshared" won't be implied
as the software runtime supports are not required any more.  So if the user has
some object files compiled using default stack protector and wants them to be
linked with object files compiled using "-mstack-protector-pauth", if
"-mstack-protector-pauth" appear in the final command line and "gcc" is used as
linker driver, then "-lssp/-lssp_nonshared" needs to be specified explicitly.
--

Generally, after this patch, if there are object files comes from tranditional
-fstack-protector then the user is responsible to specify -lssp/-lssp-nonshared.

My intention to remove ssp library when -fstack-protector-pauth specified was to
make pauth based stack protector also be available on those configurations where
libssp is not enabled or not available.

Does this make sense?

>

> If the library isn't referenced by any of the input objects we won't

> pull anything useful in from the library, so leaving it in the link list

> should be harmless.


For linux target, I agree.

>> +  return ((aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL

>> +	   || (aarch64_ra_sign_scope == AARCH64_FUNCTION_NON_LEAF

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

>> +	  || aarch64_pauth_stack_protector_enabled ());

>>   }

> Do we really want to force signing of ALL leaf functions if using PAUTH

> based signing?  Surely we only need to check those that might be

> vulnerable to buffer overruns.


aarch64_pauth_stack_protector_enabled () is already checking that, it will
return true only if crtl->stack_protect_guard is not NULL.  While
crtl->stack_protect_guard will only be created for functions which gcc
middle-end (create_stack_guard) identified to be vulnerable to buffer overruns.

Regards,
Jiong
diff mbox

Patch

diff --git a/gcc/config/aarch64/aarch64-opts.h b/gcc/config/aarch64/aarch64-opts.h
index 41c14b38a6188d399eb04baca2896e033c03ff1b..ff464ea5675146d62f0b676fe776f882fc1b8d80 100644
--- a/gcc/config/aarch64/aarch64-opts.h
+++ b/gcc/config/aarch64/aarch64-opts.h
@@ -99,4 +99,10 @@  enum aarch64_function_type {
   AARCH64_FUNCTION_ALL
 };
 
+/* GCC standard stack protector (Canary insertion based) types for AArch64.  */
+enum aarch64_stack_protector_type {
+  STACK_PROTECTOR_TRAD,
+  STACK_PROTECTOR_PAUTH
+};
+
 #endif
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index 907e8bdf5b4961b3107dcd5a481de28335e4be89..73ef2677a11450fe21f765011317bd3367ef0d94 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -982,4 +982,25 @@  enum aarch64_pauth_action_type
   AARCH64_PAUTH_AUTH
 };
 
+/* Pointer authentication accelerated -fstack-protector.  */
+#define AARCH64_PAUTH_SSP_OPTION \
+  (TARGET_PAUTH && aarch64_stack_protector_dialect == STACK_PROTECTOR_PAUTH)
+
+#define AARCH64_PAUTH_SSP \
+  (crtl->stack_protect_guard && AARCH64_PAUTH_SSP_OPTION)
+
+#define AARCH64_PAUTH_SSP_OR_RA_SIGN \
+  (AARCH64_PAUTH_SSP || AARCH64_ENABLE_RETURN_ADDRESS_SIGN)
+
+#ifndef TARGET_LIBC_PROVIDES_SSP
+#define LINK_SSP_SPEC "%{!mstack-protector-dialect=pauth:\
+			 %{fstack-protector|fstack-protector-all\
+			   |fstack-protector-strong|fstack-protector-explicit:\
+			   -lssp_nonshared -lssp}}"
+#endif
+
+/* Don't use GCC default SSP runtime if pointer authentication acceleration
+   enabled.  */
+#define ENABLE_DEFAULT_SSP_RUNTIME  !(AARCH64_PAUTH_SSP_OPTION)
+
 #endif /* GCC_AARCH64_H */
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index cae177dca511fdb909ef82c972d3bbdebab215e2..c469baf92268ff894f5cf0ea9f5dbd4180714b98 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -2993,6 +2993,15 @@  aarch64_layout_frame (void)
 	= cfun->machine->frame.frame_size - cfun->machine->frame.initial_adjust;
     }
 
+  if (AARCH64_PAUTH_SSP)
+    {
+      cfun->machine->frame.callee_adjust = varargs_and_saved_regs_size;
+      cfun->machine->frame.final_adjust
+	= cfun->machine->frame.frame_size - cfun->machine->frame.callee_adjust;
+      cfun->machine->frame.hard_fp_offset = cfun->machine->frame.callee_adjust;
+      cfun->machine->frame.locals_offset = cfun->machine->frame.hard_fp_offset;
+    }
+
   cfun->machine->frame.laid_out = true;
 }
 
@@ -3203,7 +3212,7 @@  aarch64_save_callee_saves (machine_mode mode, HOST_WIDE_INT start_offset,
 
       RTX_FRAME_RELATED_P (insn) = 1;
 
-      if (AARCH64_ENABLE_RETURN_ADDRESS_SIGN && lr_pair_reg != INVALID_REGNUM)
+      if (AARCH64_PAUTH_SSP_OR_RA_SIGN && lr_pair_reg != INVALID_REGNUM)
 	{
 	  rtx cfi_ops = NULL_RTX;
 
@@ -3335,7 +3344,7 @@  aarch64_expand_prologue (void)
 
   /* Do return address signing for all functions, even those for which LR is not
      pushed onto stack.  */
-  if (AARCH64_ENABLE_RETURN_ADDRESS_SIGN)
+  if (AARCH64_PAUTH_SSP_OR_RA_SIGN)
     {
       insn = emit_insn (gen_sign_reg (gen_rtx_REG (Pmode, LR_REGNUM),
 				      gen_rtx_REG (Pmode, LR_REGNUM),
@@ -3368,7 +3377,7 @@  aarch64_expand_prologue (void)
       aarch64_push_regs (reg1, reg2, callee_adjust);
       /* Generate return address signing dwarf annotation when
 	 omit-frame-pointer.  */
-      if (AARCH64_ENABLE_RETURN_ADDRESS_SIGN
+      if (AARCH64_PAUTH_SSP_OR_RA_SIGN
 	  && (reg1 == LR_REGNUM || reg2 == LR_REGNUM))
 	{
 	  rtx cfi_ops = NULL_RTX;
@@ -3503,7 +3512,7 @@  aarch64_expand_epilogue (bool for_sibcall)
       rtx new_cfa = plus_constant (Pmode, stack_pointer_rtx, initial_adjust);
       cfi_ops = alloc_reg_note (REG_CFA_DEF_CFA, new_cfa, cfi_ops);
 
-      if (AARCH64_ENABLE_RETURN_ADDRESS_SIGN)
+      if (AARCH64_PAUTH_SSP_OR_RA_SIGN)
 	REG_NOTES (insn) = aarch64_attach_ra_auth_dwarf_note (cfi_ops, 0);
       else
 	REG_NOTES (insn) = cfi_ops;
@@ -3528,7 +3537,7 @@  aarch64_expand_epilogue (bool for_sibcall)
      authentication, as the following stack adjustment will update CFA to
      handler's CFA while we want to use the CFA of the function which calls
      __builtin_eh_return.  */
-  if (AARCH64_ENABLE_RETURN_ADDRESS_SIGN
+  if (AARCH64_PAUTH_SSP_OR_RA_SIGN
       && (for_sibcall || !TARGET_PAUTH || crtl->calls_eh_return))
     {
       insn = emit_insn (gen_auth_reg (gen_rtx_REG (Pmode, LR_REGNUM),
@@ -8737,6 +8746,14 @@  aarch64_override_options (void)
   if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE && TARGET_ILP32)
     error ("Return address signing is only supported on LP64");
 
+  if (aarch64_stack_protector_dialect == STACK_PROTECTOR_PAUTH && TARGET_ILP32)
+    error ("Pointer authentication based -fstack-protector is only supported "
+	   "on LP64.");
+
+  if (aarch64_stack_protector_dialect == STACK_PROTECTOR_PAUTH && !TARGET_PAUTH)
+    error ("Pointer authentication based -fstack-protector is only supported "
+	   "on architecture with pointer authentication extension.");
+
   /* Make sure we properly set up the explicit options.  */
   if ((aarch64_cpu_string && valid_cpu)
        || (aarch64_tune_string && valid_tune))
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 754ea00d2f3027f0d4c57e1a2c1ea06d35135259..4fd94d23b7570fbcdb931e1e0a03257088c42955 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -581,9 +581,7 @@ 
   [(return)]
   ""
   {
-    if (AARCH64_ENABLE_RETURN_ADDRESS_SIGN
-	&& TARGET_PAUTH
-	&& !crtl->calls_eh_return)
+    if (AARCH64_PAUTH_SSP_OR_RA_SIGN && TARGET_PAUTH && !crtl->calls_eh_return)
       {
 	if (aarch64_pauth_key == AARCH64_PAUTH_IKEY_A)
 	  return "retaa";
diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt
index 0b172021dbba918ecc5a7d953cfcbdf8edfe0b5f..781f68f6b7789c386c4e2a21fef797ea8fc48810 100644
--- a/gcc/config/aarch64/aarch64.opt
+++ b/gcc/config/aarch64/aarch64.opt
@@ -198,3 +198,17 @@  Common Var(flag_mlow_precision_div) Optimization
 Enable the division approximation.  Enabling this reduces
 precision of division results to about 16 bits for
 single precision and to 32 bits for double precision.
+
+Enum
+Name(stack_protector_type) Type(enum aarch64_stack_protector_type)
+The possible stack protector dialects:
+
+EnumValue
+Enum(stack_protector_type) String(trad) Value(STACK_PROTECTOR_TRAD)
+
+EnumValue
+Enum(stack_protector_type) String(pauth) Value(STACK_PROTECTOR_PAUTH)
+
+mstack-protector-dialect=
+Target RejectNegative Joined Enum(stack_protector_type) Var(aarch64_stack_protector_dialect) Init(STACK_PROTECTOR_TRAD) Save
+Specify stack protector dialect.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index e7f842f9d21bd4e94eec9955851d8632837ba2c3..32c5cee54c8897bfee3d135a548fa70ed555e1fe 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -13357,6 +13357,12 @@  Select the key used for return address signing.  Permissible values are
 @samp{a_key} for A key and @samp{b_key} for B key.  @samp{a_key} is the default
 value.
 
+@item -mstack-protector-dialect=@var{dialect}
+@opindex mstack-protector-dialect
+Select the dialect for GCC -fstack-protector.  @samp{trad} for GCC default
+implementation and @samp{pauth} for pointer authentication accelerated
+implementation for AArch64 LP64.
+
 @end table
 
 @subsubsection @option{-march} and @option{-mcpu} Feature Modifiers