On Sat, Feb 5, 2022 at 12:15 PM Edgecombe, Rick P <rick.p.edgecombe@xxxxxxxxx> wrote: > > On Sat, 2022-02-05 at 05:29 -0800, H.J. Lu wrote: > > On Sat, Feb 5, 2022 at 5:27 AM David Laight <David.Laight@xxxxxxxxxx> > > wrote: > > > > > > 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. > > So the scenario is? > > 1. Handle signal 1 > 2. sigsetjmp() > 3. signalstack() > 4. Handle signal 2 on alt stack > 5. siglongjmp() > > I'll check that it is covered by the tests, but I think it should work > in this series that has no alt shadow stack. I have only done a high > level overview of how the shadow stack stuff, that doesn't involve the > kernel, works in glibc. Sounds like I'll need to do a deeper dive. > > > > > > > I think the shadow stack pointer has to be in ucontext - which also > > > means the application can change it before returning from a signal. > > Yes we might need to change it to support alt shadow stacks. Can you > elaborate why you think it has to be in ucontext? I was thinking of > looking at three options for storing the ssp: > - Stored in the shadow stack like a token using WRUSS from the kernel. > - Stored on the kernel side using a hashmap that maps ucontext or > sigframe userspace address to ssp (this is of course similar to > storing in ucontext, except that the user can’t change the ssp). > - Stored writable in userspace in ucontext. > > But in this version, without alt shadow stacks, the shadow stack > pointer is not stored in ucontext. This causes the limitation that > userspace can only call sigreturn when it has returned back to a point > where there is a restore token on the shadow stack (which was placed > there by the kernel). This doesn’t mean it can’t switch to a different > shadow stack or handle a nested signal, but it limits the possibility > for calling sigreturn with a totally different sigframe (like CRIU and > SROP attacks do). It should hopefully be a helpful, protective > limitation for most apps and I'm hoping CRIU can be fixed without > removing it. > > I am not aware of other limitations to signals (besides normal shadow > stack enforcement), but I could be missing it. And people's skepticism > is making me want to go back over it with more scrutiny. > > > > 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. > > I don't think this is as difficult to avoid because userspace ssp has > its own register that should not be accessed at that point, but I have > not given this aspect enough analysis. Thanks for bringing it up. > > > > > > > Hmmm... do shadow stacks mean that longjmp() has to be a system > > > call? > > > > No. setjmp/longjmp save and restore shadow stack pointer. > > > > It sounds like it would help to write up in a lot more detail exactly > how all the signal and specialer stack manipulation scenarios work in > glibc. > setjmp/longjmp work on the same sigjmp_buf. Shadow stack pointer is saved and restored, just like any other callee-saved registers. -- H.J.