ImageClass image_class_from_string(const char *s) _pure_;
/* The *_extension_release flavours will look for /usr/lib/extension-release/extension-release.NAME
+ * for sysext images and for /etc/extension-release.d/extension-release.NAME for confext images
* in accordance with the OS extension specification, rather than for /usr/lib/ or /etc/os-release. */
bool image_name_is_valid(const char *s) _pure_;
printf("%*s %s=%s\n", (int) strlen(prefix), "", *p, *q);
}
-static int get_sysext_scopes(DissectedImage *m, char ***ret_scopes) {
+static int get_extension_scopes(DissectedImage *m, char ***ret_scopes) {
_cleanup_strv_free_ char **l = NULL;
const char *e;
assert(m);
assert(ret_scopes);
- /* If there's no extension-release file its not a system extension. Otherwise the SYSEXT_SCOPE field
- * indicates which scope it is for — and it defaults to "system" + "portable" if unset. */
-
+ /* 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) {
*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");
if (e)
l = strv_split(e, WHITESPACE);
else
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 **sysext_scopes = NULL;
+ _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));
printf(" %s initrd\n",
COLOR_MARK_BOOL(!strv_isempty(m->initrd_release)));
- r = get_sysext_scopes(m, &sysext_scopes);
+ r = get_extension_scopes(m, &extension_scopes);
if (r < 0)
- return log_error_errno(r, "Failed to parse SYSEXT_SCOPE: %m");
+ return log_error_errno(r, "Failed to parse scope: %m");
- printf(" %s extension for system\n",
- COLOR_MARK_BOOL(strv_contains(sysext_scopes, "system")));
- printf(" %s extension for initrd\n",
- COLOR_MARK_BOOL(strv_contains(sysext_scopes, "initrd")));
- printf(" %s extension for portable service\n",
- COLOR_MARK_BOOL(strv_contains(sysext_scopes, "portable")));
+ 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);
putc('\n', stdout);
} else {
_cleanup_(json_variant_unrefp) JsonVariant *mi = NULL, *osr = NULL, *irdr = NULL, *exr = NULL;
- _cleanup_strv_free_ char **sysext_scopes = NULL;
+ _cleanup_strv_free_ char **extension_scopes = NULL;
if (!strv_isempty(m->machine_info)) {
r = strv_pair_to_json(m->machine_info, &mi);
return log_oom();
}
- r = get_sysext_scopes(m, &sysext_scopes);
+ r = get_extension_scopes(m, &extension_scopes);
if (r < 0)
- return log_error_errno(r, "Failed to parse SYSEXT_SCOPE: %m");
+ return log_error_errno(r, "Failed to parse scope: %m");
r = json_build(&v, JSON_BUILD_OBJECT(
JSON_BUILD_PAIR("name", JSON_BUILD_STRING(bn)),
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("useSystemExtension", JSON_BUILD_BOOLEAN(strv_contains(sysext_scopes, "system"))),
- JSON_BUILD_PAIR("useInitRDExtension", JSON_BUILD_BOOLEAN(strv_contains(sysext_scopes, "initrd"))),
- JSON_BUILD_PAIR("usePortableExtension", JSON_BUILD_BOOLEAN(strv_contains(sysext_scopes, "portable")))));
+ 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")))));
if (r < 0)
return log_oom();
}
seq[0] = safe_close(seq[0]);
if (path_is_extension)
- flags |= DISSECT_IMAGE_VALIDATE_OS_EXT | (relax_extension_release_check ? DISSECT_IMAGE_RELAX_SYSEXT_CHECK : 0);
+ flags |= DISSECT_IMAGE_VALIDATE_OS_EXT | (relax_extension_release_check ? DISSECT_IMAGE_RELAX_EXTENSION_CHECK : 0);
else
flags |= DISSECT_IMAGE_VALIDATE_OS;
if (r < 0)
return r;
if (r == 0) {
- r = path_is_extension_tree(IMAGE_SYSEXT, where, m->image_name, FLAGS_SET(flags, DISSECT_IMAGE_RELAX_SYSEXT_CHECK));
+ r = path_is_extension_tree(IMAGE_SYSEXT, where, m->image_name, FLAGS_SET(flags, DISSECT_IMAGE_RELAX_EXTENSION_CHECK));
+ if (r == 0)
+ r = path_is_extension_tree(IMAGE_CONFEXT, where, m->image_name, FLAGS_SET(flags, DISSECT_IMAGE_RELAX_EXTENSION_CHECK));
if (r < 0)
return r;
if (r > 0)
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]) {
switch (k) {
- case META_EXTENSION_RELEASE:
+ 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
* 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;
+ }
if (r < 0)
- fd = r; /* Propagate the error. */
+ fd = r;
+ else {
+ r = loop_write(fds[2*k+1], &class, sizeof(class), false);
+ if (r < 0)
+ goto inner_fail; /* Propagate the error to the parent */
+ }
+
break;
+ }
case META_HAS_INIT_SYSTEM: {
bool found = false;
break;
- case META_EXTENSION_RELEASE:
- 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");
+ case META_EXTENSION_RELEASE: {
+ ImageClass cl = IMAGE_SYSEXT;
+ size_t nr;
+
+ 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_HAS_INIT_SYSTEM: {
bool b = false;
strv_free_and_replace(m->initrd_release, initrd_release);
strv_free_and_replace(m->extension_release, extension_release);
m->has_init_system = has_init_system;
+ m->image_class = image_class;
finish:
for (unsigned k = 0; k < n_meta_initialized; k++)
return log_debug_errno(r, "Failed to load root hash: %m");
dissect_image_flags = (verity.data_path ? DISSECT_IMAGE_NO_PARTITION_TABLE : 0) |
- (relax_extension_release_check ? DISSECT_IMAGE_RELAX_SYSEXT_CHECK : 0) |
+ (relax_extension_release_check ? DISSECT_IMAGE_RELAX_EXTENSION_CHECK : 0) |
DISSECT_IMAGE_ADD_PARTITION_DEVICES |
DISSECT_IMAGE_PIN_PARTITION_DEVICES;
* then a simple match on the ID will be performed. */
if (required_host_os_release_id) {
_cleanup_strv_free_ char **extension_release = NULL;
+ ImageClass class = IMAGE_SYSEXT;
assert(!isempty(required_host_os_release_id));
r = load_extension_release_pairs(dest, IMAGE_SYSEXT, dissected_image->image_name, relax_extension_release_check, &extension_release);
+ if (r == -ENOENT) {
+ r = load_extension_release_pairs(dest, IMAGE_CONFEXT, dissected_image->image_name, relax_extension_release_check, &extension_release);
+ if (r >= 0)
+ class = IMAGE_CONFEXT;
+ }
if (r < 0)
return log_debug_errno(r, "Failed to parse image %s extension-release metadata: %m", dissected_image->image_name);
required_host_os_release_sysext_level,
required_sysext_scope,
extension_release,
- IMAGE_SYSEXT);
+ class);
if (r == 0)
return log_debug_errno(SYNTHETIC_ERRNO(ESTALE), "Image %s extension-release metadata does not match the root's", dissected_image->image_name);
if (r < 0)
#include "list.h"
#include "loop-util.h"
#include "macro.h"
+#include "os-util.h"
typedef struct DissectedImage DissectedImage;
typedef struct DissectedPartition DissectedPartition;
DISSECT_IMAGE_MOUNT_IDMAPPED = 1 << 19, /* Mount mounts with kernel 5.12-style userns ID mapping, if file system type doesn't support uid=/gid= */
DISSECT_IMAGE_ADD_PARTITION_DEVICES = 1 << 20, /* Create partition devices via BLKPG_ADD_PARTITION */
DISSECT_IMAGE_PIN_PARTITION_DEVICES = 1 << 21, /* Open dissected partitions and decrypted partitions and pin them by fd */
- DISSECT_IMAGE_RELAX_SYSEXT_CHECK = 1 << 22, /* Don't insist that the extension-release file name matches the image name */
+ DISSECT_IMAGE_RELAX_EXTENSION_CHECK = 1 << 22, /* Don't insist that the extension-release file name matches the image name */
DISSECT_IMAGE_DISKSEQ_DEVNODE = 1 << 23, /* Prefer /dev/disk/by-diskseq/… device nodes */
DISSECT_IMAGE_ALLOW_EMPTY = 1 << 24, /* Allow that no usable partitions is present */
} DissectImageFlags;
char **initrd_release;
char **extension_release;
int has_init_system;
+ ImageClass image_class;
};
struct MountOptions {
return log_error_errno(r, "Failed to discover images: %m");
HASHMAP_FOREACH(img, images) {
- r = image_read_metadata(img, &image_policy_sysext);
+ r = image_read_metadata(img, image_class_info[arg_image_class].default_image_policy);
if (r < 0)
return log_error_errno(r, "Failed to read metadata for image %s: %m", img->name);
}
test_policy(&image_policy_deny, "~");
test_policy(&image_policy_sysext, "sysext");
test_policy(&image_policy_sysext_strict, "sysext-strict");
+ test_policy(&image_policy_confext, "confext");
test_policy(&image_policy_container, "container");
test_policy(&image_policy_host, "host");
test_policy(&image_policy_service, "service");