lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Date:   Fri, 21 Jan 2022 12:15:06 +0000
From:   Kyrylo Tkachov <Kyrylo.Tkachov@....com>
To:     Ard Biesheuvel <ardb@...nel.org>
CC:     "linux-hardening@...r.kernel.org" <linux-hardening@...r.kernel.org>,
        Richard Earnshaw <Richard.Earnshaw@....com>,
        Richard Sandiford <Richard.Sandiford@....com>,
        "thomas.preudhomme@...est.fr" <thomas.preudhomme@...est.fr>,
        Keith Packard <keithpac@...zon.com>,
        "gcc-patches@....gnu.org" <gcc-patches@....gnu.org>
Subject: RE: [PATCH v6 1/1] [ARM] Add support for TLS register based stack
 protector canary access



> -----Original Message-----
> From: Ard Biesheuvel <ardb@...nel.org>
> Sent: Friday, January 21, 2022 10:50 AM
> To: Kyrylo Tkachov <Kyrylo.Tkachov@....com>
> Cc: linux-hardening@...r.kernel.org; Richard Earnshaw
> <Richard.Earnshaw@....com>; Richard Sandiford
> <Richard.Sandiford@....com>; thomas.preudhomme@...est.fr; Keith
> Packard <keithpac@...zon.com>; gcc-patches@....gnu.org
> Subject: Re: [PATCH v6 1/1] [ARM] Add support for TLS register based stack
> protector canary access
> 
> On Fri, 21 Jan 2022 at 11:47, Kyrylo Tkachov <Kyrylo.Tkachov@....com>
> wrote:
> >
> > > -----Original Message-----
> > > From: Gcc-patches <gcc-patches-
> > > bounces+kyrylo.tkachov=arm.com@....gnu.org> On Behalf Of Ard
> > > Biesheuvel via Gcc-patches
> > > Sent: Wednesday, January 19, 2022 5:44 PM
> > > To: linux-hardening@...r.kernel.org
> > > Cc: Richard Earnshaw <Richard.Earnshaw@....com>; Richard Sandiford
> > > <Richard.Sandiford@....com>; thomas.preudhomme@...est.fr; Keith
> > > Packard <keithpac@...zon.com>; gcc-patches@....gnu.org; Kyrylo
> Tkachov
> > > <kyryo.tkachov@....com>; Ard Biesheuvel <ardb@...nel.org>
> > > Subject: [PATCH v6 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.
> > >
> > > 2022-01-19 Ard Biesheuvel <ardb@...nel.org>
> > >
> > >       * 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.cc (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 <ardb@...nel.org>
> >
> > Thanks. One final bit. Given that you're using the Signed-off-by tag this
> means that you're contributing this patch under the DCO rules.
> > Can you please confirm that you intend to contribute this patch under the
> rules in https://gcc.gnu.org/dco.html
> 
> Yes, I am making this contribution under DCO 1.1 terms.
> 
> > If you're happy with that I'll push the patch for you.
> > Thanks,
> > Kyrill
> >
> 
> Thanks!

I've now pushed it to trunk.
Thank you for your patience and responsiveness and apologies for the delay in the reviews.

Thanks,
Kyrill

> 
> 
> > > ---
> > >  gcc/config/arm/arm-opts.h                        |  6 ++
> > >  gcc/config/arm/arm-protos.h                      |  2 +
> > >  gcc/config/arm/arm.cc                            | 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 | 12 ++++
> > >  gcc/testsuite/gcc.target/arm/stack-protector-8.c |  7 ++
> > >  8 files changed, 184 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/gcc/config/arm/arm-opts.h b/gcc/config/arm/arm-opts.h
> > > index c50d5e56a181..24d12fafdec8 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 cd55a9f6ca54..881c72c988bd 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.cc b/gcc/config/arm/arm.cc
> > > index 7825e364c01e..c192894ff33e 100644
> > > --- a/gcc/config/arm/arm.cc
> > > +++ b/gcc/config/arm/arm.cc
> > > @@ -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, &end, 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 && arm_stack_protector_guard == SSP_TLSREG)
> > > +    error("%'-mstack-protector-guard=tls%' needs a hardware TLS
> register");
> > >  }
> > >
> > >  /* Perform some validation between the desired architecture and the
> rest of
> > > the
> > > @@ -8108,6 +8134,23 @@ legitimize_pic_address (rtx orig,
> machine_mode
> > > mode, rtx reg, rtx pic_reg,
> > >  }
> > >
> > >
> > > +/* Generate insns that produce the address of the stack canary */
> > > +rtx
> > > +arm_stack_protect_tls_canary_mem (bool reload)
> > > +{
> > > +  rtx tp = gen_reg_rtx (SImode);
> > > +  if (reload)
> > > +    emit_insn (gen_reload_tp_hard (tp));
> > > +  else
> > > +    emit_insn (gen_load_tp_hard (tp));
> > > +
> > > +  rtx reg = gen_reg_rtx (SImode);
> > > +  rtx offset = GEN_INT (arm_stack_protector_guard_offset);
> > > +  emit_set_insn (reg, gen_rtx_PLUS (SImode, tp, offset));
> > > +  return gen_rtx_MEM (SImode, reg);
> > > +}
> > > +
> > > +
> > >  /* Whether a register is callee saved or not.  This is necessary because
> high
> > >     registers are marked as caller saved when optimizing for size on
> Thumb-1
> > >     targets despite being callee saved in order to avoid using them.  */
> > > @@ -34075,6 +34118,18 @@ arm_run_selftests (void)
> > >  #define TARGET_RUN_TARGET_SELFTESTS selftest::arm_run_selftests
> > >  #endif /* CHECKING_P */
> > >
> > > +/* Implement TARGET_STACK_PROTECT_GUARD. In case of a
> > > +   global variable based guard use the default else
> > > +   return a null tree.  */
> > > +static tree
> > > +arm_stack_protect_guard (void)
> > > +{
> > > +  if (arm_stack_protector_guard == SSP_GLOBAL)
> > > +    return default_stack_protect_guard ();
> > > +
> > > +  return NULL_TREE;
> > > +}
> > > +
> > >  /* Worker function for TARGET_MD_ASM_ADJUST, while in thumb1
> mode.
> > >     Unlike the arm version, we do NOT implement asm flag outputs.  */
> > >
> > > diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
> > > index 90756fbfa3af..60468f6182c3 100644
> > > --- a/gcc/config/arm/arm.md
> > > +++ b/gcc/config/arm/arm.md
> > > @@ -9183,7 +9183,7 @@ (define_expand "stack_protect_combined_set"
> > >                     UNSPEC_SP_SET))
> > >        (clobber (match_scratch:SI 2 ""))
> > >        (clobber (match_scratch:SI 3 ""))])]
> > > -  ""
> > > +  "arm_stack_protector_guard == SSP_GLOBAL"
> > >    ""
> > >  )
> > >
> > > @@ -9267,7 +9267,7 @@ (define_expand
> "stack_protect_combined_test"
> > >        (clobber (match_scratch:SI 3 ""))
> > >        (clobber (match_scratch:SI 4 ""))
> > >        (clobber (reg:CC CC_REGNUM))])]
> > > -  ""
> > > +  "arm_stack_protector_guard == SSP_GLOBAL"
> > >    ""
> > >  )
> > >
> > > @@ -9361,6 +9361,64 @@ (define_insn "arm_stack_protect_test_insn"
> > >     (set_attr "arch" "t,32")]
> > >  )
> > >
> > > +(define_expand "stack_protect_set"
> > > +  [(match_operand:SI 0 "memory_operand")
> > > +   (match_operand:SI 1 "memory_operand")]
> > > +  "arm_stack_protector_guard == SSP_TLSREG"
> > > +  "
> > > +{
> > > +  operands[1] = arm_stack_protect_tls_canary_mem (false /* reload */);
> > > +  emit_insn (gen_stack_protect_set_tls (operands[0], operands[1]));
> > > +  DONE;
> > > +}"
> > > +)
> > > +
> > > +;; DO NOT SPLIT THIS PATTERN.  It is important for security reasons that
> the
> > > +;; canary value does not live beyond the life of this sequence.
> > > +(define_insn "stack_protect_set_tls"
> > > +  [(set (match_operand:SI 0 "memory_operand" "=m")
> > > +       (unspec:SI [(match_operand:SI 1 "memory_operand" "m")]
> > > +        UNSPEC_SP_SET))
> > > +   (set (match_scratch:SI 2 "=&r") (const_int 0))]
> > > +  ""
> > > +  "ldr\\t%2, %1\;str\\t%2, %0\;mov\t%2, #0"
> > > +  [(set_attr "length" "12")
> > > +   (set_attr "conds" "unconditional")
> > > +   (set_attr "type" "multiple")]
> > > +)
> > > +
> > > +(define_expand "stack_protect_test"
> > > +  [(match_operand:SI 0 "memory_operand")
> > > +   (match_operand:SI 1 "memory_operand")
> > > +   (match_operand:SI 2)]
> > > +  "arm_stack_protector_guard == SSP_TLSREG"
> > > +  "
> > > +{
> > > +  operands[1] = arm_stack_protect_tls_canary_mem (true /* reload */);
> > > +  emit_insn (gen_stack_protect_test_tls (operands[0], operands[1]));
> > > +
> > > +  rtx cc_reg = gen_rtx_REG (CC_Zmode, CC_REGNUM);
> > > +  rtx eq = gen_rtx_EQ (CC_Zmode, cc_reg, const0_rtx);
> > > +  emit_jump_insn (gen_arm_cond_branch (operands[2], eq, cc_reg));
> > > +  DONE;
> > > +}"
> > > +)
> > > +
> > > +(define_insn "stack_protect_test_tls"
> > > +  [(set (reg:CC_Z CC_REGNUM)
> > > +     (compare:CC_Z (unspec:SI [(match_operand:SI 0 "memory_operand"
> > > "m")
> > > +                               (match_operand:SI 1 "memory_operand"
> > > "m")]
> > > +                              UNSPEC_SP_TEST)
> > > +                   (const_int 0)))
> > > +   (clobber (match_scratch:SI 2 "=&r"))
> > > +   (clobber (match_scratch:SI 3 "=&r"))]
> > > +  ""
> > > +  "ldr\t%2, %0\;ldr\t%3, %1\;eors\t%2, %3, %2\;mov\t%3, #0"
> > > +  [(set_attr "length" "16")
> > > +   (set_attr "conds" "set")
> > > +   (set_attr "type" "multiple")]
> > > +)
> > > +
> > >  (define_expand "casesi"
> > >    [(match_operand:SI 0 "s_register_operand") ; index to jump on
> > >     (match_operand:SI 1 "const_int_operand")  ; lower bound
> > > @@ -12133,6 +12191,15 @@ (define_insn "load_tp_hard"
> > >     (set_attr "type" "mrs")]
> > >  )
> > >
> > > +;; Used by the TLS register based stack protector
> > > +(define_insn "reload_tp_hard"
> > > +  [(set (match_operand:SI 0 "register_operand" "=r")
> > > +     (unspec_volatile:SI [(const_int 0)] VUNSPEC_MRC))]
> > > +  "TARGET_HARD_TP"
> > > +  "mrc\\tp15, 0, %0, c13, c0, 3\\t@ reload_tp_hard"
> > > +  [(set_attr "type" "mrs")]
> > > +)
> > > +
> > >  ;; Doesn't clobber R1-R3.  Must use r0 for the first operand.
> > >  (define_insn "load_tp_soft_fdpic"
> > >    [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
> > > diff --git a/gcc/config/arm/arm.opt b/gcc/config/arm/arm.opt
> > > index 587fc932f969..e342a0df4def 100644
> > > --- a/gcc/config/arm/arm.opt
> > > +++ b/gcc/config/arm/arm.opt
> > > @@ -311,3 +311,25 @@ Generate code which uses the core registers
> only
> > > (r0-r14).
> > >  mfdpic
> > >  Target Mask(FDPIC)
> > >  Enable Function Descriptor PIC mode.
> > > +
> > > +mstack-protector-guard=
> > > +Target RejectNegative Joined Enum(stack_protector_guard)
> > > Var(arm_stack_protector_guard) Init(SSP_GLOBAL)
> > > +Use given stack-protector guard.
> > > +
> > > +Enum
> > > +Name(stack_protector_guard) Type(enum stack_protector_guard)
> > > +Valid arguments to -mstack-protector-guard=:
> > > +
> > > +EnumValue
> > > +Enum(stack_protector_guard) String(tls) Value(SSP_TLSREG)
> > > +
> > > +EnumValue
> > > +Enum(stack_protector_guard) String(global) Value(SSP_GLOBAL)
> > > +
> > > +mstack-protector-guard-offset=
> > > +Target Joined RejectNegative String
> > > Var(arm_stack_protector_guard_offset_str)
> > > +Use an immediate to offset from the TLS register. This option is for use
> with
> > > +fstack-protector-guard=tls and not for use in user-land code.
> > > +
> > > +TargetVariable
> > > +long arm_stack_protector_guard_offset = 0
> > > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> > > index 58751c48b8e9..e7c9400c0ccd 100644
> > > --- a/gcc/doc/invoke.texi
> > > +++ b/gcc/doc/invoke.texi
> > > @@ -821,6 +821,7 @@ Objective-C and Objective-C++ Dialects}.
> > >  -mpure-code @gol
> > >  -mcmse @gol
> > >  -mfix-cmse-cve-2021-35465 @gol
> > > +-mstack-protector-guard=@...{guard} -mstack-protector-guard-
> > > offset=@...{offset} @gol
> > >  -mfdpic}
> > >
> > >  @emph{AVR Options}
> > > @@ -21355,6 +21356,16 @@ enabled by default when the option
> @option{-
> > > mcpu=} is used with
> > >  @code{cortex-m33}, @code{cortex-m35p} or @code{cortex-m55}.  The
> > > option
> > >  @option{-mno-fix-cmse-cve-2021-35465} can be used to disable the
> > > mitigation.
> > >
> > > +@...m -mstack-protector-guard=@...{guard}
> > > +@...mx -mstack-protector-guard-offset=@...{offset}
> > > +@...ndex mstack-protector-guard
> > > +@...ndex mstack-protector-guard-offset
> > > +Generate stack protection code using canary at @var{guard}.  Supported
> > > +locations are @samp{global} for a global canary or @samp{tls} for a
> > > +canary accessible via the TLS register. The option
> > > +@...ion{-mstack-protector-guard-offset=} is for use with
> > > +@...ion{-fstack-protector-guard=tls} and not for use in user-land code.
> > > +
> > >  @item -mfdpic
> > >  @itemx -mno-fdpic
> > >  @opindex mfdpic
> > > diff --git a/gcc/testsuite/gcc.target/arm/stack-protector-7.c
> > > b/gcc/testsuite/gcc.target/arm/stack-protector-7.c
> > > new file mode 100644
> > > index 000000000000..2173bc5a35a0
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/arm/stack-protector-7.c
> > > @@ -0,0 +1,12 @@
> > > +/* { dg-require-effective-target arm_hard_vfp_ok }  */
> > > +/* { dg-require-effective-target arm_arch_v7a_ok } */
> > > +/* { dg-do compile } */
> > > +/* { dg-options "-march=armv7-a -mfpu=vfp -fstack-protector-all -Os -
> > > mstack-protector-guard=tls -mstack-protector-guard-offset=1296 -
> mtp=cp15"
> > > } */
> > > +
> > > +#include "stack-protector-5.c"
> > > +
> > > +/* See the comment in stack-protector-5.c.  */
> > > +/* { dg-final { scan-assembler-times {\tstr\t} 1 } } */
> > > +/* Expect two TLS register accesses and two occurrences of the offset */
> > > +/* { dg-final { scan-assembler-times {\tmrc\t} 2 } } */
> > > +/* { dg-final { scan-assembler-times {1296} 2 } } */
> > > diff --git a/gcc/testsuite/gcc.target/arm/stack-protector-8.c
> > > b/gcc/testsuite/gcc.target/arm/stack-protector-8.c
> > > new file mode 100644
> > > index 000000000000..ea5ef3211678
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/arm/stack-protector-8.c
> > > @@ -0,0 +1,7 @@
> > > +/* { dg-require-effective-target arm_hard_vfp_ok }  */
> > > +/* { dg-require-effective-target arm_arch_v7a_ok } */
> > > +/* { dg-do compile } */
> > > +/* { dg-error "needs a hardware TLS register" "missing error when using
> TLS
> > > stack protector without hardware TLS register" { target *-*-* } 0 } */
> > > +/* { dg-options "-fstack-protector-all -Os -mstack-protector-guard=tls -
> > > mtp=soft" } */
> > > +
> > > +int foo;
> > > --
> > > 2.30.2
> >

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