diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/basic/os-util.h | 2 | ||||
-rw-r--r-- | src/dissect/dissect.c | 86 | ||||
-rw-r--r-- | src/shared/discover-image.c | 23 | ||||
-rw-r--r-- | src/shared/discover-image.h | 14 | ||||
-rw-r--r-- | src/shared/dissect-image.c | 105 | ||||
-rw-r--r-- | src/shared/dissect-image.h | 4 | ||||
-rw-r--r-- | src/sysext/sysext.c | 2 |
7 files changed, 143 insertions, 93 deletions
diff --git a/src/basic/os-util.h b/src/basic/os-util.h index 11afc4c6ca..7cee3dd119 100644 --- a/src/basic/os-util.h +++ b/src/basic/os-util.h @@ -10,7 +10,9 @@ typedef enum ImageClass { IMAGE_MACHINE, IMAGE_PORTABLE, IMAGE_SYSEXT, + _IMAGE_CLASS_EXTENSION_FIRST = IMAGE_SYSEXT, /* First "extension" image type, so that we can easily generically iterate through them */ IMAGE_CONFEXT, + _IMAGE_CLASS_EXTENSION_LAST = IMAGE_CONFEXT, /* Last "extension image type */ _IMAGE_CLASS_MAX, _IMAGE_CLASS_INVALID = -EINVAL, } ImageClass; diff --git a/src/dissect/dissect.c b/src/dissect/dissect.c index 28cced4173..a03f9a64db 100644 --- a/src/dissect/dissect.c +++ b/src/dissect/dissect.c @@ -765,24 +765,40 @@ static void strv_pair_print(char **l, const char *prefix) { printf("%*s %s=%s\n", (int) strlen(prefix), "", *p, *q); } -static int get_extension_scopes(DissectedImage *m, char ***ret_scopes) { +static int get_extension_scopes(DissectedImage *m, ImageClass class, char ***ret_scopes) { _cleanup_strv_free_ char **l = NULL; - const char *e; + const char *e, *field_name; + char **release_data; assert(m); assert(ret_scopes); + switch (class) { + + case IMAGE_SYSEXT: + release_data = m->sysext_release; + field_name = "SYSEXT_SCOPE"; + break; + + case IMAGE_CONFEXT: + release_data = m->confext_release; + field_name = "CONFEXT_SCOPE"; + break; + + default: + return -EINVAL; + } + /* If there's no extension-release file its not a system extension. Otherwise the SYSEXT_SCOPE * field for sysext images and the CONFEXT_SCOPE field for confext images indicates which scope * it is for — and it defaults to "system" + "portable" if unset. */ - if (!m->extension_release) { + + if (!release_data) { *ret_scopes = NULL; return 0; } - e = strv_env_pairs_get(m->extension_release, "SYSEXT_SCOPE"); - if (!e) - e = strv_env_pairs_get(m->extension_release, "CONFEXT_SCOPE"); + e = strv_env_pairs_get(release_data, field_name); if (e) l = strv_split(e, WHITESPACE); else @@ -843,7 +859,6 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) { else if (r < 0) return log_error_errno(r, "Failed to acquire image metadata: %m"); else if (arg_json_format_flags & JSON_FORMAT_OFF) { - _cleanup_strv_free_ char **extension_scopes = NULL; if (!sd_id128_is_null(m->image_uuid)) printf("Image UUID: %s\n", SD_ID128_TO_UUID_STRING(m->image_uuid)); @@ -860,15 +875,18 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) { "OS Release:"); strv_pair_print(m->initrd_release, "initrd R.:"); - strv_pair_print(m->extension_release, - " Ext. Rel.:"); + strv_pair_print(m->sysext_release, + " sysext R.:"); + strv_pair_print(m->confext_release, + "confext R.:"); if (m->hostname || !sd_id128_is_null(m->machine_id) || !strv_isempty(m->machine_info) || !strv_isempty(m->os_release) || !strv_isempty(m->initrd_release) || - !strv_isempty(m->extension_release)) + !strv_isempty(m->sysext_release) || + !strv_isempty(m->confext_release)) putc('\n', stdout); printf(" Use As: %s bootable system for UEFI\n", COLOR_MARK_BOOL(m->partitions[PARTITION_ESP].found)); @@ -881,26 +899,33 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) { printf(" %s initrd\n", COLOR_MARK_BOOL(!strv_isempty(m->initrd_release))); - r = get_extension_scopes(m, &extension_scopes); - if (r < 0) - return log_error_errno(r, "Failed to parse scope: %m"); + for (ImageClass c = _IMAGE_CLASS_EXTENSION_FIRST; c <= _IMAGE_CLASS_EXTENSION_LAST; c++) { + const char *string_class = image_class_to_string(c); + _cleanup_strv_free_ char **extension_scopes = NULL; - const char *string_class = image_class_to_string(m->image_class); - printf(" %s %s extension for system\n", - COLOR_MARK_BOOL(strv_contains(extension_scopes, "system")), string_class); - printf(" %s %s extension for initrd\n", - COLOR_MARK_BOOL(strv_contains(extension_scopes, "initrd")), string_class); - printf(" %s %s extension for portable service\n", - COLOR_MARK_BOOL(strv_contains(extension_scopes, "portable")), string_class); + r = get_extension_scopes(m, c, &extension_scopes); + if (r < 0) + return log_error_errno(r, "Failed to parse scopes: %m"); + + printf(" %s %s for system\n", + COLOR_MARK_BOOL(strv_contains(extension_scopes, "system")), string_class); + printf(" %s %s for portable service\n", + COLOR_MARK_BOOL(strv_contains(extension_scopes, "portable")), string_class); + printf(" %s %s for initrd\n", + COLOR_MARK_BOOL(strv_contains(extension_scopes, "initrd")), string_class); + } putc('\n', stdout); } else { - _cleanup_(json_variant_unrefp) JsonVariant *mi = NULL, *osr = NULL, *irdr = NULL, *exr = NULL; - _cleanup_strv_free_ char **extension_scopes = NULL; + _cleanup_strv_free_ char **sysext_scopes = NULL, **confext_scopes = NULL; + + r = get_extension_scopes(m, IMAGE_SYSEXT, &sysext_scopes); + if (r < 0) + return log_error_errno(r, "Failed to parse sysext scopes: %m"); - r = get_extension_scopes(m, &extension_scopes); + r = get_extension_scopes(m, IMAGE_CONFEXT, &confext_scopes); if (r < 0) - return log_error_errno(r, "Failed to parse scope: %m"); + return log_error_errno(r, "Failed to parse confext scopes: %m"); Architecture a = dissected_image_architecture(m); @@ -915,15 +940,18 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) { JSON_BUILD_PAIR_CONDITION(!strv_isempty(m->machine_info), "machineInfo", JSON_BUILD_STRV_ENV_PAIR(m->machine_info)), JSON_BUILD_PAIR_CONDITION(!strv_isempty(m->os_release), "osRelease", JSON_BUILD_STRV_ENV_PAIR(m->os_release)), JSON_BUILD_PAIR_CONDITION(!strv_isempty(m->initrd_release), "initrdRelease", JSON_BUILD_STRV_ENV_PAIR(m->initrd_release)), - JSON_BUILD_PAIR_CONDITION(!strv_isempty(m->extension_release), "extensionRelease", JSON_BUILD_STRV_ENV_PAIR(m->extension_release)), + JSON_BUILD_PAIR_CONDITION(!strv_isempty(m->sysext_release), "sysextRelease", JSON_BUILD_STRV_ENV_PAIR(m->sysext_release)), + JSON_BUILD_PAIR_CONDITION(!strv_isempty(m->confext_release), "confextRelease", JSON_BUILD_STRV_ENV_PAIR(m->confext_release)), JSON_BUILD_PAIR("useBootableUefi", JSON_BUILD_BOOLEAN(m->partitions[PARTITION_ESP].found)), JSON_BUILD_PAIR_CONDITION(m->has_init_system >= 0, "useBootableContainer", JSON_BUILD_BOOLEAN(m->has_init_system)), JSON_BUILD_PAIR("useInitrd", JSON_BUILD_BOOLEAN(!strv_isempty(m->initrd_release))), JSON_BUILD_PAIR("usePortableService", JSON_BUILD_BOOLEAN(strv_env_pairs_get(m->os_release, "PORTABLE_MATCHES"))), - JSON_BUILD_PAIR("ExtensionType", JSON_BUILD_STRING(image_class_to_string(m->image_class))), - JSON_BUILD_PAIR("useSystemExtension", JSON_BUILD_BOOLEAN(strv_contains(extension_scopes, "system"))), - JSON_BUILD_PAIR("useInitRDExtension", JSON_BUILD_BOOLEAN(strv_contains(extension_scopes, "initrd"))), - JSON_BUILD_PAIR("usePortableExtension", JSON_BUILD_BOOLEAN(strv_contains(extension_scopes, "portable"))))); + JSON_BUILD_PAIR("useSystemExtension", JSON_BUILD_BOOLEAN(strv_contains(sysext_scopes, "system"))), + JSON_BUILD_PAIR("useInitRDSystemExtension", JSON_BUILD_BOOLEAN(strv_contains(sysext_scopes, "initrd"))), + JSON_BUILD_PAIR("usePortableSystemExtension", JSON_BUILD_BOOLEAN(strv_contains(sysext_scopes, "portable"))), + JSON_BUILD_PAIR("useConfigurationExtension", JSON_BUILD_BOOLEAN(strv_contains(confext_scopes, "system"))), + JSON_BUILD_PAIR("useInitRDConfigurationExtension", JSON_BUILD_BOOLEAN(strv_contains(confext_scopes, "initrd"))), + JSON_BUILD_PAIR("usePortableConfigurationExtension", JSON_BUILD_BOOLEAN(strv_contains(confext_scopes, "portable"))))); if (r < 0) return log_oom(); } diff --git a/src/shared/discover-image.c b/src/shared/discover-image.c index e407820e18..094337616d 100644 --- a/src/shared/discover-image.c +++ b/src/shared/discover-image.c @@ -101,7 +101,8 @@ static Image *image_free(Image *i) { free(i->hostname); strv_free(i->machine_info); strv_free(i->os_release); - strv_free(i->extension_release); + strv_free(i->sysext_release); + strv_free(i->confext_release); return mfree(i); } @@ -1180,10 +1181,9 @@ int image_read_metadata(Image *i, const ImagePolicy *image_policy) { case IMAGE_SUBVOLUME: case IMAGE_DIRECTORY: { - _cleanup_strv_free_ char **machine_info = NULL, **os_release = NULL, **extension_release = NULL; + _cleanup_strv_free_ char **machine_info = NULL, **os_release = NULL, **sysext_release = NULL, **confext_release = NULL; + _cleanup_free_ char *hostname = NULL, *path = NULL; sd_id128_t machine_id = SD_ID128_NULL; - _cleanup_free_ char *hostname = NULL; - _cleanup_free_ char *path = NULL; if (i->class == IMAGE_SYSEXT) { r = extension_has_forbidden_content(i->path); @@ -1223,16 +1223,20 @@ int image_read_metadata(Image *i, const ImagePolicy *image_policy) { if (r < 0) log_debug_errno(r, "Failed to read os-release in image, ignoring: %m"); - r = load_extension_release_pairs(i->path, i->class, i->name, /* relax_extension_release_check= */ false, &extension_release); + r = load_extension_release_pairs(i->path, IMAGE_SYSEXT, i->name, /* relax_extension_release_check= */ false, &sysext_release); if (r < 0) - log_debug_errno(r, "Failed to read extension-release in image, ignoring: %m"); + log_debug_errno(r, "Failed to read sysext-release in image, ignoring: %m"); + + r = load_extension_release_pairs(i->path, IMAGE_CONFEXT, i->name, /* relax_extension_release_check= */ false, &confext_release); + if (r < 0) + log_debug_errno(r, "Failed to read confext-release in image, ignoring: %m"); free_and_replace(i->hostname, hostname); i->machine_id = machine_id; strv_free_and_replace(i->machine_info, machine_info); strv_free_and_replace(i->os_release, os_release); - strv_free_and_replace(i->extension_release, extension_release); - + strv_free_and_replace(i->sysext_release, sysext_release); + strv_free_and_replace(i->confext_release, confext_release); break; } @@ -1271,7 +1275,8 @@ int image_read_metadata(Image *i, const ImagePolicy *image_policy) { i->machine_id = m->machine_id; strv_free_and_replace(i->machine_info, m->machine_info); strv_free_and_replace(i->os_release, m->os_release); - strv_free_and_replace(i->extension_release, m->extension_release); + strv_free_and_replace(i->sysext_release, m->sysext_release); + strv_free_and_replace(i->confext_release, m->confext_release); break; } diff --git a/src/shared/discover-image.h b/src/shared/discover-image.h index edfb1412a4..bb046fae1e 100644 --- a/src/shared/discover-image.h +++ b/src/shared/discover-image.h @@ -45,7 +45,8 @@ typedef struct Image { sd_id128_t machine_id; char **machine_info; char **os_release; - char **extension_release; + char **sysext_release; + char **confext_release; bool metadata_valid:1; bool discoverable:1; /* true if we know for sure that image_find() would find the image given just the short name */ @@ -80,6 +81,17 @@ int image_read_metadata(Image *i, const ImagePolicy *image_policy); bool image_in_search_path(ImageClass class, const char *root, const char *image); +static inline char **image_extension_release(Image *image, ImageClass class) { + assert(image); + + if (class == IMAGE_SYSEXT) + return image->sysext_release; + if (class == IMAGE_CONFEXT) + return image->confext_release; + + return NULL; +} + static inline bool IMAGE_IS_HIDDEN(const struct Image *i) { assert(i); diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 278d2291a2..e63545312a 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -1665,7 +1665,8 @@ DissectedImage* dissected_image_unref(DissectedImage *m) { strv_free(m->machine_info); strv_free(m->os_release); strv_free(m->initrd_release); - strv_free(m->extension_release); + strv_free(m->confext_release); + strv_free(m->sysext_release); return mfree(m); } @@ -3352,7 +3353,8 @@ int dissected_image_acquire_metadata(DissectedImage *m, DissectImageFlags extra_ META_MACHINE_INFO, META_OS_RELEASE, META_INITRD_RELEASE, - META_EXTENSION_RELEASE, + META_SYSEXT_RELEASE, + META_CONFEXT_RELEASE, META_HAS_INIT_SYSTEM, _META_MAX, }; @@ -3361,15 +3363,16 @@ int dissected_image_acquire_metadata(DissectedImage *m, DissectImageFlags extra_ [META_HOSTNAME] = "/etc/hostname\0", [META_MACHINE_ID] = "/etc/machine-id\0", [META_MACHINE_INFO] = "/etc/machine-info\0", - [META_OS_RELEASE] = ("/etc/os-release\0" - "/usr/lib/os-release\0"), - [META_INITRD_RELEASE] = ("/etc/initrd-release\0" - "/usr/lib/initrd-release\0"), - [META_EXTENSION_RELEASE] = "extension-release\0", /* Used only for logging. */ + [META_OS_RELEASE] = "/etc/os-release\0" + "/usr/lib/os-release\0", + [META_INITRD_RELEASE] = "/etc/initrd-release\0" + "/usr/lib/initrd-release\0", + [META_SYSEXT_RELEASE] = "sysext-release\0", /* String used only for logging. */ + [META_CONFEXT_RELEASE] = "confext-release\0", /* ditto */ [META_HAS_INIT_SYSTEM] = "has-init-system\0", /* ditto */ }; - _cleanup_strv_free_ char **machine_info = NULL, **os_release = NULL, **initrd_release = NULL, **extension_release = NULL; + _cleanup_strv_free_ char **machine_info = NULL, **os_release = NULL, **initrd_release = NULL, **sysext_release = NULL, **confext_release = NULL; _cleanup_close_pair_ int error_pipe[2] = PIPE_EBADF; _cleanup_(rmdir_and_freep) char *t = NULL; _cleanup_(sigkill_waitp) pid_t child = 0; @@ -3379,12 +3382,10 @@ int dissected_image_acquire_metadata(DissectedImage *m, DissectImageFlags extra_ int fds[2 * _META_MAX], r, v; int has_init_system = -1; ssize_t n; - ImageClass image_class = IMAGE_SYSEXT; BLOCK_SIGNALS(SIGCHLD); assert(m); - assert(image_class); for (; n_meta_initialized < _META_MAX; n_meta_initialized ++) { if (!paths[n_meta_initialized]) { @@ -3439,40 +3440,46 @@ int dissected_image_acquire_metadata(DissectedImage *m, DissectImageFlags extra_ switch (k) { - case META_EXTENSION_RELEASE: { - /* As per the os-release spec, if the image is an extension it will have a file - * named after the image name in extension-release.d/ - we use the image name - * and try to resolve it with the extension-release helpers, as sometimes - * the image names are mangled on deployment and do not match anymore. - * Unlike other paths this is not fixed, and the image name - * can be mangled on deployment, so by calling into the helper - * we allow a fallback that matches on the first extension-release - * file found in the directory, if one named after the image cannot - * be found first. */ - ImageClass class = IMAGE_SYSEXT; - r = open_extension_release(t, IMAGE_SYSEXT, m->image_name, /* relax_extension_release_check= */ false, NULL, &fd); - if (r == -ENOENT) { - r = open_extension_release(t, IMAGE_CONFEXT, m->image_name, /* relax_extension_release_check= */ false, NULL, &fd); - if (r >= 0) - class = IMAGE_CONFEXT; - } + case META_SYSEXT_RELEASE: + /* As per the os-release spec, if the image is an extension it will have a + * file named after the image name in extension-release.d/ - we use the image + * name and try to resolve it with the extension-release helpers, as + * sometimes the image names are mangled on deployment and do not match + * anymore. Unlike other paths this is not fixed, and the image name can be + * mangled on deployment, so by calling into the helper we allow a fallback + * that matches on the first extension-release file found in the directory, + * if one named after the image cannot be found first. */ + r = open_extension_release( + t, + IMAGE_SYSEXT, + m->image_name, + /* relax_extension_release_check= */ false, + /* ret_path= */ NULL, + &fd); + if (r < 0) + fd = r; + break; + + case META_CONFEXT_RELEASE: + /* As above */ + r = open_extension_release( + t, + IMAGE_CONFEXT, + m->image_name, + /* relax_extension_release_check= */ false, + /* ret_path= */ NULL, + &fd); if (r < 0) fd = r; - else { - r = loop_write(fds[2*k+1], &class, sizeof(class)); - if (r < 0) - goto inner_fail; /* Propagate the error to the parent */ - } break; - } case META_HAS_INIT_SYSTEM: { bool found = false; FOREACH_STRING(init, - "/usr/lib/systemd/systemd", /* systemd on /usr merged system */ - "/lib/systemd/systemd", /* systemd on /usr non-merged systems */ + "/usr/lib/systemd/systemd", /* systemd on /usr/ merged system */ + "/lib/systemd/systemd", /* systemd on /usr/ non-merged systems */ "/sbin/init") { /* traditional path the Linux kernel invokes */ r = chase(init, t, CHASE_PREFIX_ROOT, NULL, NULL); @@ -3587,23 +3594,19 @@ int dissected_image_acquire_metadata(DissectedImage *m, DissectImageFlags extra_ break; - case META_EXTENSION_RELEASE: { - ImageClass cl = IMAGE_SYSEXT; - size_t nr; + case META_SYSEXT_RELEASE: + r = load_env_file_pairs(f, "sysext-release", &sysext_release); + if (r < 0) + log_debug_errno(r, "Failed to read sysext release file of image: %m"); - errno = 0; - nr = fread(&cl, 1, sizeof(cl), f); - if (nr != sizeof(cl)) - log_debug_errno(errno_or_else(EIO), "Failed to read class of extension image: %m"); - else { - image_class = cl; - r = load_env_file_pairs(f, "extension-release", &extension_release); - if (r < 0) - log_debug_errno(r, "Failed to read extension release file of image: %m"); - } + break; + + case META_CONFEXT_RELEASE: + r = load_env_file_pairs(f, "confext-release", &confext_release); + if (r < 0) + log_debug_errno(r, "Failed to read confext release file of image: %m"); break; - } case META_HAS_INIT_SYSTEM: { bool b = false; @@ -3641,9 +3644,9 @@ int dissected_image_acquire_metadata(DissectedImage *m, DissectImageFlags extra_ strv_free_and_replace(m->machine_info, machine_info); strv_free_and_replace(m->os_release, os_release); strv_free_and_replace(m->initrd_release, initrd_release); - strv_free_and_replace(m->extension_release, extension_release); + strv_free_and_replace(m->sysext_release, sysext_release); + strv_free_and_replace(m->confext_release, confext_release); m->has_init_system = has_init_system; - m->image_class = image_class; finish: for (unsigned k = 0; k < n_meta_initialized; k++) diff --git a/src/shared/dissect-image.h b/src/shared/dissect-image.h index eb0841bd2e..21a0f22bcc 100644 --- a/src/shared/dissect-image.h +++ b/src/shared/dissect-image.h @@ -108,9 +108,9 @@ struct DissectedImage { char **machine_info; char **os_release; char **initrd_release; - char **extension_release; + char **confext_release; + char **sysext_release; int has_init_system; - ImageClass image_class; }; struct MountOptions { diff --git a/src/sysext/sysext.c b/src/sysext/sysext.c index 784accc15d..becfbab44e 100644 --- a/src/sysext/sysext.c +++ b/src/sysext/sysext.c @@ -741,7 +741,7 @@ static int merge_subprocess(Hashmap *images, const char *workspace) { host_os_release_version_id, host_os_release_api_level, in_initrd() ? "initrd" : "system", - img->extension_release, + image_extension_release(img, arg_image_class), arg_image_class); if (r < 0) return r; |