I am not convinced dlopen will it make secure in the end. I am not sure this is a good solution. dlopen makes those dependencies non-obvious from packaging side and non-visible from ldd or similar checking programs.
I think it should be considered to offer more than one dynamic library. For example most services I maintain links to libsystemd just because it wants sd_notify calls in their services. Without any proof I would expect quite many services would have similar problem. Could be perhaps libsystemd broken into few more dynamic linked libraries? I somehow doubt any kind of compression is needed for sd_notify calls.
Could be even smaller library libsystemd-notify linked from libsystemd, which would allow end applications to explicitly declare they need more limited set of functions?
Is there now relatively simple way to analyze packages depending on libsystemd, how rich functionality they need to use? I somehow doubt many packages need explicit work with journal. If they do, okay, use more heavy-weight library. But quite alot of programs needs just sd_notify* and sd_listen* calls, maybe with addition to sd_booted.
The best example is sshd itself, which plays important role in this story. For a very good reason.
$ objdump -T /usr/sbin/sshd | grep sd_ 0000000000000000 DF *UND* 0000000000000000 (LIBSYSTEMD_209) sd_notify
Less code linked into libraries means less code needs to be analysed for malware or security scans. It also allows user to explicitly declare just limited functions should be available.
I have made crude script getting calls used on my own system. While there is larger group with also journal involved, I think number of packages using just sd_notify, sd_listen or similar is not unimportant.
$ dnf repoquery --whatdepends systemd-libs --alldeps | sort -u | while read PKG; do rpm -q "$PKG" >/dev/null && echo "$PKG"; done | tee installed $ cat installed | while read PKG; do rpm -ql "$PKG" | grep -E '^(/usr/s?bin/|/usr/lib64/|/usr/libexec)' | while read BIN; do objdump -T "$BIN" 2>/dev/null | grep -E ' (sd|udev)_' | sed -e 's/[0-9a-f]+\s*DF\s*(*UND*|.text)\s*[0-9a-f]+\s*//' -e "s|^|$PKG ${BIN}: |" ; done; done | tee libsystemd-calls.txt
Attached the results in libsystemd-calls.txt attachment.
I would prefer ability to explicitly declare I want just limited functionality for cooperating with systemd, without any obscure dlopen calls. They are even more suspicious in low-level library and I don't think they should be used to solve resource limitations. They make it more difficult to discover actually used dependencies by static analysis tools. udev has already own library, perhaps notify and bus should be able to use with a lightweight library too?
Regards, Petr
On 30. 03. 24 19:43, Zbigniew Jędrzejewski-Szmek wrote:
libsystemd is linked to compression libraries primarly because those compressors are options for journald files, and we generally want to mainain the property that all journal files from the past, as well as journal files from other systems, can be read by later journal code.
(bzip2 is an exception here. It is only used by systemd-importd and related tools, so libsystemd was never linked to it, IIRC.)
In recent systemd versions, dlopen is used for various compression libraries and other libraries, so they'll be opportunistically loaded if needed, effectively making those dependencies optional at runtime.
Conversions to use dlopen require a bit of boilerplate code and make the code less readable, so we only would to them if there was a reason. Usually, this reason was size and/or the dependency tree. Compression libraries are very small and have no dependencies, so it wasn't considered important to use dlopen for them. But now that there's a new motivation, as mentioned elsewhere in the thread, we'll load pretty much all dependencies of libsystemd via dlopen.
Zbyszek