On Tue, 2011-08-09 at 08:47 -0400, Steve Grubb wrote: > My main concern is that the macro will be misapplied and overall performance > will take a hit. That's a valid concern, but any hardened build would have this problem. I'm happy to talk about how the performance impact can be mitigated, but it seems unfair to blame a convenience macro for being convenient. > I don't know how a macro can tell the intent of an application as it > links it. There has not been a chmod so that it knows this is setuid > and needs more protection. Sure, but you can't possibly know suid-ness until %files time anyway. I was not attempting to enforce a policy here. I was attempting to make applying hardened build flags easy in the common case. This isn't an excuse for not using one's brain as a packager. I had hoped I had made that clear, and I did not intend to imply that this was the _only_ way to get a hardened build, but I apologize for being insufficiently precise. > For example, if coreutils was built with this (and coreutils seems to > be correct as is) because it has setuid programs, then would all apps > get the PIE/Full RELRO treatment? If so, many of coreutils apps are > called constantly by shell scripts. Yes, they would. coreutils might not be a suitable target for this flag. That's okay, coreutils is welcome to customize its build using something other than this convenience macro. > If this were used on tcpdump, would full relro leak to the libpcap? I'm not sure why you raise this concern in this particular context, since the semantics would be the same regardless of this macro. But since this detail is worth expanding on, let's ask the dynamic linker what happens. Prelink makes this harder than you might hope, but if I'm reading the scrolls right, LD_USE_LOAD_BIAS=0 effectively turns it off, and LD_DEBUG=reloc will show us the steps in relocation processing. So what does a normal execution look like? % LD_USE_LOAD_BIAS=0 LD_DEBUG=reloc /bin/ls /dev/null |& grep reloc 6762: relocation processing: /lib64/libattr.so.1 (lazy) 6762: relocation processing: /lib64/libpthread.so.0 (lazy) 6762: relocation processing: /lib64/libdl.so.2 (lazy) 6762: relocation processing: /lib64/libc.so.6 6762: relocation processing: /lib64/libacl.so.1 (lazy) 6762: relocation processing: /lib64/libcap.so.2 (lazy) 6762: relocation processing: /lib64/librt.so.1 (lazy) 6762: relocation processing: /lib64/libselinux.so.1 (lazy) 6762: relocation processing: /bin/ls (lazy) 6762: relocation processing: /lib64/ld-linux-x86-64.so.2 Note that libc and ld.so are not described as lazy. This is because they have been linked with -z now: % eu-readelf -a /lib64/libc.so.6 | grep BIND_NOW FLAGS BIND_NOW STATIC_TLS % eu-readelf -a /lib64/ld-linux-x86-64.so.2 | grep BIND_NOW BIND_NOW What if we were to force the issue? % LD_BIND_NOW=1 LD_USE_LOAD_BIAS=0 LD_DEBUG=reloc /bin/ls /dev/null |& grep reloc 6766: relocation processing: /lib64/libattr.so.1 6766: relocation processing: /lib64/libpthread.so.0 6766: relocation processing: /lib64/libdl.so.2 6766: relocation processing: /lib64/libc.so.6 6766: relocation processing: /lib64/libacl.so.1 6766: relocation processing: /lib64/libcap.so.2 6766: relocation processing: /lib64/librt.so.1 6766: relocation processing: /lib64/libselinux.so.1 6766: relocation processing: /bin/ls 6766: relocation processing: /lib64/ld-linux-x86-64.so.2 Cool, looks like that does what we would expect. But does the environment variable have a different effect than if the executable itself were marked DT_BIND_NOW? Well, let's try with a program that _is_ already -z now: % eu-readelf -a /usr/bin/ssh | grep BIND_NOW BIND_NOW % LD_USE_LOAD_BIAS=0 LD_DEBUG=reloc /usr/bin/ssh -V |& grep reloc 6790: relocation processing: /lib64/libpthread.so.0 (lazy) 6790: relocation processing: /lib64/libkeyutils.so.1 (lazy) 6790: relocation processing: /lib64/libkrb5support.so.0 (lazy) 6790: relocation processing: /lib64/libfreebl3.so (lazy) 6790: relocation processing: /usr/lib64/libsasl2.so.2 (lazy) 6790: relocation processing: /lib64/libnspr4.so (lazy) 6790: relocation processing: /lib64/libplc4.so (lazy) 6790: relocation processing: /lib64/libplds4.so (lazy) 6790: relocation processing: /usr/lib64/libnssutil3.so (lazy) 6790: relocation processing: /usr/lib64/libnss3.so (lazy) 6790: relocation processing: /usr/lib64/libsmime3.so (lazy) 6790: relocation processing: /usr/lib64/libssl3.so (lazy) 6790: relocation processing: /lib64/libc.so.6 6790: relocation processing: /lib64/libcom_err.so.2 (lazy) 6790: relocation processing: /lib64/libk5crypto.so.3 (lazy) 6790: relocation processing: /lib64/libkrb5.so.3 (lazy) 6790: relocation processing: /lib64/libgssapi_krb5.so.2 (lazy) 6790: relocation processing: /lib64/libresolv.so.2 (lazy) 6790: relocation processing: /lib64/libcrypt.so.1 (lazy) 6790: relocation processing: /lib64/libnsl.so.1 (lazy) 6790: relocation processing: /lib64/libz.so.1 (lazy) 6790: relocation processing: /lib64/libutil.so.1 (lazy) 6790: relocation processing: /usr/lib64/liblber-2.4.so.2 (lazy) 6790: relocation processing: /usr/lib64/libldap-2.4.so.2 (lazy) 6790: relocation processing: /lib64/libdl.so.2 (lazy) 6790: relocation processing: /lib64/libcrypto.so.10 (lazy) 6790: relocation processing: /lib64/libselinux.so.1 (lazy) 6790: relocation processing: /usr/lib64/libfipscheck.so.1 (lazy) 6790: relocation processing: /usr/bin/ssh 6790: relocation processing: /lib64/ld-linux-x86-64.so.2 6790: relocation processing: /lib64/libnss_files.so.2 (lazy) Indeed not! ssh itself is eagerly bound but its dependencies are not. Thus we can conclude that full- or partial-relro-ness is a per-object property, and that fully hardening an entire runtime-linked image requires hardening all of its components. This isn't entirely surprising, but it's nice to not be surprised. (Yes, Dmitri, it's good to be fine.) The question then becomes which libraries you want to so harden. Again, this is a judgement call and I was not intending to imply that this would be applied globally; if I had, it wouldn't have been a macro at all. (Of course it's a friendly call.) For the case of tcpdump we could probably reasonably say all of its deps should be hardened: % LD_USE_LOAD_BIAS=0 LD_DEBUG=reloc tcpdump -h |& grep reloc 14319: relocation processing: /lib64/libz.so.1 (lazy) 14319: relocation processing: /lib64/libdl.so.2 (lazy) 14319: relocation processing: /lib64/libc.so.6 14319: relocation processing: /usr/lib64/libpcap.so.1 (lazy) 14319: relocation processing: /lib64/libcrypto.so.10 (lazy) 14319: relocation processing: tcpdump (lazy) 14319: relocation processing: /lib64/ld-linux-x86-64.so.2 zlib is historically a CVE fest, pcap handles untrusted data by design, libcrypto is almost definitely worth hardening. For the case of libdl I suspect the glibc maintainers may have a functional reason to want it to not be -z now, but I've not investigated in that level of detail. Certainly from a performance perspective it's unlikely to make much difference, the thing only imports 23 symbols and exports 15. (tcpdump using libdl is a bit of a red flag on its own, though. In attempting to build it I was mildly surprised to see that it BuildRequires: bluez-libs-devel; yet from the trace above it's not linked against anything from bluez. So I would assume that it can dynamically load plugins, and that either tcpdump should call dlopen() with RTLD_NOW for them, or that they should themselves be linked with -z now. Fortunately, the new _hardened_build convenience macro makes this quite easy...) - ajax
Attachment:
signature.asc
Description: This is a digitally signed message part
-- devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxxx https://admin.fedoraproject.org/mailman/listinfo/devel