On Wed, 2023-06-21 at 16:15 -0700, Rick Edgecombe wrote: > On Wed, 2023-06-21 at 16:05 -0700, H.J. Lu wrote: > > > 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. > > Oh good point. Hmm. Just had a quick chat with HJ on this. It seems like it *might* be able to made to work. How it would go is setjmp() could act as a wrapper by calling it's own return address (the function that called setjmp()). This would mean in the case of longjmp() not being called, control flow would return through setjmp() before returning from the calling method. This would allow libc to do a RSTORSSP when returning though setjmp() in the non-shadow stack case, and essentially skip over the kernel placed restore token, and then return from setjmp() like normal. In the case of longjmp() being called, it could RSTORSSP directly to the token, and then return from setjmp(). Another option could be getting the compilers help to do the RSTORSSP in the case of longjmp() not being called. Apparently compilers are aware of setjmp() and already do special things around it (makes sense I guess, but news to me). And also, this all would actually work with IBT, because the compiler knows already to add an endbr at that point right after setjmp(). I think neither of us were ready to bet on it, but thought maybe it could work. And even if it works it's much more complicated than I first thought, so I don't like it as much. It's also unclear what a change like that would mean for security. As for unwinding through the existing swapcontext() placed restore tokens, the problem was as assumed - that it's difficult to find them. Even considering brute force options like doing manual searches for a nearby token to use turned up edge cases pretty quick. So I think that kind of leaves us where we were originally, with no known solutions that would require breaking kernel ABI changes. Are you interested in helping get longjmp() from a ucontext stack working for shadow stack? One other thing that came up in the conversation was that while it is known that some apps are doing this, there are no tests for mixing longjmp and ucontext in glibc. So we may not know which combinations of mixing them together even work in the non-shadow stack case. It could be useful to add some tests for this to glibc and we could get some clarity on what behaviors shadow stack would actually need to support.