Merge pull request #29525 from poettering/confext-sysext-multimodal

dissect: make sure we can dissect and inspect DDIs that are both confext *and* sysext
This commit is contained in:
Luca Boccassi
2023-10-14 00:28:47 +01:00
committed by GitHub
11 changed files with 230 additions and 156 deletions
+14 -9
View File
@@ -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;
}
+13 -1
View File
@@ -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);
+54 -51
View File
@@ -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++)
+20 -2
View File
@@ -6,11 +6,13 @@
#include "sd-id128.h"
#include "architecture.h"
#include "env-util.h"
#include "gpt.h"
#include "list.h"
#include "loop-util.h"
#include "macro.h"
#include "os-util.h"
#include "strv.h"
typedef struct DissectedImage DissectedImage;
typedef struct DissectedPartition DissectedPartition;
@@ -108,9 +110,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 {
@@ -169,6 +171,22 @@ int dissected_image_acquire_metadata(DissectedImage *m, DissectImageFlags extra_
Architecture dissected_image_architecture(DissectedImage *m);
static inline bool dissected_image_is_bootable_os(DissectedImage *m) {
return m && m->has_init_system > 0;
}
static inline bool dissected_image_is_bootable_uefi(DissectedImage *m) {
return m && m->partitions[PARTITION_ESP].found && dissected_image_is_bootable_os(m);
}
static inline bool dissected_image_is_portable(DissectedImage *m) {
return m && strv_env_pairs_get(m->os_release, "PORTABLE_PREFIXES");
}
static inline bool dissected_image_is_initrd(DissectedImage *m) {
return m && !strv_isempty(m->initrd_release);
}
DecryptedImage* decrypted_image_ref(DecryptedImage *p);
DecryptedImage* decrypted_image_unref(DecryptedImage *p);
DEFINE_TRIVIAL_CLEANUP_FUNC(DecryptedImage*, decrypted_image_unref);
+43
View File
@@ -3709,6 +3709,49 @@ int json_buildv(JsonVariant **ret, va_list ap) {
break;
}
case _JSON_BUILD_STRV_ENV_PAIR: {
char **l;
if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
r = -EINVAL;
goto finish;
}
l = va_arg(ap, char **);
_cleanup_strv_free_ char **el = NULL;
STRV_FOREACH_PAIR(x, y, l) {
char *n = NULL;
n = strjoin(*x, "=", *y);
if (!n) {
r = -ENOMEM;
goto finish;
}
r = strv_consume(&el, n);
if (r < 0)
goto finish;
}
if (current->n_suppress == 0) {
r = json_variant_new_array_strv(&add, el);
if (r < 0)
goto finish;
}
n_subtract = 1;
if (current->expect == EXPECT_TOPLEVEL)
current->expect = EXPECT_END;
else if (current->expect == EXPECT_OBJECT_VALUE)
current->expect = EXPECT_OBJECT_KEY;
else
assert(current->expect == EXPECT_ARRAY_ELEMENT);
break;
}
case _JSON_BUILD_BASE64:
case _JSON_BUILD_BASE32HEX:
case _JSON_BUILD_HEX:
+2
View File
@@ -266,6 +266,7 @@ enum {
_JSON_BUILD_VARIANT_ARRAY,
_JSON_BUILD_LITERAL,
_JSON_BUILD_STRV,
_JSON_BUILD_STRV_ENV_PAIR,
_JSON_BUILD_BASE64,
_JSON_BUILD_BASE32HEX,
_JSON_BUILD_HEX,
@@ -304,6 +305,7 @@ enum {
#define JSON_BUILD_VARIANT_ARRAY(v, n) _JSON_BUILD_VARIANT_ARRAY, (JsonVariant **) { v }, (size_t) { n }
#define JSON_BUILD_LITERAL(l) _JSON_BUILD_LITERAL, (const char*) { l }
#define JSON_BUILD_STRV(l) _JSON_BUILD_STRV, (char**) { l }
#define JSON_BUILD_STRV_ENV_PAIR(l) _JSON_BUILD_STRV_ENV_PAIR, (char**) { l }
#define JSON_BUILD_BASE64(p, n) _JSON_BUILD_BASE64, (const void*) { p }, (size_t) { n }
#define JSON_BUILD_BASE32HEX(p, n) _JSON_BUILD_BASE32HEX, (const void*) { p }, (size_t) { n }
#define JSON_BUILD_HEX(p, n) _JSON_BUILD_HEX, (const void*) { p }, (size_t) { n }