Skip to content

Commit 9901835

Browse files
committed
sysext: split version validation logic into function of its own
Just some simple refactoring to simplify the logic.
1 parent 1f3707a commit 9901835

File tree

1 file changed

+73
-49
lines changed

1 file changed

+73
-49
lines changed

src/sysext/sysext.c

Lines changed: 73 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,71 @@ static int strverscmpp(char *const* a, char *const* b) {
399399
return strverscmp(*a, *b);
400400
}
401401

402+
static int validate_version(
403+
const char *root,
404+
const char *name,
405+
const char *host_os_release_id,
406+
const char *host_os_release_version_id,
407+
const char *host_os_release_sysext_level) {
408+
409+
_cleanup_free_ char *extension_release_id = NULL, *extension_release_version_id = NULL, *extension_release_sysext_level = NULL;
410+
int r;
411+
412+
assert(root);
413+
assert(name);
414+
415+
/* Insist that extension images do not overwrite the underlying OS release file (it's fine if
416+
* they place one in /etc/os-release, i.e. where things don't matter, as they aren't
417+
* merged.) */
418+
r = chase_symlinks("/usr/lib/os-release", root, CHASE_PREFIX_ROOT, NULL, NULL);
419+
if (r < 0) {
420+
if (r != -ENOENT)
421+
return log_error_errno(r, "Failed to determine whether /usr/lib/os-release exists in the extension image: %m");
422+
} else
423+
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
424+
"Extension image contains /usr/lib/os-release file, which is not allowed (it may carry /etc/os-release), refusing.");
425+
426+
/* Now that we can look into the extension image, let's see if the OS version is compatible */
427+
r = parse_extension_release(
428+
root,
429+
name,
430+
"ID", &extension_release_id,
431+
"VERSION_ID", &extension_release_version_id,
432+
"SYSEXT_LEVEL", &extension_release_sysext_level,
433+
NULL);
434+
if (r == -ENOENT) {
435+
log_notice_errno(r, "Extension '%s' carries no extension-release data, ignoring extension.", name);
436+
return 0;
437+
}
438+
if (r < 0)
439+
return log_error_errno(r, "Failed to acquire 'os-release' data of extension '%s': %m", name);
440+
441+
if (!streq_ptr(host_os_release_id, extension_release_id)) {
442+
log_notice("Extension '%s' is for OS '%s', but running on '%s', ignoring extension.",
443+
name, strna(extension_release_id), strna(host_os_release_id));
444+
return 0;
445+
}
446+
447+
/* If the extension has a sysext API level declared, then it must match the host API
448+
* level. Otherwise, compare OS version as a whole */
449+
if (extension_release_sysext_level) {
450+
if (!streq_ptr(host_os_release_sysext_level, extension_release_sysext_level)) {
451+
log_notice("Extension '%s' is for sysext API level '%s', but running on sysext API level '%s', ignoring extension.",
452+
name, extension_release_sysext_level, strna(host_os_release_sysext_level));
453+
return 0;
454+
}
455+
} else {
456+
if (!streq_ptr(host_os_release_version_id, extension_release_version_id)) {
457+
log_notice("Extension '%s' is for OS version '%s', but running on OS version '%s', ignoring extension.",
458+
name, extension_release_version_id, strna(host_os_release_version_id));
459+
return 0;
460+
}
461+
}
462+
463+
log_debug("Version info of extension '%s' matches host.", name);
464+
return 1;
465+
}
466+
402467
static int merge_subprocess(Hashmap *images, const char *workspace) {
403468
_cleanup_free_ char *host_os_release_id = NULL, *host_os_release_version_id = NULL, *host_os_release_sysext_level = NULL,
404469
*buf = NULL;
@@ -440,8 +505,7 @@ static int merge_subprocess(Hashmap *images, const char *workspace) {
440505

441506
/* Let's now mount all images */
442507
HASHMAP_FOREACH(img, images) {
443-
_cleanup_free_ char *p = NULL,
444-
*extension_release_id = NULL, *extension_release_version_id = NULL, *extension_release_sysext_level = NULL;
508+
_cleanup_free_ char *p = NULL;
445509

446510
p = path_join(workspace, "extensions", img->name);
447511
if (!p)
@@ -523,57 +587,17 @@ static int merge_subprocess(Hashmap *images, const char *workspace) {
523587
assert_not_reached("Unsupported image type");
524588
}
525589

526-
/* Insist that extension images do not overwrite the underlying OS release file (it's fine if
527-
* they place one in /etc/os-release, i.e. where things don't matter, as they aren't
528-
* merged.) */
529-
r = chase_symlinks("/usr/lib/os-release", p, CHASE_PREFIX_ROOT, NULL, NULL);
530-
if (r < 0) {
531-
if (r != -ENOENT)
532-
return log_error_errno(r, "Failed to determine whether /usr/lib/os-release exists in the extension image: %m");
533-
} else
534-
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
535-
"Extension image contains /usr/lib/os-release file, which is not allowed (it may carry /etc/os-release), refusing.");
536-
537-
/* Now that we can look into the extension image, let's see if the OS version is compatible */
538-
r = parse_extension_release(
590+
r = validate_version(
539591
p,
540592
img->name,
541-
"ID", &extension_release_id,
542-
"VERSION_ID", &extension_release_version_id,
543-
"SYSEXT_LEVEL", &extension_release_sysext_level,
544-
NULL);
545-
if (r == -ENOENT) {
546-
log_notice_errno(r, "Extension '%s' carries no extension-release data, ignoring extension.", img->name);
593+
host_os_release_id,
594+
host_os_release_version_id,
595+
host_os_release_sysext_level);
596+
if (r < 0)
597+
return r;
598+
if (r == 0) {
547599
n_ignored++;
548600
continue;
549-
} else if (r < 0)
550-
return log_error_errno(r, "Failed to acquire 'os-release' data of extension '%s': %m", img->name);
551-
else {
552-
if (!streq_ptr(host_os_release_id, extension_release_id)) {
553-
log_notice("Extension '%s' is for OS '%s', but running on '%s', ignoring extension.",
554-
img->name, strna(extension_release_id), strna(host_os_release_id));
555-
n_ignored++;
556-
continue;
557-
}
558-
559-
/* If the extension has a sysext API level declared, then it must match the host API level. Otherwise, compare OS version as a whole */
560-
if (extension_release_sysext_level) {
561-
if (!streq_ptr(host_os_release_sysext_level, extension_release_sysext_level)) {
562-
log_notice("Extension '%s' is for sysext API level '%s', but running on sysext API level '%s', ignoring extension.",
563-
img->name, extension_release_sysext_level, strna(host_os_release_sysext_level));
564-
n_ignored++;
565-
continue;
566-
}
567-
} else {
568-
if (!streq_ptr(host_os_release_version_id, extension_release_version_id)) {
569-
log_notice("Extension '%s' is for OS version '%s', but running on OS version '%s', ignoring extension.",
570-
img->name, extension_release_version_id, strna(host_os_release_version_id));
571-
n_ignored++;
572-
continue;
573-
}
574-
}
575-
576-
log_debug("Version info of extension '%s' matches host.", img->name);
577601
}
578602

579603
/* Noice! This one is an extension we want. */

0 commit comments

Comments
 (0)