Skip to content

Commit 484d26d

Browse files
committed
confext: add dissect tool support for confext images
Allow image wide systemd tool support for confext images by adding dissect tool support for these images
1 parent 8a324d1 commit 484d26d

File tree

7 files changed

+74
-31
lines changed

7 files changed

+74
-31
lines changed

src/basic/os-util.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const char* image_class_to_string(ImageClass cl) _const_;
1919
ImageClass image_class_from_string(const char *s) _pure_;
2020

2121
/* The *_extension_release flavours will look for /usr/lib/extension-release/extension-release.NAME
22+
* for sysext images and for /etc/extension-release.d/extension-release.NAME for confext images
2223
* in accordance with the OS extension specification, rather than for /usr/lib/ or /etc/os-release. */
2324

2425
bool image_name_is_valid(const char *s) _pure_;

src/dissect/dissect.c

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -782,22 +782,24 @@ static void strv_pair_print(char **l, const char *prefix) {
782782
printf("%*s %s=%s\n", (int) strlen(prefix), "", *p, *q);
783783
}
784784

785-
static int get_sysext_scopes(DissectedImage *m, char ***ret_scopes) {
785+
static int get_extension_scopes(DissectedImage *m, char ***ret_scopes) {
786786
_cleanup_strv_free_ char **l = NULL;
787787
const char *e;
788788

789789
assert(m);
790790
assert(ret_scopes);
791791

792-
/* If there's no extension-release file its not a system extension. Otherwise the SYSEXT_SCOPE field
793-
* indicates which scope it is for and it defaults to "system" + "portable" if unset. */
794-
792+
/* If there's no extension-release file its not a system extension. Otherwise the SYSEXT_SCOPE
793+
* field for sysext images and the CONFEXT_SCOPE field for confext images indicates which scope
794+
* it is for — and it defaults to "system" + "portable" if unset. */
795795
if (!m->extension_release) {
796796
*ret_scopes = NULL;
797797
return 0;
798798
}
799799

800800
e = strv_env_pairs_get(m->extension_release, "SYSEXT_SCOPE");
801+
if (!e)
802+
e = strv_env_pairs_get(m->extension_release, "CONFEXT_SCOPE");
801803
if (e)
802804
l = strv_split(e, WHITESPACE);
803805
else
@@ -858,7 +860,7 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) {
858860
else if (r < 0)
859861
return log_error_errno(r, "Failed to acquire image metadata: %m");
860862
else if (arg_json_format_flags & JSON_FORMAT_OFF) {
861-
_cleanup_strv_free_ char **sysext_scopes = NULL;
863+
_cleanup_strv_free_ char **extension_scopes = NULL;
862864

863865
if (!sd_id128_is_null(m->image_uuid))
864866
printf("Image UUID: %s\n", SD_ID128_TO_UUID_STRING(m->image_uuid));
@@ -896,21 +898,22 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) {
896898
printf(" %s initrd\n",
897899
COLOR_MARK_BOOL(!strv_isempty(m->initrd_release)));
898900

899-
r = get_sysext_scopes(m, &sysext_scopes);
901+
r = get_extension_scopes(m, &extension_scopes);
900902
if (r < 0)
901-
return log_error_errno(r, "Failed to parse SYSEXT_SCOPE: %m");
903+
return log_error_errno(r, "Failed to parse scope: %m");
902904

903-
printf(" %s extension for system\n",
904-
COLOR_MARK_BOOL(strv_contains(sysext_scopes, "system")));
905-
printf(" %s extension for initrd\n",
906-
COLOR_MARK_BOOL(strv_contains(sysext_scopes, "initrd")));
907-
printf(" %s extension for portable service\n",
908-
COLOR_MARK_BOOL(strv_contains(sysext_scopes, "portable")));
905+
const char *string_class = image_class_to_string(m->image_class);
906+
printf(" %s %s extension for system\n",
907+
COLOR_MARK_BOOL(strv_contains(extension_scopes, "system")), string_class);
908+
printf(" %s %s extension for initrd\n",
909+
COLOR_MARK_BOOL(strv_contains(extension_scopes, "initrd")), string_class);
910+
printf(" %s %s extension for portable service\n",
911+
COLOR_MARK_BOOL(strv_contains(extension_scopes, "portable")), string_class);
909912

910913
putc('\n', stdout);
911914
} else {
912915
_cleanup_(json_variant_unrefp) JsonVariant *mi = NULL, *osr = NULL, *irdr = NULL, *exr = NULL;
913-
_cleanup_strv_free_ char **sysext_scopes = NULL;
916+
_cleanup_strv_free_ char **extension_scopes = NULL;
914917

915918
if (!strv_isempty(m->machine_info)) {
916919
r = strv_pair_to_json(m->machine_info, &mi);
@@ -936,9 +939,9 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) {
936939
return log_oom();
937940
}
938941

939-
r = get_sysext_scopes(m, &sysext_scopes);
942+
r = get_extension_scopes(m, &extension_scopes);
940943
if (r < 0)
941-
return log_error_errno(r, "Failed to parse SYSEXT_SCOPE: %m");
944+
return log_error_errno(r, "Failed to parse scope: %m");
942945

943946
r = json_build(&v, JSON_BUILD_OBJECT(
944947
JSON_BUILD_PAIR("name", JSON_BUILD_STRING(bn)),
@@ -955,9 +958,10 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) {
955958
JSON_BUILD_PAIR_CONDITION(m->has_init_system >= 0, "useBootableContainer", JSON_BUILD_BOOLEAN(m->has_init_system)),
956959
JSON_BUILD_PAIR("useInitrd", JSON_BUILD_BOOLEAN(!strv_isempty(m->initrd_release))),
957960
JSON_BUILD_PAIR("usePortableService", JSON_BUILD_BOOLEAN(strv_env_pairs_get(m->os_release, "PORTABLE_MATCHES"))),
958-
JSON_BUILD_PAIR("useSystemExtension", JSON_BUILD_BOOLEAN(strv_contains(sysext_scopes, "system"))),
959-
JSON_BUILD_PAIR("useInitRDExtension", JSON_BUILD_BOOLEAN(strv_contains(sysext_scopes, "initrd"))),
960-
JSON_BUILD_PAIR("usePortableExtension", JSON_BUILD_BOOLEAN(strv_contains(sysext_scopes, "portable")))));
961+
JSON_BUILD_PAIR("ExtensionType", JSON_BUILD_STRING(image_class_to_string(m->image_class))),
962+
JSON_BUILD_PAIR("useSystemExtension", JSON_BUILD_BOOLEAN(strv_contains(extension_scopes, "system"))),
963+
JSON_BUILD_PAIR("useInitRDExtension", JSON_BUILD_BOOLEAN(strv_contains(extension_scopes, "initrd"))),
964+
JSON_BUILD_PAIR("usePortableExtension", JSON_BUILD_BOOLEAN(strv_contains(extension_scopes, "portable")))));
961965
if (r < 0)
962966
return log_oom();
963967
}

