Re: [PATCH v5 1/1] [ARM] Add support for TLS register based stack protector canary access

2022-01-20 Thread Ard Biesheuvel via Gcc-patches
On Wed, 19 Jan 2022 at 18:02, Ard Biesheuvel  wrote:
>
> On Wed, 19 Jan 2022 at 17:54, Kyrylo Tkachov  wrote:
> >
> > Hi Ard,
> >
> > > -Original Message-
> > > From: Gcc-patches  > > bounces+kyrylo.tkachov=arm@gcc.gnu.org> On Behalf Of Ard
> > > Biesheuvel via Gcc-patches
> > > Sent: Monday, November 15, 2021 6:04 PM
> > > To: linux-harden...@vger.kernel.org
> > > Cc: Richard Sandiford ;
> > > thomas.preudho...@celest.fr; Keith Packard ;
> > > gcc-patches@gcc.gnu.org; Kyrylo Tkachov ; Ard
> > > Biesheuvel 
> > > Subject: [PATCH v5 1/1] [ARM] Add support for TLS register based stack
> > > protector canary access
> > >
> > > Add support for accessing the stack canary value via the TLS register,
> > > so that multiple threads running in the same address space can use
> > > distinct canary values. This is intended for the Linux kernel running in
> > > SMP mode, where processes entering the kernel are essentially threads
> > > running the same program concurrently: using a global variable for the
> > > canary in that context is problematic because it can never be rotated,
> > > and so the OS is forced to use the same value as long as it remains up.
> > >
> > > Using the TLS register to index the stack canary helps with this, as it
> > > allows each CPU to context switch the TLS register along with the rest
> > > of the process, permitting each process to use its own value for the
> > > stack canary.
> >
> > I've tested this patch on an arm-none-linux-gnueabihf target and the 
> > results look clean.
> > Have you tested this patch with a kernel build as well? (since the 
> > functionality is intended for that use).
>
> Of course.
>
> > If so, the patch is okay but please rebase it and repost so that we can 
> > commit it taking into account
> >
>
> Will do.

I have sent out my v6 - please let me know if there is anything else I
need to do to get this landed.

Thanks,
Ard.


Re: [PATCH v5 1/1] [ARM] Add support for TLS register based stack protector canary access

2022-01-19 Thread Ard Biesheuvel via Gcc-patches
On Wed, 19 Jan 2022 at 17:54, Kyrylo Tkachov  wrote:
>
> Hi Ard,
>
> > -Original Message-
> > From: Gcc-patches  > bounces+kyrylo.tkachov=arm@gcc.gnu.org> On Behalf Of Ard
> > Biesheuvel via Gcc-patches
> > Sent: Monday, November 15, 2021 6:04 PM
> > To: linux-harden...@vger.kernel.org
> > Cc: Richard Sandiford ;
> > thomas.preudho...@celest.fr; Keith Packard ;
> > gcc-patches@gcc.gnu.org; Kyrylo Tkachov ; Ard
> > Biesheuvel 
> > Subject: [PATCH v5 1/1] [ARM] Add support for TLS register based stack
> > protector canary access
> >
> > Add support for accessing the stack canary value via the TLS register,
> > so that multiple threads running in the same address space can use
> > distinct canary values. This is intended for the Linux kernel running in
> > SMP mode, where processes entering the kernel are essentially threads
> > running the same program concurrently: using a global variable for the
> > canary in that context is problematic because it can never be rotated,
> > and so the OS is forced to use the same value as long as it remains up.
> >
> > Using the TLS register to index the stack canary helps with this, as it
> > allows each CPU to context switch the TLS register along with the rest
> > of the process, permitting each process to use its own value for the
> > stack canary.
>
> I've tested this patch on an arm-none-linux-gnueabihf target and the results 
> look clean.
> Have you tested this patch with a kernel build as well? (since the 
> functionality is intended for that use).

Of course.

> If so, the patch is okay but please rebase it and repost so that we can 
> commit it taking into account
>

Will do.


