RE: [PATCH 00/35] Shadow stacks for userspace

David Laight
2022-02-05T13:27:17Z

From: Edgecombe, Rick P
> Sent: 04 February 2022 01:08
> Hi Thomas,
>
> Thanks for feedback on the plan.
>
> On Thu, 2022-02-03 at 22:07 +0100, Thomas Gleixner wrote:
> > > Until now, the enabling effort was trying to support both Shadow
> > > Stack and IBT.
> > > This history will focus on a few areas of the shadow stack
> > > development history
> > > that I thought stood out.
> > >
> > > Signals
> > > -------
> > > Originally signals placed the location of the shadow stack
> > > restore
> > > token inside the saved state on the stack. This was
> > > problematic from a
> > > past ABI promises perspective. So the restore location was
> > > instead just
> > > assumed from the shadow stack pointer. This works because in
> > > normal
> > > allowed cases of calling sigreturn, the shadow stack pointer
> > > should be
> > > right at the restore token at that time. There is no
> > > alternate shadow
> > > stack support. If an alt shadow stack is added later we
> > > would
> > > need to
> >
> > So how is that going to work? altstack is not an esoteric corner
> > case.
>
> My understanding is that the main usages for the signal stack were
> handling stack overflows and corruption. Since the shadow stack only
> contains return addresses rather than large stack allocations, and is
> not generally writable or pivotable, I thought there was a good
> possibility an alt shadow stack would not end up being especially
> useful. Does it seem like reasonable guesswork?

The other 'problem' is that it is valid to longjump out of a signal handler.
These days you have to use siglongjmp() not longjmp() but it is still used.

It is probably also valid to use siglongjmp() to jump from a nested
signal handler into the outer handler.
Given both signal handlers can have their own stack, there can be three
stacks involved.

I think the shadow stack pointer has to be in ucontext - which also
means the application can change it before returning from a signal.
In much the same way as all the segment registers can be changed
leading to all the nasty bugs when the final 'return to user' code
traps in kernel when loading invalid segment registers or executing iret.

Hmmm... do shadow stacks mean that longjmp() has to be a system call?

David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)