src/portable/portable.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ static int portable_extract_by_path(
420420
seq[0] = safe_close(seq[0]);
421421

422422
if (path_is_extension)
423-
flags |= DISSECT_IMAGE_VALIDATE_OS_EXT | (relax_extension_release_check ? DISSECT_IMAGE_RELAX_SYSEXT_CHECK : 0);
423+
flags |= DISSECT_IMAGE_VALIDATE_OS_EXT | (relax_extension_release_check ? DISSECT_IMAGE_RELAX_EXTENSION_CHECK : 0);
424424
else
425425
flags |= DISSECT_IMAGE_VALIDATE_OS;
426426

src/shared/dissect-image.c

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2102,7 +2102,9 @@ int dissected_image_mount(
21022102
if (r < 0)
21032103
return r;
21042104
if (r == 0) {
2105-
r = path_is_extension_tree(IMAGE_SYSEXT, where, m->image_name, FLAGS_SET(flags, DISSECT_IMAGE_RELAX_SYSEXT_CHECK));
2105+
r = path_is_extension_tree(IMAGE_SYSEXT, where, m->image_name, FLAGS_SET(flags, DISSECT_IMAGE_RELAX_EXTENSION_CHECK));
2106+
if (r == 0)
2107+
r = path_is_extension_tree(IMAGE_CONFEXT, where, m->image_name, FLAGS_SET(flags, DISSECT_IMAGE_RELAX_EXTENSION_CHECK));
21062108
if (r < 0)
21072109
return r;
21082110
if (r > 0)
@@ -3295,10 +3297,12 @@ int dissected_image_acquire_metadata(DissectedImage *m, DissectImageFlags extra_
32953297
int fds[2 * _META_MAX], r, v;
32963298
int has_init_system = -1;
32973299
ssize_t n;
3300+
ImageClass image_class = IMAGE_SYSEXT;
32983301

32993302
BLOCK_SIGNALS(SIGCHLD);
33003303

33013304
assert(m);
3305+
assert(image_class);
33023306

33033307
for (; n_meta_initialized < _META_MAX; n_meta_initialized ++) {
33043308
if (!paths[n_meta_initialized]) {
@@ -3352,7 +3356,7 @@ int dissected_image_acquire_metadata(DissectedImage *m, DissectImageFlags extra_
33523356

33533357
switch (k) {
33543358

3355-
case META_EXTENSION_RELEASE:
3359+
case META_EXTENSION_RELEASE: {
33563360
/* As per the os-release spec, if the image is an extension it will have a file
33573361
* named after the image name in extension-release.d/ - we use the image name
33583362
* and try to resolve it with the extension-release helpers, as sometimes
@@ -3362,10 +3366,23 @@ int dissected_image_acquire_metadata(DissectedImage *m, DissectImageFlags extra_
33623366
* we allow a fallback that matches on the first extension-release
33633367
* file found in the directory, if one named after the image cannot
33643368
* be found first. */
3369+
ImageClass class = IMAGE_SYSEXT;
33653370
r = open_extension_release(t, IMAGE_SYSEXT, m->image_name, /* relax_extension_release_check= */ false, NULL, &fd);
3371+
if (r == -ENOENT) {
3372+
r = open_extension_release(t, IMAGE_CONFEXT, m->image_name, /* relax_extension_release_check= */ false, NULL, &fd);
3373+
if (r >= 0)
3374+
class = IMAGE_CONFEXT;
3375+
}
33663376
if (r < 0)
3367-
fd = r; /* Propagate the error. */
3377+
fd = r;
3378+
else {
3379+
r = loop_write(fds[2*k+1], &class, sizeof(class), false);
3380+
if (r < 0)
3381+
goto inner_fail; /* Propagate the error to the parent */
3382+
}
3383+
33683384
break;
3385+
}
33693386

33703387
case META_HAS_INIT_SYSTEM: {
33713388
bool found = false;
@@ -3487,12 +3504,23 @@ int dissected_image_acquire_metadata(DissectedImage *m, DissectImageFlags extra_
34873504

34883505
break;
34893506

3490-
case META_EXTENSION_RELEASE:
3491-
r = load_env_file_pairs(f, "extension-release", &extension_release);
3492-
if (r < 0)
3493-
log_debug_errno(r, "Failed to read extension release file of image: %m");
3507+
case META_EXTENSION_RELEASE: {
3508+
ImageClass cl = IMAGE_SYSEXT;
3509+
size_t nr;
3510+
3511+
errno = 0;
3512+
nr = fread(&cl, 1, sizeof(cl), f);
3513+
if (nr != sizeof(cl))
3514+
log_debug_errno(errno_or_else(EIO), "Failed to read class of extension image: %m");
3515+
else {
3516+
image_class = cl;
3517+
r = load_env_file_pairs(f, "extension-release", &extension_release);
3518+
if (r < 0)
3519+
log_debug_errno(r, "Failed to read extension release file of image: %m");
3520+
}
34943521

34953522
break;
3523+
}
34963524

34973525
case META_HAS_INIT_SYSTEM: {
34983526
bool b = false;
@@ -3532,6 +3560,7 @@ int dissected_image_acquire_metadata(DissectedImage *m, DissectImageFlags extra_
35323560
strv_free_and_replace(m->initrd_release, initrd_release);
35333561
strv_free_and_replace(m->extension_release, extension_release);
35343562
m->has_init_system = has_init_system;
3563+
m->image_class = image_class;
35353564

35363565
finish:
35373566
for (unsigned k = 0; k < n_meta_initialized; k++)
@@ -3820,7 +3849,7 @@ int verity_dissect_and_mount(
38203849
return log_debug_errno(r, "Failed to load root hash: %m");
38213850

38223851
dissect_image_flags = (verity.data_path ? DISSECT_IMAGE_NO_PARTITION_TABLE : 0) |
3823-
(relax_extension_release_check ? DISSECT_IMAGE_RELAX_SYSEXT_CHECK : 0) |
3852+
(relax_extension_release_check ? DISSECT_IMAGE_RELAX_EXTENSION_CHECK : 0) |
38243853
DISSECT_IMAGE_ADD_PARTITION_DEVICES |
38253854
DISSECT_IMAGE_PIN_PARTITION_DEVICES;
38263855

@@ -3889,10 +3918,16 @@ int verity_dissect_and_mount(
38893918
* then a simple match on the ID will be performed. */
38903919
if (required_host_os_release_id) {
38913920
_cleanup_strv_free_ char **extension_release = NULL;
3921+
ImageClass class = IMAGE_SYSEXT;
38923922

38933923
assert(!isempty(required_host_os_release_id));
38943924

38953925
r = load_extension_release_pairs(dest, IMAGE_SYSEXT, dissected_image->image_name, relax_extension_release_check, &extension_release);
3926+
if (r == -ENOENT) {
3927+
r = load_extension_release_pairs(dest, IMAGE_CONFEXT, dissected_image->image_name, relax_extension_release_check, &extension_release);
3928+
if (r >= 0)
3929+
class = IMAGE_CONFEXT;
3930+
}
38963931
if (r < 0)
38973932
return log_debug_errno(r, "Failed to parse image %s extension-release metadata: %m", dissected_image->image_name);
38983933

@@ -3903,7 +3938,7 @@ int verity_dissect_and_mount(
39033938
required_host_os_release_sysext_level,
39043939
required_sysext_scope,
39053940
extension_release,
3906-
IMAGE_SYSEXT);
3941+
class);
39073942
if (r == 0)
39083943
return log_debug_errno(SYNTHETIC_ERRNO(ESTALE), "Image %s extension-release metadata does not match the root's", dissected_image->image_name);
39093944
if (r < 0)

src/shared/dissect-image.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "list.h"
1111
#include "loop-util.h"
1212
#include "macro.h"
13+
#include "os-util.h"
1314

1415
typedef struct DissectedImage DissectedImage;
1516
typedef struct DissectedPartition DissectedPartition;
@@ -78,7 +79,7 @@ typedef enum DissectImageFlags {
7879
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= */
7980
DISSECT_IMAGE_ADD_PARTITION_DEVICES = 1 << 20, /* Create partition devices via BLKPG_ADD_PARTITION */
8081
DISSECT_IMAGE_PIN_PARTITION_DEVICES = 1 << 21, /* Open dissected partitions and decrypted partitions and pin them by fd */
81-
DISSECT_IMAGE_RELAX_SYSEXT_CHECK = 1 << 22, /* Don't insist that the extension-release file name matches the image name */
82+
DISSECT_IMAGE_RELAX_EXTENSION_CHECK = 1 << 22, /* Don't insist that the extension-release file name matches the image name */
8283
DISSECT_IMAGE_DISKSEQ_DEVNODE = 1 << 23, /* Prefer /dev/disk/by-diskseq/… device nodes */
8384
DISSECT_IMAGE_ALLOW_EMPTY = 1 << 24, /* Allow that no usable partitions is present */
8485
} DissectImageFlags;
@@ -107,6 +108,7 @@ struct DissectedImage {
107108
char **initrd_release;
108109
char **extension_release;
109110
int has_init_system;
111+
ImageClass image_class;
110112
};
111113

112114
struct MountOptions {

src/sysext/sysext.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -803,7 +803,7 @@ static int image_discover_and_read_metadata(Hashmap **ret_images) {
803803
return log_error_errno(r, "Failed to discover images: %m");
804804

805805
HASHMAP_FOREACH(img, images) {
806-
r = image_read_metadata(img, &image_policy_sysext);
806+
r = image_read_metadata(img, image_class_info[arg_image_class].default_image_policy);
807807
if (r < 0)
808808
return log_error_errno(r, "Failed to read metadata for image %s: %m", img->name);
809809
}

src/test/test-image-policy.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ TEST_RET(test_image_policy_to_string) {
7878
test_policy(&image_policy_deny, "~");
7979
test_policy(&image_policy_sysext, "sysext");
8080
test_policy(&image_policy_sysext_strict, "sysext-strict");
81+
test_policy(&image_policy_confext, "confext");
8182
test_policy(&image_policy_container, "container");
8283
test_policy(&image_policy_host, "host");
8384
test_policy(&image_policy_service, "service");

0 commit comments

Comments
 (0)