mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-02-09 09:57:26 +03:00
sysext: split version validation logic into function of its own
Just some simple refactoring to simplify the logic.
This commit is contained in:
parent
1f3707aeea
commit
9901835d80
@ -399,6 +399,71 @@ static int strverscmpp(char *const* a, char *const* b) {
|
||||
return strverscmp(*a, *b);
|
||||
}
|
||||
|
||||
static int validate_version(
|
||||
const char *root,
|
||||
const char *name,
|
||||
const char *host_os_release_id,
|
||||
const char *host_os_release_version_id,
|
||||
const char *host_os_release_sysext_level) {
|
||||
|
||||
_cleanup_free_ char *extension_release_id = NULL, *extension_release_version_id = NULL, *extension_release_sysext_level = NULL;
|
||||
int r;
|
||||
|
||||
assert(root);
|
||||
assert(name);
|
||||
|
||||
/* Insist that extension images do not overwrite the underlying OS release file (it's fine if
|
||||
* they place one in /etc/os-release, i.e. where things don't matter, as they aren't
|
||||
* merged.) */
|
||||
r = chase_symlinks("/usr/lib/os-release", root, CHASE_PREFIX_ROOT, NULL, NULL);
|
||||
if (r < 0) {
|
||||
if (r != -ENOENT)
|
||||
return log_error_errno(r, "Failed to determine whether /usr/lib/os-release exists in the extension image: %m");
|
||||
} else
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Extension image contains /usr/lib/os-release file, which is not allowed (it may carry /etc/os-release), refusing.");
|
||||
|
||||
/* Now that we can look into the extension image, let's see if the OS version is compatible */
|
||||
r = parse_extension_release(
|
||||
root,
|
||||
name,
|
||||
"ID", &extension_release_id,
|
||||
"VERSION_ID", &extension_release_version_id,
|
||||
"SYSEXT_LEVEL", &extension_release_sysext_level,
|
||||
NULL);
|
||||
if (r == -ENOENT) {
|
||||
log_notice_errno(r, "Extension '%s' carries no extension-release data, ignoring extension.", name);
|
||||
return 0;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to acquire 'os-release' data of extension '%s': %m", name);
|
||||
|
||||
if (!streq_ptr(host_os_release_id, extension_release_id)) {
|
||||
log_notice("Extension '%s' is for OS '%s', but running on '%s', ignoring extension.",
|
||||
name, strna(extension_release_id), strna(host_os_release_id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If the extension has a sysext API level declared, then it must match the host API
|
||||
* level. Otherwise, compare OS version as a whole */
|
||||
if (extension_release_sysext_level) {
|
||||
if (!streq_ptr(host_os_release_sysext_level, extension_release_sysext_level)) {
|
||||
log_notice("Extension '%s' is for sysext API level '%s', but running on sysext API level '%s', ignoring extension.",
|
||||
name, extension_release_sysext_level, strna(host_os_release_sysext_level));
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (!streq_ptr(host_os_release_version_id, extension_release_version_id)) {
|
||||
log_notice("Extension '%s' is for OS version '%s', but running on OS version '%s', ignoring extension.",
|
||||
name, extension_release_version_id, strna(host_os_release_version_id));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
log_debug("Version info of extension '%s' matches host.", name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int merge_subprocess(Hashmap *images, const char *workspace) {
|
||||
_cleanup_free_ char *host_os_release_id = NULL, *host_os_release_version_id = NULL, *host_os_release_sysext_level = NULL,
|
||||
*buf = NULL;
|
||||
@ -440,8 +505,7 @@ static int merge_subprocess(Hashmap *images, const char *workspace) {
|
||||
|
||||
/* Let's now mount all images */
|
||||
HASHMAP_FOREACH(img, images) {
|
||||
_cleanup_free_ char *p = NULL,
|
||||
*extension_release_id = NULL, *extension_release_version_id = NULL, *extension_release_sysext_level = NULL;
|
||||
_cleanup_free_ char *p = NULL;
|
||||
|
||||
p = path_join(workspace, "extensions", img->name);
|
||||
if (!p)
|
||||
@ -523,57 +587,17 @@ static int merge_subprocess(Hashmap *images, const char *workspace) {
|
||||
assert_not_reached("Unsupported image type");
|
||||
}
|
||||
|
||||
/* Insist that extension images do not overwrite the underlying OS release file (it's fine if
|
||||
* they place one in /etc/os-release, i.e. where things don't matter, as they aren't
|
||||
* merged.) */
|
||||
r = chase_symlinks("/usr/lib/os-release", p, CHASE_PREFIX_ROOT, NULL, NULL);
|
||||
if (r < 0) {
|
||||
if (r != -ENOENT)
|
||||
return log_error_errno(r, "Failed to determine whether /usr/lib/os-release exists in the extension image: %m");
|
||||
} else
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Extension image contains /usr/lib/os-release file, which is not allowed (it may carry /etc/os-release), refusing.");
|
||||
|
||||
/* Now that we can look into the extension image, let's see if the OS version is compatible */
|
||||
r = parse_extension_release(
|
||||
r = validate_version(
|
||||
p,
|
||||
img->name,
|
||||
"ID", &extension_release_id,
|
||||
"VERSION_ID", &extension_release_version_id,
|
||||
"SYSEXT_LEVEL", &extension_release_sysext_level,
|
||||
NULL);
|
||||
if (r == -ENOENT) {
|
||||
log_notice_errno(r, "Extension '%s' carries no extension-release data, ignoring extension.", img->name);
|
||||
host_os_release_id,
|
||||
host_os_release_version_id,
|
||||
host_os_release_sysext_level);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) {
|
||||
n_ignored++;
|
||||
continue;
|
||||
} else if (r < 0)
|
||||
return log_error_errno(r, "Failed to acquire 'os-release' data of extension '%s': %m", img->name);
|
||||
else {
|
||||
if (!streq_ptr(host_os_release_id, extension_release_id)) {
|
||||
log_notice("Extension '%s' is for OS '%s', but running on '%s', ignoring extension.",
|
||||
img->name, strna(extension_release_id), strna(host_os_release_id));
|
||||
n_ignored++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If the extension has a sysext API level declared, then it must match the host API level. Otherwise, compare OS version as a whole */
|
||||
if (extension_release_sysext_level) {
|
||||
if (!streq_ptr(host_os_release_sysext_level, extension_release_sysext_level)) {
|
||||
log_notice("Extension '%s' is for sysext API level '%s', but running on sysext API level '%s', ignoring extension.",
|
||||
img->name, extension_release_sysext_level, strna(host_os_release_sysext_level));
|
||||
n_ignored++;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (!streq_ptr(host_os_release_version_id, extension_release_version_id)) {
|
||||
log_notice("Extension '%s' is for OS version '%s', but running on OS version '%s', ignoring extension.",
|
||||
img->name, extension_release_version_id, strna(host_os_release_version_id));
|
||||
n_ignored++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
log_debug("Version info of extension '%s' matches host.", img->name);
|
||||
}
|
||||
|
||||
/* Noice! This one is an extension we want. */
|
||||
|
Loading…
x
Reference in New Issue
Block a user