|
Message-ID: <20150405034412.GA28727@brightrain.aerifal.cx> Date: Sat, 4 Apr 2015 23:44:12 -0400 From: Rich Felker <dalias@...c.org> To: musl@...ts.openwall.com Subject: The path to building libc with stack protector Since having libc itself built with stack protector would have rendered CVE-2015-1817 at-most-DoS, I've added ssp in libc to the roadmap for this release cycle and started working on how to achieve it. The core difficulty is avoiding running code that depends on the stack protector canary being setup/available before it actually is. Since the way the canary is accessed varies by arch and there are two main methods (and some archs even support both as runtime options): 1. Thread-local canary at a fixed offset from the thread pointer. This requires the thread pointer to be setup. 2. Global variable storing canary. This requires symbol relocations to have been performed. Both are basically non-issues for static linking; we can just build __libc_start_main.c, __stack_chk_fail.c, and __init_tls.c without stack protector and all is well. Dynamic linking is much harder for both cases. For variant 1 (TLS), we can't know the size of TLS needed until all libraries are loaded, but by that time we've already called a lot of code that needs to be protected by stack protector. The only solution I see here is to initialize the thread pointer twice. We can aim to optimize out the second call as long as the final TLS fits in the builtin_tls object and doesn't have increased alignment requirements, reducing the runtime cost a bit, but in general we may need to perform the operation twice. In any case, I consider this a solved problem. For variant 2 (global), things are much harder. The final location where the global will reside cannot be known until the main program's relocations are processed, since there may be a copy relocation. And if the dynamic linker is being used as a command to load the main program, it needs to make a number of calls before the main program is even loaded. So I see no clean solution except to do tentative relocations early and possibly override them later. We could do this only for the __stack_chk_guard symbol, or for all symbols in libc. I would really prefer to do the latter -- tentatively resolve all relocations in libc.so before doing anything else. This would have a number of additional benefits besides making ssp-libc possible: - We would be immune to poor compiler and linker choices whether to use PC-relative or GOT-based access and whether to resolve these references at ld time or leave them for the dynamic linker; old toolchains without -Bsymbolic-functions should even work. - It lets us setup a true compiler barrier between GOT relocation and GOT accesses. Right now, the compiler can theoretically load addresses from the GOT (and cache them in registers or on the stack for later use) before the GOT is relocated. - It might allow us to reduce or eliminate the need for arch-specific early relocation code like mips, powerpc, and microblaze use now. - It eliminates the undocumented and fragile assumptions the dynamic linker makes about what functions it can call early. Right now, it can't call anything that depends on relocations having been performed, so for instance it can't use any of the standard stdio FILE streams because these objects contain function pointers. This would also allow us to eliminate the static wrap_write function in vfprintf.c and other similar hacks. - We could allow symbol interposition if we want, e.g. replacing malloc (of course other major remain for that one). One complication of doing early relocations that might need to be replaced later is that, on archs without RELA, the original addend is clobbered when the relocation is performed. Fortunately, PLT and GOT type relocations don't have addends, and these seem to be the only ones we'd actually need to re-do later. The above is all just high-level conceptual. Actually implementing this cleanly is still a pretty big task, and I might end up making a lot of cleanup/overhaul in the dynamic linker in the process. I'll keep posting more updates on design ideas as I make progress on it. Rich
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.