summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2021-01-19 19:57:13 +0100
committerLennart Poettering <lennart@poettering.net>2021-01-20 17:44:53 +0100
commit9901835d80adc6358a7092d3cb3bbd7689d63caa (patch)
tree85650724add3f415eaa043a4eb7d75ccbacfc3e9 /src
parent1f3707aeea7dccaf12c15efa3fe2ac3843c5a52e (diff)
downloadsystemd-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.c122
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. */