RE: [PATCH v5 1/1] [ARM] Add support for TLS register based stack protector canary access

2022-01-19 Thread Kyrylo Tkachov via Gcc-patches
Hi Ard,

> -Original Message-
> From: Gcc-patches  bounces+kyrylo.tkachov=arm@gcc.gnu.org> On Behalf Of Ard
> Biesheuvel via Gcc-patches
> Sent: Monday, November 15, 2021 6:04 PM
> To: linux-harden...@vger.kernel.org
> Cc: Richard Sandiford ;
> thomas.preudho...@celest.fr; Keith Packard ;
> gcc-patches@gcc.gnu.org; Kyrylo Tkachov ; Ard
> Biesheuvel 
> Subject: [PATCH v5 1/1] [ARM] Add support for TLS register based stack
> protector canary access
> 
> Add support for accessing the stack canary value via the TLS register,
> so that multiple threads running in the same address space can use
> distinct canary values. This is intended for the Linux kernel running in
> SMP mode, where processes entering the kernel are essentially threads
> running the same program concurrently: using a global variable for the
> canary in that context is problematic because it can never be rotated,
> and so the OS is forced to use the same value as long as it remains up.
> 
> Using the TLS register to index the stack canary helps with this, as it
> allows each CPU to context switch the TLS register along with the rest
> of the process, permitting each process to use its own value for the
> stack canary.

I've tested this patch on an arm-none-linux-gnueabihf target and the results 
look clean.
Have you tested this patch with a kernel build as well? (since the 
functionality is intended for that use).
If so, the patch is okay but please rebase it and repost so that we can commit 
it taking into account

> 
> 2021-11-15 Ard Biesheuvel 
> 
>   * config/arm/arm-opts.h (enum stack_protector_guard): New
>   * config/arm/arm-protos.h (arm_stack_protect_tls_canary_mem):
>   New
>   * config/arm/arm.c (TARGET_STACK_PROTECT_GUARD): Define

... this file has now be renamed to arm.cc and...

>   (arm_option_override_internal): Handle and put in error checks
>   for stack protector guard options.
>   (arm_option_reconfigure_globals): Likewise
>   (arm_stack_protect_tls_canary_mem): New
>   (arm_stack_protect_guard): New
>   * config/arm/arm.md (stack_protect_set): New
>   (stack_protect_set_tls): Likewise
>   (stack_protect_test): Likewise
>   (stack_protect_test_tls): Likewise
>   (reload_tp_hard): Likewise
>   * config/arm/arm.opt (-mstack-protector-guard): New
>   (-mstack-protector-guard-offset): New.
>   * doc/invoke.texi: Document new options
> 
> gcc/testsuite/ChangeLog:
> 
>   * gcc.target/arm/stack-protector-7.c: New test.
>   * gcc.target/arm/stack-protector-8.c: New test.
> 
> Signed-off-by: Ard Biesheuvel 
> ---
>  gcc/config/arm/arm-opts.h|  6 ++
>  gcc/config/arm/arm-protos.h  |  2 +
>  gcc/config/arm/arm.c | 55 +++
>  gcc/config/arm/arm.md| 71 +++-
>  gcc/config/arm/arm.opt   | 22 ++
>  gcc/doc/invoke.texi  | 11 +++
>  gcc/testsuite/gcc.target/arm/stack-protector-7.c | 10 +++
>  gcc/testsuite/gcc.target/arm/stack-protector-8.c |  5 ++
>  8 files changed, 180 insertions(+), 2 deletions(-)
> 
> diff --git a/gcc/config/arm/arm-opts.h b/gcc/config/arm/arm-opts.h
> index 5c4b62f404f7..581ba3c4fbbb 100644
> --- a/gcc/config/arm/arm-opts.h
> +++ b/gcc/config/arm/arm-opts.h
> @@ -69,4 +69,10 @@ enum arm_tls_type {
>TLS_GNU,
>TLS_GNU2
>  };
> +
> +/* Where to get the canary for the stack protector.  */
> +enum stack_protector_guard {
> +  SSP_TLSREG,  /* per-thread canary in TLS register */
> +  SSP_GLOBAL   /* global canary */
> +};
>  #endif
> diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
> index 9b1f61394ad7..d8d605920c97 100644
> --- a/gcc/config/arm/arm-protos.h
> +++ b/gcc/config/arm/arm-protos.h
> @@ -195,6 +195,8 @@ extern void arm_split_atomic_op (enum rtx_code,
> rtx, rtx, rtx, rtx, rtx, rtx);
>  extern rtx arm_load_tp (rtx);
>  extern bool arm_coproc_builtin_available (enum unspecv);
>  extern bool arm_coproc_ldc_stc_legitimate_address (rtx);
> +extern rtx arm_stack_protect_tls_canary_mem (bool);
> +
> 
>  #if defined TREE_CODE
>  extern void arm_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
> index a5b403eb3e49..e5077348ce07 100644
> --- a/gcc/config/arm/arm.c
> +++ b/gcc/config/arm/arm.c
> @@ -829,6 +829,9 @@ static const struct attribute_spec
> arm_attribute_table[] =
> 
>  #undef TARGET_MD_ASM_ADJUST
>  #define TARGET_MD_ASM_ADJUST arm_md_asm_adjust
> +
> +#undef TARGET_STACK_PROTECT_GUARD
> +#define TARGET

