diff --git a/src/shared/os-util.c b/src/shared/os-util.c index 3b7e4958464c0..7ada368679f1e 100644 --- a/src/shared/os-util.c +++ b/src/shared/os-util.c @@ -31,13 +31,17 @@ int path_is_os_tree(const char *path) { return 1; } -int open_os_release(const char *root, char **ret_path, int *ret_fd) { +int open_extension_release(const char *root, const char *extension, char **ret_path, int *ret_fd) { _cleanup_free_ char *q = NULL; - const char *p; + char **paths, **p; int r, fd; - FOREACH_STRING(p, "/etc/os-release", "/usr/lib/os-release") { - r = chase_symlinks(p, root, CHASE_PREFIX_ROOT, + if (extension) + paths = STRV_MAKE(strjoina("/usr/lib/extension-release.d/extension-release.", extension)); + else + paths = STRV_MAKE("/etc/os-release", "/usr/lib/os-release"); + STRV_FOREACH(p, paths) { + r = chase_symlinks(*p, root, CHASE_PREFIX_ROOT, ret_path ? &q : NULL, ret_fd ? &fd : NULL); if (r != -ENOENT) @@ -64,16 +68,16 @@ int open_os_release(const char *root, char **ret_path, int *ret_fd) { return 0; } -int fopen_os_release(const char *root, char **ret_path, FILE **ret_file) { +int fopen_extension_release(const char *root, const char *extension, char **ret_path, FILE **ret_file) { _cleanup_free_ char *p = NULL; _cleanup_close_ int fd = -1; FILE *f; int r; if (!ret_file) - return open_os_release(root, ret_path, NULL); + return open_extension_release(root, extension, ret_path, NULL); - r = open_os_release(root, ret_path ? &p : NULL, &fd); + r = open_extension_release(root, extension, ret_path ? &p : NULL, &fd); if (r < 0) return r; @@ -89,18 +93,35 @@ int fopen_os_release(const char *root, char **ret_path, FILE **ret_file) { return 0; } -int parse_os_release(const char *root, ...) { +static int parse_release_internal(const char *root, const char *extension, va_list ap) { _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *p = NULL; - va_list ap; int r; - r = fopen_os_release(root, &p, &f); + r = fopen_extension_release(root, extension, &p, &f); if (r < 0) return r; + return parse_env_filev(f, p, ap); +} + +int parse_extension_release(const char *root, const char *extension, ...) { + va_list ap; + int r; + + va_start(ap, extension); + r = parse_release_internal(root, extension, ap); + va_end(ap); + + return r; +} + +int parse_os_release(const char *root, ...) { + va_list ap; + int r; + va_start(ap, root); - r = parse_env_filev(f, p, ap); + r = parse_release_internal(root, NULL, ap); va_end(ap); return r; diff --git a/src/shared/os-util.h b/src/shared/os-util.h index 1d9b0b146b3a2..5b724eb7ac1e0 100644 --- a/src/shared/os-util.h +++ b/src/shared/os-util.h @@ -5,9 +5,19 @@ int path_is_os_tree(const char *path); -int open_os_release(const char *root, char **ret_path, int *ret_fd); -int fopen_os_release(const char *root, char **ret_path, FILE **ret_file); +/* The *_extension_release flavours will look for /usr/lib/extension-release/extension-release.NAME + * in accordance with the OS extension specification, rather than for /usr/lib/ or /etc/os-release. */ +int open_extension_release(const char *root, const char *extension, char **ret_path, int *ret_fd); +static inline int open_os_release(const char *root, char **ret_path, int *ret_fd) { + return open_extension_release(root, NULL, ret_path, ret_fd); +} +int fopen_extension_release(const char *root, const char *extension, char **ret_path, FILE **ret_file); +static inline int fopen_os_release(const char *root, char **ret_path, FILE **ret_file) { + return fopen_extension_release(root, NULL, ret_path, ret_file); +} + +int parse_extension_release(const char *root, const char *extension, ...) _sentinel_; int parse_os_release(const char *root, ...) _sentinel_; int load_os_release_pairs(const char *root, char ***ret); int load_os_release_pairs_with_prefix(const char *root, const char *prefix, char ***ret); diff --git a/src/sysext/sysext.c b/src/sysext/sysext.c index 8862e3aac9149..9e7bcebdfa11c 100644 --- a/src/sysext/sysext.c +++ b/src/sysext/sysext.c @@ -455,8 +455,16 @@ static int merge_subprocess(Hashmap *images, const char *workspace) { _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL; _cleanup_(loop_device_unrefp) LoopDevice *d = NULL; _cleanup_(decrypted_image_unrefp) DecryptedImage *di = NULL; + _cleanup_(verity_settings_done) VeritySettings verity_settings = VERITY_SETTINGS_DEFAULT; DissectImageFlags flags = DISSECT_IMAGE_READ_ONLY|DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_MOUNT_ROOT_ONLY; + r = verity_settings_load(&verity_settings, img->path, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to read verity artifacts for %s: %m", img->path); + + if (verity_settings.data_path) + flags |= DISSECT_IMAGE_NO_PARTITION_TABLE; + r = loop_device_make_by_path(img->path, O_RDONLY, 0, &d); if (r < 0) return log_error_errno(r, "Failed to set up loopback device: %m"); @@ -464,7 +472,7 @@ static int merge_subprocess(Hashmap *images, const char *workspace) { r = dissect_image_and_warn( d->fd, img->path, - NULL, + &verity_settings, NULL, flags, &m); @@ -473,7 +481,7 @@ static int merge_subprocess(Hashmap *images, const char *workspace) { r = dissected_image_decrypt_interactively( m, NULL, - NULL, + &verity_settings, flags, &di); if (r < 0) @@ -501,14 +509,15 @@ static int merge_subprocess(Hashmap *images, const char *workspace) { } /* Now that we can look into the extension image, let's see of the OS version is compatible */ - r = parse_os_release( + r = parse_extension_release( p, + img->name, "ID", &extension_os_release_id, "VERSION_ID", &extension_os_release_version_id, "SYSEXT_LEVEL", &extension_os_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); + return log_notice_errno(r, "Extension '%s' carries no extension-release data, ignoring extension.", img->name); else if (r < 0) return log_error_errno(r, "Failed to acquire 'os-release' data of extension '%s': %m", img->name); else {