Hi Szabolcs,

> -----Original Message-----
> From: Szabolcs Nagy <szabolcs.n...@arm.com>
> Sent: 09 April 2020 15:20
> To: gcc-patches@gcc.gnu.org
> Cc: Richard Earnshaw <richard.earns...@arm.com>; Richard Sandiford
> <richard.sandif...@arm.com>; Kyrylo Tkachov <kyrylo.tkac...@arm.com>
> Subject: [PATCH] aarch64: Fix .cfi_window_save with pac-ret [PR94515]
> 
> On aarch64 -mbranch-protection=pac-ret reuses the dwarf
> opcode for window_save to mean "toggle the return address
> mangle state", but in the dwarf2cfi internal logic the
> state was not properly recorded so the remember/restore
> logic was broken.
> 
> This can cause the unwinder not to authenticate return
> addresses that were signed (or vice versa) which means
> a runtime crash on a pauth enabled system.
> 
> Currently only aarch64 pac-ret uses REG_CFA_TOGGLE_RA_MANGLE.

I think this is ok, but this code is in the midend so I've CC'ed Jason who, 
from what I gather from MAINTAINERS, is maintainer for this file.
Thanks,
Kyrill

> 
> gcc/ChangeLog:
> 
> 2020-04-XX  Szabolcs Nagy  <szabolcs.n...@arm.com>
> 
>       PR target/94515
>       * dwarf2cfi.c (dwarf2out_frame_debug): Record RA
>       mangle state in cur_row->window_save.
> 
> gcc/testsuite/ChangeLog:
> 
> 2020-04-XX  Szabolcs Nagy  <szabolcs.n...@arm.com>
> 
>       PR target/94515
>       * g++.target/aarch64/pr94515.C: New test.
> ---
>  gcc/dwarf2cfi.c                            |  3 ++
>  gcc/testsuite/g++.target/aarch64/pr94515.C | 43 ++++++++++++++++++++++
>  2 files changed, 46 insertions(+)
>  create mode 100644 gcc/testsuite/g++.target/aarch64/pr94515.C
> 
> diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
> index 229fbfacc30..22989a6c2fb 100644
> --- a/gcc/dwarf2cfi.c
> +++ b/gcc/dwarf2cfi.c
> @@ -2145,6 +2145,9 @@ dwarf2out_frame_debug (rtx_insn *insn)
>        case REG_CFA_TOGGLE_RA_MANGLE:
>       /* This uses the same DWARF opcode as the next operation.  */
>       dwarf2out_frame_debug_cfa_window_save (true);
> +     /* Keep track of RA mangle state by toggling the window_save bit.
> +        This is needed so .cfi_window_save is emitted correctly.  */
> +     cur_row->window_save = !cur_row->window_save;
>       handled_one = true;
>       break;
> 
> diff --git a/gcc/testsuite/g++.target/aarch64/pr94515.C
> b/gcc/testsuite/g++.target/aarch64/pr94515.C
> new file mode 100644
> index 00000000000..7707c773a72
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/aarch64/pr94515.C
> @@ -0,0 +1,43 @@
> +/* PR target/94515. Check .cfi_window_save with multiple return paths.  */
> +/* { dg-do run } */
> +/* { dg-additional-options "-O2 -mbranch-protection=pac-ret --save-temps" }
> */
> +
> +volatile int zero = 0;
> +
> +__attribute__((noinline, target("branch-protection=none")))
> +void unwind (void)
> +{
> +  if (zero == 0)
> +    throw 42;
> +}
> +
> +__attribute__((noinline, noipa, target("branch-protection=pac-ret")))
> +int test (int z)
> +{
> +  if (z) {
> +    asm volatile ("":::"x20","x21");
> +    unwind ();
> +    return 1;
> +  } else {
> +    unwind ();
> +    return 2;
> +  }
> +}
> +
> +__attribute__((target("branch-protection=none")))
> +int main ()
> +{
> +  try {
> +    test (zero);
> +    __builtin_abort ();
> +  } catch (...) {
> +    return 0;
> +  }
> +  __builtin_abort ();
> +}
> +
> +/* This check only works if there are two return paths in test and
> +   cfi_window_save is used for both instead of cfi_remember_state
> +   plus cfi_restore_state.  This is currently the case with -O2.  */
> +
> +/* { dg-final { scan-assembler-times {\t\.cfi_window_save\n} 4 } } */
> --
> 2.17.1

Reply via email to