Re: [PATCH v5 1/1] [ARM] Add support for TLS register based stack protector canary access

2022-01-14 Thread Ard Biesheuvel via Gcc-patches
(+ Richard Earnshaw)

On Wed, 12 Jan 2022 at 19:29, Ard Biesheuvel  wrote:
>
> On Wed, 17 Nov 2021 at 18:12, Ard Biesheuvel  wrote:
> >
> > (+ Ramana)
> >
>
> Ping?
>
> > On Mon, 15 Nov 2021 at 19:04, Ard Biesheuvel  wrote:
> > >
> > > Add support for accessing the stack canary value via the TLS register,
> > > so that multiple threads running in the same address space can use
> > > distinct canary values. This is intended for the Linux kernel running in
> > > SMP mode, where processes entering the kernel are essentially threads
> > > running the same program concurrently: using a global variable for the
> > > canary in that context is problematic because it can never be rotated,
> > > and so the OS is forced to use the same value as long as it remains up.
> > >
> > > Using the TLS register to index the stack canary helps with this, as it
> > > allows each CPU to context switch the TLS register along with the rest
> > > of the process, permitting each process to use its own value for the
> > > stack canary.
> > >
> > > 2021-11-15 Ard Biesheuvel 
> > >
> > > * config/arm/arm-opts.h (enum stack_protector_guard): New
> > > * config/arm/arm-protos.h (arm_stack_protect_tls_canary_mem):
> > > New
> > > * config/arm/arm.c (TARGET_STACK_PROTECT_GUARD): Define
> > > (arm_option_override_internal): Handle and put in error checks
> > > for stack protector guard options.
> > > (arm_option_reconfigure_globals): Likewise
> > > (arm_stack_protect_tls_canary_mem): New
> > > (arm_stack_protect_guard): New
> > > * config/arm/arm.md (stack_protect_set): New
> > > (stack_protect_set_tls): Likewise
> > > (stack_protect_test): Likewise
> > > (stack_protect_test_tls): Likewise
> > > (reload_tp_hard): Likewise
> > > * config/arm/arm.opt (-mstack-protector-guard): New
> > > (-mstack-protector-guard-offset): New.
> > > * doc/invoke.texi: Document new options
> > >
> > > gcc/testsuite/ChangeLog:
> > >
> > > * gcc.target/arm/stack-protector-7.c: New test.
> > > * gcc.target/arm/stack-protector-8.c: New test.
> > >
> > > Signed-off-by: Ard Biesheuvel 
> > > ---
> > >  gcc/config/arm/arm-opts.h|  6 ++
> > >  gcc/config/arm/arm-protos.h  |  2 +
> > >  gcc/config/arm/arm.c | 55 +++
> > >  gcc/config/arm/arm.md| 71 
> > > +++-
> > >  gcc/config/arm/arm.opt   | 22 ++
> > >  gcc/doc/invoke.texi  | 11 +++
> > >  gcc/testsuite/gcc.target/arm/stack-protector-7.c | 10 +++
> > >  gcc/testsuite/gcc.target/arm/stack-protector-8.c |  5 ++
> > >  8 files changed, 180 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/gcc/config/arm/arm-opts.h b/gcc/config/arm/arm-opts.h
> > > index 5c4b62f404f7..581ba3c4fbbb 100644
> > > --- a/gcc/config/arm/arm-opts.h
> > > +++ b/gcc/config/arm/arm-opts.h
> > > @@ -69,4 +69,10 @@ enum arm_tls_type {
> > >TLS_GNU,
> > >TLS_GNU2
> > >  };
> > > +
> > > +/* Where to get the canary for the stack protector.  */
> > > +enum stack_protector_guard {
> > > +  SSP_TLSREG,  /* per-thread canary in TLS register */
> > > +  SSP_GLOBAL   /* global canary */
> > > +};
> > >  #endif
> > > diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
> > > index 9b1f61394ad7..d8d605920c97 100644
> > > --- a/gcc/config/arm/arm-protos.h
> > > +++ b/gcc/config/arm/arm-protos.h
> > > @@ -195,6 +195,8 @@ extern void arm_split_atomic_op (enum rtx_code, rtx, 
> > > rtx, rtx, rtx, rtx, rtx);
> > >  extern rtx arm_load_tp (rtx);
> > >  extern bool arm_coproc_builtin_available (enum unspecv);
> > >  extern bool arm_coproc_ldc_stc_legitimate_address (rtx);
> > > +extern rtx arm_stack_protect_tls_canary_mem (bool);
> > > +
> > >
> > >  #if defined TREE_CODE
> > >  extern void arm_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, 
> > > tree);
> > > diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
> > > index a5b403eb3e49..e5077348ce07 100644
> > > --- a/gcc/config/arm/arm.c
> > > +++ b/gcc/config/arm/arm.c
> > > @@ -829,6 +829,9 @@ static const struct attribute_spec 
> > > arm_attribute_table[] =
> > >
> > >  #undef TARGET_MD_ASM_ADJUST
> > >  #define TARGET_MD_ASM_ADJUST arm_md_asm_adjust
> > > +
> > > +#undef TARGET_STACK_PROTECT_GUARD
> > > +#define TARGET_STACK_PROTECT_GUARD arm_stack_protect_guard
> > >
> > >  /* Obstack for minipool constant handling.  */
> > >  static struct obstack minipool_obstack;
> > > @@ -3176,6 +3179,26 @@ arm_option_override_internal (struct gcc_options 
> > > *opts,
> > >if (TARGET_THUMB2_P (opts->x_target_flags))
> > >  opts->x_inline_asm_unified = true;
> > >
> > > +  if (arm_stack_protector_guard == SSP_GLOBAL
> > > +  && opts->x_arm_stack_protector_guard_offset_str)
> > > +{
> > > +  error 

Re: [PATCH v5 1/1] [ARM] Add support for TLS register based stack protector canary access

2022-01-12 Thread Ard Biesheuvel via Gcc-patches
On Wed, 17 Nov 2021 at 18:12, Ard Biesheuvel  wrote:
>
> (+ Ramana)
>

Ping?

> On Mon, 15 Nov 2021 at 19:04, Ard Biesheuvel  wrote:
> >
> > Add support for accessing the stack canary value via the TLS register,
> > so that multiple threads running in the same address space can use
> > distinct canary values. This is intended for the Linux kernel running in
> > SMP mode, where processes entering the kernel are essentially threads
> > running the same program concurrently: using a global variable for the
> > canary in that context is problematic because it can never be rotated,
> > and so the OS is forced to use the same value as long as it remains up.
> >
> > Using the TLS register to index the stack canary helps with this, as it
> > allows each CPU to context switch the TLS register along with the rest
> > of the process, permitting each process to use its own value for the
> > stack canary.
> >
> > 2021-11-15 Ard Biesheuvel 
> >
> > * config/arm/arm-opts.h (enum stack_protector_guard): New
> > * config/arm/arm-protos.h (arm_stack_protect_tls_canary_mem):
> > New
> > * config/arm/arm.c (TARGET_STACK_PROTECT_GUARD): Define
> > (arm_option_override_internal): Handle and put in error checks
> > for stack protector guard options.
> > (arm_option_reconfigure_globals): Likewise
> > (arm_stack_protect_tls_canary_mem): New
> > (arm_stack_protect_guard): New
> > * config/arm/arm.md (stack_protect_set): New
> > (stack_protect_set_tls): Likewise
> > (stack_protect_test): Likewise
> > (stack_protect_test_tls): Likewise
> > (reload_tp_hard): Likewise
> > * config/arm/arm.opt (-mstack-protector-guard): New
> > (-mstack-protector-guard-offset): New.
> > * doc/invoke.texi: Document new options
> >
> > gcc/testsuite/ChangeLog:
> >
> > * gcc.target/arm/stack-protector-7.c: New test.
> > * gcc.target/arm/stack-protector-8.c: New test.
> >
> > Signed-off-by: Ard Biesheuvel 
> > ---
> >  gcc/config/arm/arm-opts.h|  6 ++
> >  gcc/config/arm/arm-protos.h  |  2 +
> >  gcc/config/arm/arm.c | 55 +++
> >  gcc/config/arm/arm.md| 71 +++-
> >  gcc/config/arm/arm.opt   | 22 ++
> >  gcc/doc/invoke.texi  | 11 +++
> >  gcc/testsuite/gcc.target/arm/stack-protector-7.c | 10 +++
> >  gcc/testsuite/gcc.target/arm/stack-protector-8.c |  5 ++
> >  8 files changed, 180 insertions(+), 2 deletions(-)
> >
> > diff --git a/gcc/config/arm/arm-opts.h b/gcc/config/arm/arm-opts.h
> > index 5c4b62f404f7..581ba3c4fbbb 100644
> > --- a/gcc/config/arm/arm-opts.h
> > +++ b/gcc/config/arm/arm-opts.h
> > @@ -69,4 +69,10 @@ enum arm_tls_type {
> >TLS_GNU,
> >TLS_GNU2
> >  };
> > +
> > +/* Where to get the canary for the stack protector.  */
> > +enum stack_protector_guard {
> > +  SSP_TLSREG,  /* per-thread canary in TLS register */
> > +  SSP_GLOBAL   /* global canary */
> > +};
> >  #endif
> > diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
> > index 9b1f61394ad7..d8d605920c97 100644
> > --- a/gcc/config/arm/arm-protos.h
> > +++ b/gcc/config/arm/arm-protos.h
> > @@ -195,6 +195,8 @@ extern void arm_split_atomic_op (enum rtx_code, rtx, 
> > rtx, rtx, rtx, rtx, rtx);
> >  extern rtx arm_load_tp (rtx);
> >  extern bool arm_coproc_builtin_available (enum unspecv);
> >  extern bool arm_coproc_ldc_stc_legitimate_address (rtx);
> > +extern rtx arm_stack_protect_tls_canary_mem (bool);
> > +
> >
> >  #if defined TREE_CODE
> >  extern void arm_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
> > diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
> > index a5b403eb3e49..e5077348ce07 100644
> > --- a/gcc/config/arm/arm.c
> > +++ b/gcc/config/arm/arm.c
> > @@ -829,6 +829,9 @@ static const struct attribute_spec 
> > arm_attribute_table[] =
> >
> >  #undef TARGET_MD_ASM_ADJUST
> >  #define TARGET_MD_ASM_ADJUST arm_md_asm_adjust
> > +
> > +#undef TARGET_STACK_PROTECT_GUARD
> > +#define TARGET_STACK_PROTECT_GUARD arm_stack_protect_guard
> >
> >  /* Obstack for minipool constant handling.  */
> >  static struct obstack minipool_obstack;
> > @@ -3176,6 +3179,26 @@ arm_option_override_internal (struct gcc_options 
> > *opts,
> >if (TARGET_THUMB2_P (opts->x_target_flags))
> >  opts->x_inline_asm_unified = true;
> >
> > +  if (arm_stack_protector_guard == SSP_GLOBAL
> > +  && opts->x_arm_stack_protector_guard_offset_str)
> > +{
> > +  error ("incompatible options %'-mstack-protector-guard=global%' and"
> > +"%'-mstack-protector-guard-offset=%qs%'",
> > +arm_stack_protector_guard_offset_str);
> > +}
> > +
> > +  if (opts->x_arm_stack_protector_guard_offset_str)
> > +{
> > +  char *end;
> > +  const char *str = 

Re: [PATCH v5 1/1] [ARM] Add support for TLS register based stack protector canary access

2021-11-17 Thread Ard Biesheuvel via Gcc-patches
(+ Ramana)

On Mon, 15 Nov 2021 at 19:04, Ard Biesheuvel  wrote:
>
> Add support for accessing the stack canary value via the TLS register,
> so that multiple threads running in the same address space can use
> distinct canary values. This is intended for the Linux kernel running in
> SMP mode, where processes entering the kernel are essentially threads
> running the same program concurrently: using a global variable for the
> canary in that context is problematic because it can never be rotated,
> and so the OS is forced to use the same value as long as it remains up.
>
> Using the TLS register to index the stack canary helps with this, as it
> allows each CPU to context switch the TLS register along with the rest
> of the process, permitting each process to use its own value for the
> stack canary.
>
> 2021-11-15 Ard Biesheuvel 
>
> * config/arm/arm-opts.h (enum stack_protector_guard): New
> * config/arm/arm-protos.h (arm_stack_protect_tls_canary_mem):
> New
> * config/arm/arm.c (TARGET_STACK_PROTECT_GUARD): Define
> (arm_option_override_internal): Handle and put in error checks
> for stack protector guard options.
> (arm_option_reconfigure_globals): Likewise
> (arm_stack_protect_tls_canary_mem): New
> (arm_stack_protect_guard): New
> * config/arm/arm.md (stack_protect_set): New
> (stack_protect_set_tls): Likewise
> (stack_protect_test): Likewise
> (stack_protect_test_tls): Likewise
> (reload_tp_hard): Likewise
> * config/arm/arm.opt (-mstack-protector-guard): New
> (-mstack-protector-guard-offset): New.
> * doc/invoke.texi: Document new options
>
> gcc/testsuite/ChangeLog:
>
> * gcc.target/arm/stack-protector-7.c: New test.
> * gcc.target/arm/stack-protector-8.c: New test.
>
> Signed-off-by: Ard Biesheuvel 
> ---
>  gcc/config/arm/arm-opts.h|  6 ++
>  gcc/config/arm/arm-protos.h  |  2 +
>  gcc/config/arm/arm.c | 55 +++
>  gcc/config/arm/arm.md| 71 +++-
>  gcc/config/arm/arm.opt   | 22 ++
>  gcc/doc/invoke.texi  | 11 +++
>  gcc/testsuite/gcc.target/arm/stack-protector-7.c | 10 +++
>  gcc/testsuite/gcc.target/arm/stack-protector-8.c |  5 ++
>  8 files changed, 180 insertions(+), 2 deletions(-)
>
> diff --git a/gcc/config/arm/arm-opts.h b/gcc/config/arm/arm-opts.h
> index 5c4b62f404f7..581ba3c4fbbb 100644
> --- a/gcc/config/arm/arm-opts.h
> +++ b/gcc/config/arm/arm-opts.h
> @@ -69,4 +69,10 @@ enum arm_tls_type {
>TLS_GNU,
>TLS_GNU2
>  };
> +
> +/* Where to get the canary for the stack protector.  */
> +enum stack_protector_guard {
> +  SSP_TLSREG,  /* per-thread canary in TLS register */
> +  SSP_GLOBAL   /* global canary */
> +};
>  #endif
> diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
> index 9b1f61394ad7..d8d605920c97 100644
> --- a/gcc/config/arm/arm-protos.h
> +++ b/gcc/config/arm/arm-protos.h
> @@ -195,6 +195,8 @@ extern void arm_split_atomic_op (enum rtx_code, rtx, rtx, 
> rtx, rtx, rtx, rtx);
>  extern rtx arm_load_tp (rtx);
>  extern bool arm_coproc_builtin_available (enum unspecv);
>  extern bool arm_coproc_ldc_stc_legitimate_address (rtx);
> +extern rtx arm_stack_protect_tls_canary_mem (bool);
> +
>
>  #if defined TREE_CODE
>  extern void arm_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
> index a5b403eb3e49..e5077348ce07 100644
> --- a/gcc/config/arm/arm.c
> +++ b/gcc/config/arm/arm.c
> @@ -829,6 +829,9 @@ static const struct attribute_spec arm_attribute_table[] =
>
>  #undef TARGET_MD_ASM_ADJUST
>  #define TARGET_MD_ASM_ADJUST arm_md_asm_adjust
> +
> +#undef TARGET_STACK_PROTECT_GUARD
> +#define TARGET_STACK_PROTECT_GUARD arm_stack_protect_guard
>
>  /* Obstack for minipool constant handling.  */
>  static struct obstack minipool_obstack;
> @@ -3176,6 +3179,26 @@ arm_option_override_internal (struct gcc_options *opts,
>if (TARGET_THUMB2_P (opts->x_target_flags))
>  opts->x_inline_asm_unified = true;
>
> +  if (arm_stack_protector_guard == SSP_GLOBAL
> +  && opts->x_arm_stack_protector_guard_offset_str)
> +{
> +  error ("incompatible options %'-mstack-protector-guard=global%' and"
> +"%'-mstack-protector-guard-offset=%qs%'",
> +arm_stack_protector_guard_offset_str);
> +}
> +
> +  if (opts->x_arm_stack_protector_guard_offset_str)
> +{
> +  char *end;
> +  const char *str = arm_stack_protector_guard_offset_str;
> +  errno = 0;
> +  long offs = strtol (arm_stack_protector_guard_offset_str, , 0);
> +  if (!*str || *end || errno)
> +   error ("%qs is not a valid offset in %qs", str,
> +  "-mstack-protector-guard-offset=");
> +  

[PATCH v5 1/1] [ARM] Add support for TLS register based stack protector canary access

2021-11-15 Thread Ard Biesheuvel via Gcc-patches
Add support for accessing the stack canary value via the TLS register,
so that multiple threads running in the same address space can use
distinct canary values. This is intended for the Linux kernel running in
SMP mode, where processes entering the kernel are essentially threads
running the same program concurrently: using a global variable for the
canary in that context is problematic because it can never be rotated,
and so the OS is forced to use the same value as long as it remains up.

Using the TLS register to index the stack canary helps with this, as it
allows each CPU to context switch the TLS register along with the rest
of the process, permitting each process to use its own value for the
stack canary.

2021-11-15 Ard Biesheuvel 

* config/arm/arm-opts.h (enum stack_protector_guard): New
* config/arm/arm-protos.h (arm_stack_protect_tls_canary_mem):
New
* config/arm/arm.c (TARGET_STACK_PROTECT_GUARD): Define
(arm_option_override_internal): Handle and put in error checks
for stack protector guard options.
(arm_option_reconfigure_globals): Likewise
(arm_stack_protect_tls_canary_mem): New
(arm_stack_protect_guard): New
* config/arm/arm.md (stack_protect_set): New
(stack_protect_set_tls): Likewise
(stack_protect_test): Likewise
(stack_protect_test_tls): Likewise
(reload_tp_hard): Likewise
* config/arm/arm.opt (-mstack-protector-guard): New
(-mstack-protector-guard-offset): New.
* doc/invoke.texi: Document new options

gcc/testsuite/ChangeLog:

* gcc.target/arm/stack-protector-7.c: New test.
* gcc.target/arm/stack-protector-8.c: New test.

Signed-off-by: Ard Biesheuvel 
---
 gcc/config/arm/arm-opts.h|  6 ++
 gcc/config/arm/arm-protos.h  |  2 +
 gcc/config/arm/arm.c | 55 +++
 gcc/config/arm/arm.md| 71 +++-
 gcc/config/arm/arm.opt   | 22 ++
 gcc/doc/invoke.texi  | 11 +++
 gcc/testsuite/gcc.target/arm/stack-protector-7.c | 10 +++
 gcc/testsuite/gcc.target/arm/stack-protector-8.c |  5 ++
 8 files changed, 180 insertions(+), 2 deletions(-)

diff --git a/gcc/config/arm/arm-opts.h b/gcc/config/arm/arm-opts.h
index 5c4b62f404f7..581ba3c4fbbb 100644
--- a/gcc/config/arm/arm-opts.h
+++ b/gcc/config/arm/arm-opts.h
@@ -69,4 +69,10 @@ enum arm_tls_type {
   TLS_GNU,
   TLS_GNU2
 };
+
+/* Where to get the canary for the stack protector.  */
+enum stack_protector_guard {
+  SSP_TLSREG,  /* per-thread canary in TLS register */
+  SSP_GLOBAL   /* global canary */
+};
 #endif
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 9b1f61394ad7..d8d605920c97 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -195,6 +195,8 @@ extern void arm_split_atomic_op (enum rtx_code, rtx, rtx, 
rtx, rtx, rtx, rtx);
 extern rtx arm_load_tp (rtx);
 extern bool arm_coproc_builtin_available (enum unspecv);
 extern bool arm_coproc_ldc_stc_legitimate_address (rtx);
+extern rtx arm_stack_protect_tls_canary_mem (bool);
+
 
 #if defined TREE_CODE
 extern void arm_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index a5b403eb3e49..e5077348ce07 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -829,6 +829,9 @@ static const struct attribute_spec arm_attribute_table[] =
 
 #undef TARGET_MD_ASM_ADJUST
 #define TARGET_MD_ASM_ADJUST arm_md_asm_adjust
+
+#undef TARGET_STACK_PROTECT_GUARD
+#define TARGET_STACK_PROTECT_GUARD arm_stack_protect_guard
 
 /* Obstack for minipool constant handling.  */
 static struct obstack minipool_obstack;
@@ -3176,6 +3179,26 @@ arm_option_override_internal (struct gcc_options *opts,
   if (TARGET_THUMB2_P (opts->x_target_flags))
 opts->x_inline_asm_unified = true;
 
+  if (arm_stack_protector_guard == SSP_GLOBAL
+  && opts->x_arm_stack_protector_guard_offset_str)
+{
+  error ("incompatible options %'-mstack-protector-guard=global%' and"
+"%'-mstack-protector-guard-offset=%qs%'",
+arm_stack_protector_guard_offset_str);
+}
+
+  if (opts->x_arm_stack_protector_guard_offset_str)
+{
+  char *end;
+  const char *str = arm_stack_protector_guard_offset_str;
+  errno = 0;
+  long offs = strtol (arm_stack_protector_guard_offset_str, , 0);
+  if (!*str || *end || errno)
+   error ("%qs is not a valid offset in %qs", str,
+  "-mstack-protector-guard-offset=");
+  arm_stack_protector_guard_offset = offs;
+}
+
 #ifdef SUBTARGET_OVERRIDE_INTERNAL_OPTIONS
   SUBTARGET_OVERRIDE_INTERNAL_OPTIONS;
 #endif
@@ -3843,6 +3866,9 @@ arm_option_reconfigure_globals (void)
   else
target_thread_pointer = TP_SOFT;
 }
+
+  if (!TARGET_HARD_TP &&