3 ms·
Do any Linux/glibc or Linux/musl systems support static PIE binaries, yet? Without static PIE support you don't benefit from ASLR (at least not fully). This 201
by wahern 6y ago
Do any Linux/glibc or Linux/musl systems support static PIE binaries, yet? Without static PIE support you don't benefit from ASLR (at least not fully). This 2018 article seems like a good breakdown of the issues: https://www.leviathansecurity.com/blog/aslr-protection-for-statically-linked-executables https://www.leviathansecurity.com/blog/aslr-protection-for-s...
OpenBSD has supported static PIE since 2015; not just supported, but all system static binaries (e.g. /bin and /sbin) are built as static PIEs, and I believe PIE is the default behavior when using `cc -static`. The reasons for the switch and the required toolchain changes are summarized in this presentation: https://www.openbsd.org/papers/asiabsdcon2015-pie-slides.pdf https://www.openbsd.org/papers/asiabsdcon2015-pie-slides.pdf
Also, simply checking the "static PIE" box isn't the end of the story. There are different ways to accomplish it, and some are better than others in terms of ASLR, W^X, and other exploit mitigations. It's been a couple of years since I last looked into and had a hold on all the issues simultaneously[1], but the basic takeaway is that dynamic linking in system toolchains and system runtimes is far more mature than static linking.
[1] static PIE issues are a nexus of exploit mitigation techniques, so if you want to deep dive into exploit mitigation or even just linking issues then chasing the static PIE rabbit is a good approach.
- monocasa 6y agoI imagine there's some way to, because the kernel is able to apply ASLR to the dynamic linker itself.
- wahern 6y agoIt's not a matter of possible, but whether the work has been done throughout the toolchain and runtime stacks. When OpenBSD implemented static PIE, -static and -pie, the literal options and the code generation aspects more generally, were still mutually exclusive in GCC and clang. GCC required patching to enable both static linking and PIE generation. In fact, my local GCC 9.3 man page still says that -static overrides -pie; to build static PIE seems to require the special option -static-pie, in addition to -fPIE/-fPIC when building the object code. But it's not enough for the compiler and compile time linker to support it. libc and libstdc++/libc++ also need support, both internally as well as in the built libraries. And I think libdl might need support if you want dlopen to work from a static PIE binary. Likewise for libpthread. Supporting static PIE requires the cooperation of many moving parts. And that's just to support it. Making it easy, let alone the default behavior, so that it doesn't require many carefully coordinated, obscure flags without the risk of any misstep silently disabling some exploit mitigation, is yet another story. It can be done. It should be done. But to what extent has it been done? I'm not sure, though some quick Googling suggests GCC and clang are mostly there, at least in terms of nominal support (which, again, is distinct from fully supporting all the same mitigation measures). glibc seems to have gotten some support (e.g. --enable-static-pie in glibc's build), though I'm not sure whether it's available in distros. And I would guess that musl libc support is pretty far along, and presumably more mature than glibc's given that Rich Felker started experimenting with static PIE several years ago, shortly after OpenBSD did their work. See https://www.openwall.com/lists/musl/2015/06/01/12 https://www.openwall.com/lists/musl/2015/06/01/12
- monocasa 6y agoFor sure. My comment was directed at Linux the kernel rather than Linux the ecosystem, but it's a totally valid point that for practical purposes that distinction can border on meaningless.
- mforney 6y agoMost Linux/musl systems support it. On Alpine, gcc is built with `--enable-default-pie` so all static libraries can be linked into a static PIE. On vanilla gcc (since version 8 when static PIE was upstreamed), `-static` means non-PIE static executable and there is a separate flag for `-static-pie` for static PIE. Alpine patches gcc so that `-static` and `-pie` are independent flags, so both `cc -static` and `cc -static-pie` will produce a static PIE.
- Ericson2314 6y agoNixpkgs / NixOS does.
- saagarjha 6y agoI'm not sure I understand the first link you posted: if a binary is statically linked, why does it need a GOT? It's literally calling functions in its own binary…
- wahern 6y agoBut where in its own binary? To support ASLR of code (a ROP mitigation), especially fine-grain randomization, function call sites can't use static addressing, either absolute or relative, pointing directly to a function. To support ASLR of code you can either rewrite every function call site on load (kinda similar to DLLs on Windows), or use one or more tables that are updated at runtime (PLTs, GOT, etc). BSD and Linux environments use the PLT/GOT approach because 1) it's a better fit for ELF, 2) shares most of the preexisting instrumentation with dynamic linking, and 3) preserves the ability to share most of the mapped pages of static binaries (imagine if a static /bin/sh was effectively rewritten on every invocation). Trying to accomplish this safely and effectively is what RELRO is about. See https://www.redhat.com/en/blog/hardening-elf-binaries-using-relocation-read-only-relro https://www.redhat.com/en/blog/hardening-elf-binaries-using-... But RELRO poses some dilemmas regarding performance, and depending on your choices as well as the details of the implementation, RELRO might be ineffective or, worse, introduce exploits of its own. See https://www.usenix.org/system/files/conference/usenixsecurity15/sec15-paper-di-frederico.pdf https://www.usenix.org/system/files/conference/usenixsecurit... It's difficult to achieve a design that provides all the desirable exploit mitigations without sacrificing startup latency and other features. OpenBSD added a new syscall, kbind (https://man.openbsd.org/kbind https://man.openbsd.org/kbind), so that they can have lazy binding without being susceptible to the RELRO exploits mentioned in that Usenix paper. (Unfortunately, the 2018 leviathansecurity.com article fails to mention kbind, even though kbind was added to OpenBSD in 2015.) There are other approaches. I think the PaX Team has written quite alot about their preferred techniques. But the point is that static PIE, which is desirable because of ASLR and other reasons (e.g. unification of code generation techniques), touches upon varying and distant components of toolchains and runtimes.
- saagarjha 6y agoI know how ASLR/ROP/PLT/GOT/RELRO work, but I'm still not understanding what's going on here. When you statically link a binary, you get…one file. And that gets loaded into memory together, and to make it PIE you have all the jumps be pc-relative. Like, a straight up jump instruction to a fixed offset. So where the the room for a table like this? (Unrelated, but since you brought it up: kbind is IMO not a very good mitigation. It seems that all you have to do to bypass it is leak a cookie and ROP to that one place in ld.so that is "blessed" and then you not only have the ability to scribble all over your read-only GOT but as far as I can tell you can overwrite any read-only memory, which means it opens up an extremely valuable exploit primitive…)
- cosmojg 6y ago> but the basic takeaway is that dynamic linking in system toolchains and system runtimes is far more mature than static linking. But that's a chicken-or-egg problem, right? The only way static linking tools will reach parity with dynamic ones in terms of maturity is if static linking replaces dynamic linking as the de facto method of choice.
- pjmlp 6y agoGenerally speaking static compilation has had 30 years of head start across multiple OS and hardware architectures, until dynamic compilation was even an option on mainstream computing, it was after all the only way, with dynamic only available in research platforms like what was going on at Xerox PARC. So this widespread lack of knowledge that static is actually more mature than dynamic is kind of ironic.