systemd is a set of system administration daemons
Recently, the systemd developers had a discussion in which it was placed on the table the issue of reducing libsystemd library dependencies (the library in charge of implementing services and interacting with systemd). This is because there is currently a certain concern about increasing third party dependencies in libsystemd that are not controlled by the project and this increases the attack surface. The discussion starter notes that libsystemd loads several critical libraries, such as libzstd, liblz4, and libgcrypt, in addition to liblzma and glibc. This raises significant security issues, especially if these third-party libraries are compromised.
On Fedora, for example, more than 150 packages depend on libsystemd, increasing the complexity and associated risks. The proposal To address this involves split libsystemd into several separate libraries, each responsible for a specific API. This would allow third-party dependencies to be loaded only when necessary, thus reducing exposure to potential vulnerabilities in libraries not directly controlled by systemd developers.
However, developers by systemd They argue that this separation would be problematic due to the interconnection of drivers present in libsystemd. They believe that splitting would be labor-intensive and could result in a loss of efficiency or the need to duplicate code, which would counteract the intended security benefits.
Instead of a complete separation, libsystemd has gone for a more dynamic approach by dynamically loading the liblzma, libzstd and liblz4 libraries when necessary, using the dlopen() call. A similar change is planned to be implemented for libgcrypt in future releases to address both security concerns and code efficiency and maintainability needs.
I believe that most of these dependencies are not necessary to implement core libsystemd functions, such as those mentioned above.
This problem may mean splitting libsystemd into multiple libraries that implement different APIs, one of which, for example libsystemd-core, would only depend on libc, and other more specialized libraries would add other dependencies. Also, if some of the dependencies are only needed for certain systemd services, move the dependencies to those services.
The end effect of this should be to reduce the attack surface and improve system security.
During the discussion There was one point which most of the developers criticized, and they mention that the decision to load third party libraries implicitly using dlopen() in libsystemd would generate additional work due to the added complexity in diagnosis and lack of link visibility, they also mention that this complicates the identification of libsystemd API calls that connect to external library functions, since it is not obvious in the code. This new way of loading, although it does not change the underlying architecture, hides external components from maintainers and users.
Lenart Pottering expressed his disagreement with the idea of splitting libsystemd into multiple libraries due to the complications this would bring in code sharing and maintaining API and namespace stability. Splitting libsystemd would require exposing all internal drivers or statically compiling them separately in each library, which could increase size due to code duplication or make it difficult to manage system stability and consistency.
Instead of division, the strategy of loading external libraries only when necessary is considered optimal, In addition, to address the added complexity in the diagnosis, it is proposed to add additional fields to the ELF files with information about the dynamic dependencies loaded, allowing debuggers to process this information and display it in the output of tools such as readelf. This would provide greater transparency and visibility into the dynamic dependencies used by libsystemd, thus making it easier to diagnose and debug issues related to dynamically loaded external libraries.
Lenart recommended to developers of applications that, instead of linking directly with libsystemd for a specific function, a protocol handler is implemented at the application level.
This strategy of implementing protocol drivers at the application level offers several advantagess:
- Reduces dependency on libsystemd and avoids loading external libraries when they are not needed.
- Provides more flexibility and control over the specific functionality required by the application.
- Simplifies diagnosis and debugging by having more direct control over the implementation of specific functions.
- In general, this approach promotes modularity and independence of applications, improving flexibility and efficiency in software development and maintenance.
If you are interested in knowing more about it, you can check the details In the following link.