On Wed, Jun 21, 2023 at 3:23 PM Edgecombe, Rick P <rick.p.edgecombe@xxxxxxxxx> wrote: > > On Wed, 2023-06-21 at 11:54 -0700, Rick Edgecombe wrote: > > > > > > > > there is no magic, longjmp should be implemented as: > > > > > > > > > > > > > > > > target_ssp = read from jmpbuf; > > > > > > > > current_ssp = read ssp; > > > > > > > > for (p = target_ssp; p != current_ssp; p--) { > > > > > > > > if (*p == restore-token) { > > > > > > > > // target_ssp is on a different > > > > > > > > shstk. > > > > > > > > switch_shstk_to(p); > > > > > > > > break; > > > > > > > > } > > > > > > > > } > > > > > > > > for (; p != target_ssp; p++) > > > > > > > > // ssp is now on the same shstk as > > > > > > > > target. > > > > > > > > inc_ssp(); > > > > > > > > > > > > > > > > this is what setcontext is doing and longjmp can do the > > > > > > > > same: > > > > > > > > for programs that always longjmp within the same shstk > > > > > > > > the > > > > > > > > first > > > > > > > > loop is just p = current_ssp, but it also works when > > > > > > > > longjmp > > > > > > > > target is on a different shstk assuming nothing is > > > > > > > > running > > > > > > > > on > > > > > > > > that shstk, which is only possible if there is a restore > > > > > > > > token > > > > > > > > on top. > > > > > > > > > > > > > > > > this implies if the kernel switches shstk on signal entry > > > > > > > > it has > > > > > > > > to add a restore-token on the switched away shstk. > > Wait a second, the claim is that the kernel should add a restore token > on the current shadow stack before handling a signal, to allow to > unwind from an alt shadow stack, right? But in this series there is not > an alt shadow stack, so signal will be handled on the current shadow > stack. If the user stays on the current shadow stack, the existing > simple INCSSP based solution will work. > > If the user swapcontext()'s away while handling a signal (which *is* > currently supported) they will leave their own restore token on the old > stack. Hypothetically glibc could unwind back through a series of > ucontext stacks by pivoting, if it kept some metadata somewhere about > where to restore to. So there are actually already enough tokens to > make it back in this case, glibc just doesn't do this. > > But how does the proposed token placed by the kernel on the original > stack help this problem? The longjmp() would have to be able to find > the location of the restore tokens somehow, which would not necessarily > be near the setjmp() point. The signal token could even be on a > different shadow stack. > > So I think the above is short of a design for a universally compatible > longjmp(). > > Which makes me think if we did want to make a more compatible longjmp() > a better the way to do it might be an arch_prctl that emits a token at > the current SSP. This would be loosening up the security somewhat (have > to be an opt-in), but less so then enabling WRSS. But it would also be > way simpler, work for all cases (I think), and be faster (maybe?) than > INCSSPing through a bunch of stacks. Since longjmp isn't required to be called after setjmp, leaving a restore token doesn't work when longjmp isn't called. > I'm also not sure leaving a token on signal doesn't weaken the security > it it's own way as well. Any thread could then swap to that token. > Where as the shadow stack signal frame ssp pointer can only be used > from the shadow stack the signal was handled on. > > So I think, in addition to blocking the shadow stack overflow use case > in the future, leaving a token behind on signal will not really help > longjmp(). (or at least I'm not following) > -- H.J.