diff options
author | Lennart Poettering <lennart@poettering.net> | 2021-01-19 19:57:13 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2021-01-20 17:44:53 +0100 |
commit | 9901835d80adc6358a7092d3cb3bbd7689d63caa (patch) | |
tree | 85650724add3f415eaa043a4eb7d75ccbacfc3e9 /src | |
parent | 1f3707aeea7dccaf12c15efa3fe2ac3843c5a52e (diff) | |
download | systemd-9901835d80adc6358a7092d3cb3bbd7689d63caa.tar.gz |
sysext: split version validation logic into function of its own
Just some simple refactoring to simplify the logic.
Diffstat (limited to 'src')
-rw-r--r-- | src/sysext/sysext.c | 122 |
1 files changed, 73 insertions, 49 deletions
diff --git a/src/sysext/sysext.c b/src/sysext/sysext.c index 17b8dcd2fc..e54f1845f8 100644 --- a/src/sysext/sysext.c +++ b/src/sysext/sysext.c @@ -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. */ |