|
|
Message-ID: <csi5RfKTpfkBN0IaWsbQqs8EuuE_i4k1bUK1bdqGu4HkTKazVuo1iSGK_d5--blDgnaI_r2AMnndDYFAbtrdJaethNnJF8DQgNqF3q5Ydyk=@hexsys.org> Date: Sat, 10 Jan 2026 18:54:39 +0000 From: Ali Polatel <alip@...sys.org> To: "oss-security@...ts.openwall.com" <oss-security@...ts.openwall.com> Subject: The Curious Case of Stack Pivot Detection Dear kind people, I hope you're fine and healthy. The reason I am writing this mail is to share a few of my experiments and research I've done to come up with a reasonable stack pivot detection for the Syd kernel. TL;DR I have failed and I have learned a lot. I have also learned everyone is doing various levels of wrong and I have yet to come up with a "correct" solution. Are we doing it wrong or are we attacking the wrong link? Please discuss. The obvious idea is to check if stack pointer points to a valid stack region at various boundaries. This solution is so obvious you'd imagine even a 4-year-old can come up with it, yet G**gle has a patent[1] on it. Curious (mis)use of software patents where an entity patents the equation "foo < bar < baz". What do we do if they go one step ahead and patent "<"? Use emoji for maths? Move to Mars? Anyhow, this is not what I am here to discuss. OpenBSD does something similar with MAP_STACK[2] and Windows 8 had a similar mitigation until someone demonstrated a trivial bypass[3]. Finding out this bypass was an important step forward for me so I went ahead and rewrote it[4] for UNIX and verified it bypasses what Syd had at the time and what OpenBSD has. This bypass is a simple improvement of what OpenBSD regression tests have and involves a quick jumpback to the stack. Funnily if you remove the printf in the intermediate stage of the bypass OpenBSD's SP check at write(2) boundary will catch and kill you so keep it quiet as you bypass this delicate mitigation ;). Another roadblock for the SP points to a stack region detection is in userspace there's no clear definition of "stack". The stack of the main thread is handled by the kernel where everything is fine but thread stacks are typically your language runtime's business. As an example if you check the stack of a Go thread on Linux, you'll most probably find the VMA is named " Go: heap". It may be the stack for now, but maybe it was not a bit ago or won't be a bit later. Asking Go devs to use MAP_STACK would probably be rejected because it breaks the whole model of how they do multithreading... I digged a bit deeper and found what I thought was an improvement at the time. Why not check the frame pointer instead of the stack pointer? Why not both? It was fairly easy to patch Syd for this so I got to testing. This way of detection is imho more reliable and less prone to bypassing however there's a big issue. Both gcc and clang imply -fomit-frame-pointer with -O2 so you'll have a hard time finding a binary in the wild these days that has frame pointers. If I were OpenBSD, I'd compile the world with -fno-omit-frame-pointer and move on with my life and I'd humbly and kindly recommend them to do that in short of any better ideas. Now, my tests showed me another problem. Stack pivotting is not as unusual and as malicious as you think. In fact, various programs make use of it in arguably weird ways to achieve their goals. One example is Firefox's crashhelper, bash, gawk, ceph, ... I can easily come up with dozens more if I enable this mitigation and build Exherbo packages under Syd as we proudly enable package testing by default. So even if you'd come up with a reliable, efficient way to detect stack pivot, you're gonna have loads of false positives to manage. Good luck. Finally, after I ended my experiments and reverted[5] Syd's stack pivot detection. I came across LKRG's README[6] incidentally which mentions validating the stack pointer with "pCFI", their version of coarse-grained CFI, which also seems to check the frame pointer[7] against the stack. I'd be curious to know whether there's any added mechanism to detect stack pivot when the binary is compiled without frame pointers when the frame pointer is reused by compiler for different purposes. Best regards, Ali Polatel [1]: https://patents.google.com/patent/US10853480B2/en [2]: https://isopenbsdsecu.re/mitigations/map_stack/ [3]: https://archive.ph/xS2Fl#selection-13.0-243.52 [4]: https://gitlab.exherbo.org/sydbox/sydbox/-/blob/main/dev/stackpivot-jumpback-bypass.c [5]: https://gitlab.exherbo.org/sydbox/sydbox/-/commit/f03db6c677ddf5dbf87adeb6bd5efb0677869104 [6]: https://github.com/lkrg-org/lkrg/blob/b8b1418a6c1e7229cdf3dfa020fcc4945e108d83/README#L505 [7]: https://github.com/lkrg-org/lkrg/blob/b8b1418a6c1e7229cdf3dfa020fcc4945e108d83/src/modules/exploit_detection/p_exploit_detection.c#L1585-L1591 Download attachment "publickey - alip@...sys.org - 0xC22DA9DE.asc" of type "application/pgp-keys" (637 bytes) Download attachment "signature.asc" of type "application/pgp-signature" (344 bytes)
Powered by blists - more mailing lists
Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.