|
Message-ID: <20161204164708.GC5749@port70.net> Date: Sun, 4 Dec 2016 17:47:08 +0100 From: Szabolcs Nagy <nsz@...t70.net> To: Thomas Petazzoni <thomas.petazzoni@...e-electrons.com> Cc: Rich Felker <dalias@...c.org>, musl@...ts.openwall.com Subject: Re: [resend] Solving the SSP+PIE issue on i386: recommended solution * Thomas Petazzoni <thomas.petazzoni@...e-electrons.com> [2016-12-04 16:38:57 +0100]: > Buildroot is facing the well-known __stack_chk_fail_local unresolved > symbol issue when PIE executables are built on i386. We have this issue > at least when building openssh, cups and ipmiutil (and possible other > packages which build their code as PIE by default, for one reason or > another). > > However, the solution to this problem is not very clear: > > - It seems like Alpine Linux [1] and OpenWRT [2] have chosen to build a > small piece of code implementing __stack_chk_fail_local() and build > it into a libssp_nonshared.a library. > > However, it is not clear to me why the __stack_chk_fail_local() > symbol provided by musl in libc.so is not sufficient. > this a gcc bug on i386 (and powerpc) gcc can generate *local* calls to __stack_chk_fail_local, so the symbol must be defined in the binary that makes the call (not in an external library like libc.so) this saves code size on targets where making an extern call overhead: they call a local function first which makes the heavy extern call (otherwise every canary check failure path would need to do the heavy extern call in every function). musl defines this symbol because musl itself can be built with stack protection (and for static linking). ideally if the compiler generates local calls as an optimization, then it is the compiler runtime's job to make sure that call is defined (i.e. it should be in libgcc.a that is static linked into the binary). > [1] http://git.alpinelinux.org/cgit/aports/tree/main/musl/APKBUILD > [2] https://github.com/openwrt/openwrt/blob/master/toolchain/musl/patches/200-add_libssp_nonshared.patch > > I guess they are also patching the gcc LINK_SSP_SPEC to link with > ssp_nonshared. It's done in [3] for OpenWRT, and [4] for Alpine. > > [3] https://github.com/openwrt/openwrt/blob/master/toolchain/gcc/patches/5.3.0/230-musl_libssp.patch > [4] http://git.alpinelinux.org/cgit/aports/tree/main/gcc/gcc-6.1-musl-libssp.patch > > - On the other side, the musl-cross project seems to have taken a > different approach: they patch the LINK_SSP_SPEC of gcc to link with > libssp_nonshared, and they [5] claim that their patch, in > combination with commit 55d061f031085f24d138664c897791aebe9a2fab in > musl solves the problem. > > But how does it work? musl doesn't build/install a libssp_nonshared > library. If the fix is that simple, why are Alpine Linux and OpenWRT > producing on their own a minimal libssp_nonshared.a ? > gcc did not do the right thing instead it has a (broken) libssp implementation which includes a small libssp_nonshared.a and it adds -lssp and -lssp_nonshared to the link spec when necessary. but since libssp is broken the libc has to provide a sane ssp runtime. so gcc allows the libc to implement ssp, but then it requires the libc to provide the loccal symbol too which is not possible (in case of dynamic linking). ..and it is a gcc internal target specific optimization thing so it does not make sense to do this in the libc even if it is possible. what glibc does: the libc.so visible to ld is a linker script that magically adds glibc's libssp_nonshared.a to the link command. (and they build gcc with disabled libssp) (of course this linker script can cause horrible pains and misery) what musl does: implements the public api in libc.so, but requires the compiler to provide the local definition. So e.g. you can build gcc with libssp enabled which has libssp_nonshared.a or you can provide one yourself.. but gcc does not add -lssp_nonshared if it thinks the libc provides ssp, so that's why those patches are needed: they add -lssp_nonshared back. (providing this lib yourself is better since that avoids uselessly building and installing the rest of libssp which can cause trouble if somebody accidentally uses -lssp explicitly) > [5] https://github.com/GregorR/musl-gcc-patches/commit/43fc05be584b8fa7cff566045e8582c525212286 > > What is the recommended fix for this problem ? > fix gcc to be saner. - move __stack_chk_fail_local to libgcc.a (and only on the targets where it is actually generated), and fix up the link_spec in the driver (-lssp_nonshared is not needed anymore). - have an option that does not generate any call at all: emitting a __builtin_trap instruction is safer and smaller than any form of extern call. given the amount of hackery around this in gcc these are not easy to do, i think alpine originally tried to do the right thing but they run into bootstrapping problems when the toolchain itself is built with ssp. > Thanks a lot, > > Thomas > -- > Thomas Petazzoni, CTO, Free Electrons > Embedded Linux and Kernel engineering > http://free-electrons.com
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.