From 4287c855893b6a2666fbe0422a1e738c47fa3ef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 14 Dec 2021 13:20:28 +0100 Subject: [PATCH 1/3] meson: create new libsystemd-core.so private shared library MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The scheme is very similar to libsystemd-shared.so: instead of building a static library, we build a shared library from the same objects and link the two users to it. Both systemd and systemd-analyze consist mostly of the fairly big code in libcore, so we save a bit on the installation: (-0g, no strip) -rwxr-xr-x 5238864 Dec 14 12:52 /var/tmp/inst1/usr/lib/systemd/systemd -rwxr-xr-x 5399600 Dec 14 12:52 /var/tmp/inst1/usr/bin/systemd-analyze -rwxr-xr-x 244912 Dec 14 13:17 /var/tmp/inst2/usr/lib/systemd/systemd -rwxr-xr-x 461224 Dec 14 13:17 /var/tmp/inst2/usr/bin/systemd-analyze -rwxr-xr-x 5271568 Dec 14 13:17 /var/tmp/inst2/usr/lib/systemd/libsystemd-core-250.so (-0g, strip) -rwxr-xr-x 2522080 Dec 14 13:19 /var/tmp/inst1/usr/lib/systemd/systemd -rwxr-xr-x 2604160 Dec 14 13:19 /var/tmp/inst1/usr/bin/systemd-analyze -rwxr-xr-x 113304 Dec 14 13:19 /var/tmp/inst2/usr/lib/systemd/systemd -rwxr-xr-x 207656 Dec 14 13:19 /var/tmp/inst2/usr/bin/systemd-analyze -rwxr-xr-x 2648520 Dec 14 13:19 /var/tmp/inst2/usr/lib/systemd/libsystemd-core-250.so So for systemd itself we grow a bit (2522080 → 2648520+113304=2761824), but overall we save. The most is saved on all the test files that link to libcore, if they are installed, because there's 15 of them: $ du -s /var/tmp/inst? 220096 /var/tmp/inst1 122960 /var/tmp/inst2 I also considered making systemd-analyze a symlink to /usr/lib/systemd/systemd and turning systemd into a multicall binary. We did something like this with udevd and udevadm. But that solution doesn't fit well in this case. systemd-analyze has a bunch of functionality that is not used in systemd, so the systemd binary would need to grow quite a bit. And we're likely to add new types of verification or introspection features in analyze, and this baggage would only grow. In addition, there are the test binaries which also benefit from this. --- meson.build | 14 ++------------ src/core/meson.build | 14 +++++++++++--- src/shared/meson.build | 2 +- src/test/meson.build | 3 ++- tools/oss-fuzz.sh | 4 +++- 5 files changed, 19 insertions(+), 18 deletions(-) diff --git a/meson.build b/meson.build index 2665024426d..146c95a478f 100644 --- a/meson.build +++ b/meson.build @@ -2021,12 +2021,7 @@ dbus_programs += executable( link_with : [libcore, libshared], dependencies : [versiondep, - threads, - librt, - libseccomp, - libselinux, - libmount, - libblkid], + libseccomp], install_rpath : rootlibexecdir, install : true, install_dir : rootlibexecdir) @@ -2042,12 +2037,7 @@ public_programs += executable( link_with : [libcore, libshared], dependencies : [versiondep, - threads, - librt, - libseccomp, - libselinux, - libmount, - libblkid], + libseccomp], install_rpath : rootlibexecdir, install : conf.get('ENABLE_ANALYZE')) diff --git a/src/core/meson.build b/src/core/meson.build index d229d46779a..87456712131 100644 --- a/src/core/meson.build +++ b/src/core/meson.build @@ -167,12 +167,18 @@ load_fragment_gperf_nulstr_c = custom_target( command : [awk, '-f', '@INPUT0@', '@INPUT1@'], capture : true) -libcore = static_library( - 'core', +libcore_name = 'systemd-core-@0@'.format(meson.project_version()) + +libcore = shared_library( + libcore_name, libcore_sources, load_fragment_gperf_c, load_fragment_gperf_nulstr_c, include_directories : includes, + c_args : ['-fvisibility=default'], + link_args : ['-shared', + '-Wl,--version-script=' + libshared_sym_path], + link_with : libshared, dependencies : [versiondep, threads, libdl, @@ -184,8 +190,10 @@ libcore = static_library( libapparmor, libselinux, libmount, + libblkid, libacl], - build_by_default : false) + install : true, + install_dir : rootlibexecdir) core_includes = [includes, include_directories('.')] diff --git a/src/shared/meson.build b/src/shared/meson.build index 5dc58a863d4..c2e02339746 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -465,13 +465,13 @@ libshared_static = static_library( libshared = shared_library( libshared_name, include_directories : includes, + c_args : ['-fvisibility=default'], link_args : ['-shared', '-Wl,--version-script=' + libshared_sym_path], link_whole : [libshared_static, libbasic, libbasic_gcrypt, libsystemd_static], - c_args : ['-fvisibility=default'], dependencies : libshared_deps, install : true, install_dir : rootlibexecdir) diff --git a/src/test/meson.build b/src/test/meson.build index 9a1c481f226..364cd3dd3fd 100644 --- a/src/test/meson.build +++ b/src/test/meson.build @@ -419,7 +419,8 @@ tests += [ libmount, libxz, liblz4, - libblkid], + libblkid, + libselinux], [core_includes, journal_includes, udev_includes]], [['src/test/test-prioq.c']], diff --git a/tools/oss-fuzz.sh b/tools/oss-fuzz.sh index 8a19da665eb..244eb83906b 100755 --- a/tools/oss-fuzz.sh +++ b/tools/oss-fuzz.sh @@ -67,7 +67,9 @@ df="$build/dns-fuzzing" git clone --depth 1 https://github.com/CZ-NIC/dns-fuzzing "$df" zip -jqr "$OUT/fuzz-dns-packet_seed_corpus.zip" "$df/packet" -install -Dt "$OUT/src/shared/" "$build"/src/shared/libsystemd-shared-*.so +install -Dt "$OUT/src/shared/" \ + "$build"/src/shared/libsystemd-shared-*.so \ + "$build"/src/core/libsystemd-core-*.so wget -O "$OUT/fuzz-json.dict" https://raw.githubusercontent.com/rc0r/afl-fuzz/master/dictionaries/json.dict From a2b0cd3f5ab3f450e74e2085ad20372a05451c74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 14 Dec 2021 18:03:06 +0100 Subject: [PATCH 2/3] meson: allow specifying a custom "tag" for the private shared libaries We have /usr/lib/systemd/libsystemd-{shared,core}-nnn.so. With this path the 'nnn' part can be changed to something different. The idea is that during a package build this will be set to the package version. This way during in-place upgrades with the same major version both the new and old libraries can cooexit. This should fix the issue when systemd programs are called during package upgrades and fail to exec because the expect different symbols in the library they are linked to. This should fix https://bugzilla.redhat.com/show_bug.cgi?id=1906010. --- meson.build | 6 ++++++ meson_options.txt | 2 ++ src/core/meson.build | 2 +- src/shared/meson.build | 2 +- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index 146c95a478f..ef9a0278c97 100644 --- a/meson.build +++ b/meson.build @@ -599,6 +599,11 @@ endif versiondep = declare_dependency(sources: version_h) +shared_lib_tag = get_option('shared-lib-tag') +if shared_lib_tag == '' + shared_lib_tag = meson.project_version() +endif + sh = find_program('sh') echo = find_program('echo') sed = find_program('sed') @@ -3902,6 +3907,7 @@ summary({ 'D-Bus system directory' : dbussystemservicedir, 'bash completions directory' : bashcompletiondir, 'zsh completions directory' : zshcompletiondir, + 'private shared lib version tag' : shared_lib_tag, 'extra start script' : get_option('rc-local'), 'debug shell' : '@0@ @ @1@'.format(get_option('debug-shell'), get_option('debug-tty')), diff --git a/meson_options.txt b/meson_options.txt index 401f0933d73..23691fb4986 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -3,6 +3,8 @@ option('version-tag', type : 'string', description : 'override the git version string') +option('shared-lib-tag', type : 'string', + description : 'override the private shared library version tag (defaults to project version)') option('mode', type : 'combo', choices : ['developer', 'release'], description : 'autoenable features suitable for systemd development/release builds') diff --git a/src/core/meson.build b/src/core/meson.build index 87456712131..fd15a7fbefd 100644 --- a/src/core/meson.build +++ b/src/core/meson.build @@ -167,7 +167,7 @@ load_fragment_gperf_nulstr_c = custom_target( command : [awk, '-f', '@INPUT0@', '@INPUT1@'], capture : true) -libcore_name = 'systemd-core-@0@'.format(meson.project_version()) +libcore_name = 'systemd-core-@0@'.format(shared_lib_tag) libcore = shared_library( libcore_name, diff --git a/src/shared/meson.build b/src/shared/meson.build index c2e02339746..f58d623f4a1 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -430,7 +430,7 @@ target2 = custom_target( shared_generated_gperf_headers = [target1, target2] shared_sources += shared_generated_gperf_headers -libshared_name = 'systemd-shared-@0@'.format(meson.project_version()) +libshared_name = 'systemd-shared-@0@'.format(shared_lib_tag) libshared_deps = [threads, libacl, From ff254eea8feb55bbea9ec5d731e3dc9299b80b9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 15 Dec 2021 09:14:44 +0100 Subject: [PATCH 3/3] test: ignore the error about our own libraries missing during image creation 19:50:59 F: Missing a shared library required by /var/tmp/systemd-test.NIPT2q/root/lib/systemd/libsystemd-core-250.so. 19:50:59 F: Run "ldd /var/tmp/systemd-test.NIPT2q/root/lib/systemd/libsystemd-core-250.so" to find out what it is. 19:50:59 F: libsystemd-shared-250.so => not found 19:50:59 F: Cannot create a test image. --- test/test-functions | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/test/test-functions b/test/test-functions index 218d0e6888c..95d37d09d59 100644 --- a/test/test-functions +++ b/test/test-functions @@ -1932,11 +1932,9 @@ inst_libs() { while read -r line; do [[ "$line" = 'not a dynamic executable' ]] && break - # Skip a harmless error when running the tests on a system with a significantly - # older systemd version (ldd tries to resolve the unprefixed RPATH for libsystemd.so.0, - # which is in this case older than the already installed libsystemd.so.0 in $initdir). - # The issue is triggered by installing test dependencies in install_missing_libraries(). - [[ "$line" =~ libsystemd.so.*:\ version\ .*\ not\ found ]] && continue + # Ignore errors about our own stuff missing. This is most likely caused + # by ldd attempting to use the unprefixed RPATH. + [[ "$line" =~ libsystemd.*\ not\ found ]] && continue if [[ "$line" =~ $so_regex ]]; then file="${BASH_REMATCH[1]}" @@ -2309,7 +2307,7 @@ inst_binary() { # In certain cases we might attempt to install a binary which is already # present in the test image, yet it's missing from the host system. # In such cases, let's check if the binary indeed exists in the image - # before doing any other chcecks. If it does, immediately return with + # before doing any other checks. If it does, immediately return with # success. if [[ $# -eq 1 ]]; then for path in "" bin sbin usr/bin usr/sbin; do @@ -2328,6 +2326,10 @@ inst_binary() { while read -r line; do [[ "$line" = 'not a dynamic executable' ]] && break + # Ignore errors about our own stuff missing. This is most likely caused + # by ldd attempting to use the unprefixed RPATH. + [[ "$line" =~ libsystemd.*\ not\ found ]] && continue + if [[ "$line" =~ $so_regex ]]; then file="${BASH_REMATCH[1]}" [[ -e "${initdir}/$file" ]] && continue