3 ms·
There are a bunch of other cases where guard pages don't help you (as long as you're filling in the bytes from the far end of the stack first, as you probably a
by geofft 8y ago
There are a bunch of other cases where guard pages don't help you (as long as you're filling in the bytes from the far end of the stack first, as you probably are on a stacks-grow-down architecture). If you start overwriting an area of memory that's being used by another thread, even if you eventually segfault, you've still corrupted memory. That can be a problem if the process has multiple threads and you can corrupt another thread's memory, or if you overwrite mmaped data and so the writes get committed to disk even if the program proceeds to crash and restart.
In any case, those + your SEGV handler case are ones where stack clash attacks are exploitable to corrupt memory or hijack control flow. The OOM killer never corrupts memory or permits hijacking control flow; it only kills the process if it's in an irrecoverable situation. So overcommit is much safer.
The technique you describe is sometimes called "stack probing" (or confusingly "stack checking") and is what GCC's -fstack-clash-protection implements, which is why this isn't exploitable on OSes which compile systemd with that option.
- kazinator 8y agoThis is true; if it's under threads and we hop a guard page, we are screwed, due to the race condition; by the time we hit that guard page, the other thread has used the corrupt stack. I have seen this sort of thing happen! Third party routing stack used in system with thread stacks reduced to 64K. Third party stack turned out to have debugging macros producing "{ char msg[8192]; ...}" declarations for sprintf. Twice the size of a page; hopped right into another thread stack. (Don't tell me systemd has threads in it, ouch!)