The 04/17/2020 12:50, Jason Merrill wrote:
> On 4/17/20 6:08 AM, Kyrylo Tkachov wrote:
> > Hi Szabolcs,
> >
> > > -----Original Message-----
> > > From: Szabolcs Nagy <[email protected]>
> > > Sent: 09 April 2020 15:20
> > > To: [email protected]
> > > Cc: Richard Earnshaw <[email protected]>; Richard Sandiford
> > > <[email protected]>; Kyrylo Tkachov <[email protected]>
> > > 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 <[email protected]>
> > >
> > > 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 <[email protected]>
> > >
> > > 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;
>
> It looks like passing 'true' to dwarf2out_frame_debug_cfa_window_save
> prevents that function from messing with the window_safe flag. Does
> changing the argument to 'false' get the behavior you want?
we want the state = !state toggling.
it might make more sense to do that in
dwarf2out_frame_debug_cfa_window_save(true)
or to inline that entire logic into the two
places where it is used (instead of
dispatching with a bool argument).
for the bug fix i'd like a minimal change
(so it can be backported), doing the fix in
dwarf2out_frame_debug_cfa_window_save
is fine with me, would you prefer that?
>
> > > 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
> >
>
--