New hardened build support (coming) in F16

Adam Jackson ajax at redhat.com
Tue Aug 9 14:39:26 UTC 2011


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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: This is a digitally signed message part
Url : http://lists.fedoraproject.org/pipermail/devel/attachments/20110809/486877f6/attachment-0001.bin 


More information about the devel mailing list