Comment by stmw
8 years ago
Very good point. Key phrase is "an offset > 4096 is just bogus. That's big enough to skip right over the guard page" - if allocating more than a page-size-worth (4K in most cases), it should try to write to it before returning.
It isn't. -fstack-check consistently checks the stack at a 4K offset. It wasn't designed for Stack Clash protection, but in practice, it works as long as all the code was compiled with it (which on Gentoo Hardened, it would be, at least for typical C/C++ apps). The whole stack is still being probed (except perhaps the first page), it's just being probed ahead of actually being used. The caller was responsible for probing the space up to that 4K offset. It's counterintuitive, but in practice it works as an effective mitigation (and it exists already, so Gentoo might as well use it until real Stack Clash specific protection lands in GCC).
Edit: to give an example: if a function uses 6K of stack space, then -fstack-check will probe pages from [SP+4K] to [SP+10K]. [SP] through [SP+4K] are assumed already probed by the call chain, and the [SP+4K] through [SP+6K] region is being probed explicitly. In the end, nothing gets skipped over.
This only works if literally every function has a probe inserted, which is a really silly dependency and is slow. With a more sensible design, functions with small stack frames don't need probes.
It's also not at all clear that this design works is signals are involved unless there's explicit runtime support.
Sure. -fstack-check wasn't designed for stack clash protection. It's old and it makes little sense in context, but it works and it exists, which is why it's being used until proper Stack Clash prevention lands in GCC 8.
I don't think signals change anything. You can think of them as just function calls that skip over the redzone, then keep probing. The redzone is < 1 page so you should still wind up touching every page.
Oh, I was imagining that referred to a situation where you have a stack (say 8K to keep it aligned), then a 4K guard page (which faults when you grow past it), and then someone probes past it, at 16K. Which may be mapped to all kinds of other things, no?
Sure, but the thing is something would've already probed into the 4K guard page before you had a chance to probe past it. If your stack guard page is the next thing up on the stack and you call that vDSO function, then sure, it'll probe past the guard page. But if all your code is built with -fstack-check then that guarantees you should have already crashed by having some prior function in the call stack probe into that guard page.