]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sysext: split version validation logic into function of its own
authorLennart Poettering <lennart@poettering.net>
Tue, 19 Jan 2021 18:57:13 +0000 (19:57 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 20 Jan 2021 16:44:53 +0000 (17:44 +0100)
Just some simple refactoring to simplify the logic.

src/sysext/sysext.c

index 17b8dcd2fcc42814f240b9d84b46afe38d0a761b..e54f1845f8227501e894a0181d659c5a577d941d 100644 (file)
@@ -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. */