-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add an open-coded check for selinux to avoid linkage to libselinux/libpcre/libdl #6464
Conversation
With -Dselinux-workaround=true: $ ldd build/libnss_mymachines.so.2 linux-vdso.so.1 (0x00007fffec33e000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f18404e4000) libc.so.6 => /lib64/libc.so.6 (0x00007f1840113000) librt.so.1 => /lib64/librt.so.1 (0x00007f183ff0b000) libcap.so.2 => /lib64/libcap.so.2 (0x00007f183fd06000) /lib64/ld-linux-x86-64.so.2 (0x00005612fe411000) With -Dselinux-workaround=false: linux-vdso.so.1 (0x00007ffe5ad87000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f107f893000) libc.so.6 => /lib64/libc.so.6 (0x00007f107f4c2000) librt.so.1 => /lib64/librt.so.1 (0x00007f107f2ba000) libcap.so.2 => /lib64/libcap.so.2 (0x00007f107f0b5000) libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f107ee8d000) /lib64/ld-linux-x86-64.so.2 (0x000055ec087a0000) libpcre.so.1 => /lib64/libpcre.so.1 (0x00007f107ec19000) libdl.so.2 => /lib64/libdl.so.2 (0x00007f107ea15000) The result is the same for nss-resolve and nss-systemd. This is with gcc-7.1.1-3.fc26.x86_64, binutils-2.27-24.fc26.x86_64, meson-0.41.1-1.fc26.noarch, libselinux-2.6-6.fc26.x86_64. The sequence of calls from the nss modules to selinux is: sd_bus_open_system → sd_bus_start → bus_start_address → bus_container_connect_socket → bus_socket_start_auth → bus_get_peercred → mac_selinux_use → is_selinux_enabled It seems that eliminating is_selinux_enabled() is enough to allow gcc to deduce that the other selinux functions are not necessary and drop the selinux linkage. For some reason this only works when mac_selinux_use() is defined in a seperate compilation unit. The reason to cut down the library list is that those modules are loaded everywhere, also for very short-lived programs, so every library adds a small cost. Additionally, presence of additional libraries in memory — particularly libdl — can be argued to make it easier to find code to reuse from exploits. Such reduction should make the installation of our nss modules by default more palatable to some folks. This is a bit ugly, but might be worth the trouble. Previously, in 8c78165 (and two earlier commits) I replaced linking to libshared.la with libsystemd-internal.la (which is now libsystemd_internal or libsystemd.a under meson), to remove linkage to liblzma, liblz4, libgcrypt, libgpg-error, libacl, libidn, and libseccomp. At the time Fedora builds were using libtool which misplaced the --as-needed argument. Under meson it is placed correctly (before any libraries).
maybe we should go the other way, and try to remove that call chain into libselinux. For example, I think we could just invoke getpeersec() unconditionally, there's not really much of a cost involved with that, and we could even cache if it returns EOPNOTSUPP if there's value in suppressing this syscall on each connection. AFAICS it's the only place we call into the selinux code. Or to say this differently: if the kernel allows us to query that data we should also be Ok with passing it on to our own caller, regardless if selinux is technically on or off... |
I'll try that and see how the final linkage looks like. It's also possible that me might have to split libsystemd-bus into selinux and non-selinux parts. The whole things is a mess :( |
Quoting Lennart Poettering in systemd#6464 (comment): > If the kernel allows us to query that data we should also be Ok with passing > it on to our own caller, regardless if selinux is technically on or off... The advantage is that this allows gcc to be smarter and reduce linkage: (before)$ ldd build/libnss_systemd.so.2 linux-vdso.so.1 (0x00007ffeb46ff000) librt.so.1 => /lib64/librt.so.1 (0x00007f2f60da6000) libcap.so.2 => /lib64/libcap.so.2 (0x00007f2f60ba1000) libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f2f60978000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f2f60759000) libc.so.6 => /lib64/libc.so.6 (0x00007f2f60374000) /lib64/ld-linux-x86-64.so.2 (0x00007f2f61294000) libpcre2-8.so.0 => /lib64/libpcre2-8.so.0 (0x00007f2f600f0000) libdl.so.2 => /lib64/libdl.so.2 (0x00007f2f5feec000) (after )$ ldd build/libnss_systemd.so.2 linux-vdso.so.1 (0x00007ffe5f543000) librt.so.1 => /lib64/librt.so.1 (0x00007f427dcaa000) libcap.so.2 => /lib64/libcap.so.2 (0x00007f427daa5000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f427d886000) libc.so.6 => /lib64/libc.so.6 (0x00007f427d4a1000) /lib64/ld-linux-x86-64.so.2 (0x00007f427e196000) Note that this only works in conjuction with the previous commit: either of the two commits alone does not have the desired effect on linkage. Replaces systemd#6464.
Quoting Lennart Poettering in systemd/systemd#6464 (comment): > If the kernel allows us to query that data we should also be Ok with passing > it on to our own caller, regardless if selinux is technically on or off... The advantage is that this allows gcc to be smarter and reduce linkage: (before)$ ldd build/libnss_systemd.so.2 linux-vdso.so.1 (0x00007ffeb46ff000) librt.so.1 => /lib64/librt.so.1 (0x00007f2f60da6000) libcap.so.2 => /lib64/libcap.so.2 (0x00007f2f60ba1000) libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f2f60978000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f2f60759000) libc.so.6 => /lib64/libc.so.6 (0x00007f2f60374000) /lib64/ld-linux-x86-64.so.2 (0x00007f2f61294000) libpcre2-8.so.0 => /lib64/libpcre2-8.so.0 (0x00007f2f600f0000) libdl.so.2 => /lib64/libdl.so.2 (0x00007f2f5feec000) (after )$ ldd build/libnss_systemd.so.2 linux-vdso.so.1 (0x00007ffe5f543000) librt.so.1 => /lib64/librt.so.1 (0x00007f427dcaa000) libcap.so.2 => /lib64/libcap.so.2 (0x00007f427daa5000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f427d886000) libc.so.6 => /lib64/libc.so.6 (0x00007f427d4a1000) /lib64/ld-linux-x86-64.so.2 (0x00007f427e196000) Note that this only works in conjuction with the previous commit: either of the two commits alone does not have the desired effect on linkage. Replaces #6464.
I'm not entirely sure why this works, but it has a pretty nice effect. Loading additional libraries into every process which uses the glibc resolver interface is not nice: it slows things down, and has potential security effects, by making it easier to exploit vulnerabilities. I would like this, or something to the same effect, to go in.