nspawn: fix comparisons of versions with non-numerical suffixes

See a2b0cd3f5a. When -Dshared-lib-tag is used,
libsystemd-shared.so and libsystemd-core.so get a suffix which breaks the
parsing done by systemd_installation_has_version(). We can assume that the
tag will be something like "251-rc1-1.fc37" that is currently used in Fedora.
(Anything that does *not* start with the version would be completely crazy.)
By switching to strverscmp_improved() we simplify the code and fix comparisons
with such versions.

$ build/test-nspawn-util /var/lib/machines/rawhide
...
Found libsystemd shared at "/var/lib/machines/rawhide/lib/systemd/libsystemd-shared-251-rc1-1.fc37.so.so", version 251-rc1-1.fc37 (OK).
/var/lib/machines/rawhide has systemd >= 251: yes
...

I noticed this when I started a systemd-nspawn container with Redora rawhide
and got the message "Not running with unified cgroup hierarchy, LSM BPF is not
supported". I thought the message is in error, but it was actually correct:
nspawn was misdetecting that the container does not sport new-enough systemd
to support cgroups-v2.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2022-04-07 18:19:03 +02:00
parent c9394f4f93
commit 7e6821ed4e
4 changed files with 15 additions and 22 deletions
+7 -14
View File
@@ -9,7 +9,7 @@
#include "path-util.h"
#include "string-util.h"
int systemd_installation_has_version(const char *root, unsigned minimal_version) {
int systemd_installation_has_version(const char *root, const char *minimal_version) {
const char *pattern;
int r;
@@ -48,7 +48,6 @@ int systemd_installation_has_version(const char *root, unsigned minimal_version)
STRV_FOREACH(name, names) {
/* This is most likely to run only once, hence let's not optimize anything. */
char *t, *t2;
unsigned version;
t = startswith(*name, path);
if (!t)
@@ -57,19 +56,13 @@ int systemd_installation_has_version(const char *root, unsigned minimal_version)
t2 = endswith(t, ".so");
if (!t2)
continue;
*t2 = '\0';
t2[0] = '\0'; /* truncate the suffix */
r = safe_atou(t, &version);
if (r < 0) {
log_debug_errno(r, "Found libsystemd shared at \"%s.so\", but failed to parse version: %m", *name);
continue;
}
log_debug("Found libsystemd shared at \"%s.so\", version %u (%s).",
*name, version,
version >= minimal_version ? "OK" : "too old");
if (version >= minimal_version)
r = strverscmp_improved(t, minimal_version);
log_debug("Found libsystemd shared at \"%s.so\", version %s (%s).",
*name, t,
r >= 0 ? "OK" : "too old");
if (r >= 0)
return true;
}
}