From: Luca Boccassi Date: Mon, 11 Jan 2021 23:00:58 +0000 (+0000) Subject: sysext: use parse_extension_release and reject extension if not found X-Git-Tag: v248-rc1~298^2~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=60bb6caaae48c646219645c207b2692a6e12a871;p=thirdparty%2Fsystemd.git sysext: use parse_extension_release and reject extension if not found --- diff --git a/man/systemd-sysext.xml b/man/systemd-sysext.xml index 14aab94dc93..6bda5f4fc65 100644 --- a/man/systemd-sysext.xml +++ b/man/systemd-sysext.xml @@ -55,10 +55,9 @@ Files and directories contained in the extension images outside of the /usr/ and /opt/ hierarchies are not merged, and hence have no effect - when included in a system extension image (with the exception of /etc/os-release, - see below). In particular, files in the /etc/ and /var/ - included in a system extension image will not appear in the respective hierarchies - after activation. + when included in a system extension image. In particular, files in the /etc/ and + /var/ included in a system extension image will not appear in + the respective hierarchies after activation. System extension images are strictly read-only, and the host /usr/ and /opt/ hierarchies become read-only too while they are activated. @@ -111,13 +110,17 @@ Note that there is no concept of enabling/disabling installed system extension images: all installed extension images are automatically activated at boot. - A simple mechanism for version compatibility is enforced: a system extension image may carry an - /etc/os-release file that is compared with the host os-release + A simple mechanism for version compatibility is enforced: a system extension image must carry a + /usr/lib/extension-release.d/extension-release.$name + file, which must match its image name, that is compared with the host os-release file: the contained ID= fields have to match, as well as the - SYSEXT_LEVEL= field (if defined). If the latter is not defined the + SYSEXT_LEVEL= field (if defined). If the latter is not defined, the VERSION_ID= field has to match instead. System extensions should not ship a /usr/lib/os-release file (as that would be merged into the host - /usr/ tree, overriding the host OS version data, which is not desirable). + /usr/ tree, overriding the host OS version data, which is not desirable). The + extension-release file follows the same format and semantics, and carries the same + content, as the os-release file of the OS, but it describes the resources carried + in the extension image. diff --git a/src/sysext/sysext.c b/src/sysext/sysext.c index c12f40c160d..8a8cd7535ed 100644 --- a/src/sysext/sysext.c +++ b/src/sysext/sysext.c @@ -441,7 +441,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_os_release_id = NULL, *extension_os_release_version_id = NULL, *extension_os_release_sysext_level = NULL; + *extension_release_id = NULL, *extension_release_version_id = NULL, *extension_release_sysext_level = NULL; p = path_join(workspace, "extensions", img->name); if (!p) @@ -535,36 +535,39 @@ static int merge_subprocess(Hashmap *images, const char *workspace) { "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_os_release( + r = parse_extension_release( p, - "ID", &extension_os_release_id, - "VERSION_ID", &extension_os_release_version_id, - "SYSEXT_LEVEL", &extension_os_release_sysext_level, + 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 os-release data, not checking for version compatibility.", img->name); - else if (r < 0) + if (r == -ENOENT) { + log_notice_errno(r, "Extension '%s' carries no extension-release data, ignoring extension.", img->name); + 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_os_release_id)) { + 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_os_release_id), strna(host_os_release_id)); + 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_os_release_sysext_level) { - if (!streq_ptr(host_os_release_sysext_level, extension_os_release_sysext_level)) { + 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_os_release_sysext_level, strna(host_os_release_sysext_level)); + 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_os_release_version_id)) { + 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_os_release_version_id, strna(host_os_release_version_id)); + img->name, extension_release_version_id, strna(host_os_release_version_id)); n_ignored++; continue; }