]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dissect-image: split DISSECT_IMAGE_REQUIRE_ROOT in two
authorLennart Poettering <lennart@poettering.net>
Wed, 10 Mar 2021 16:41:18 +0000 (17:41 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 16 Mar 2021 13:57:40 +0000 (14:57 +0100)
Previously, the flag did two things at once: enable support for using
generic partitions as root fs if there were only one/allow use of
partition-table-less images as root fs. And secondly, insist that there
was a rootfs, and fail if not. Let's split these two in two separate
options so that they can be used independently of each other.

There are cases where one wants to use one without the other (i.e. when
inspecting things with systemd-dissect tool it should be OK to do so
even if image has no root fs), and it's cleaner anyway.

12 files changed:
src/core/namespace.c
src/dissect/dissect.c
src/firstboot/firstboot.c
src/journal/journalctl.c
src/nspawn/nspawn.c
src/portable/portable.c
src/shared/discover-image.c
src/shared/dissect-image.c
src/shared/dissect-image.h
src/sysext/sysext.c
src/sysusers/sysusers.c
src/tmpfiles/tmpfiles.c

index c5897c6c944be52fda33757abdf39c6c5663cb01..56385270d86065239a481aadcf682f7ef9da1ff7 100644 (file)
@@ -1825,7 +1825,7 @@ int setup_namespace(
                 mount_flags = MS_SHARED;
 
         if (root_image) {
-                dissect_image_flags |= DISSECT_IMAGE_REQUIRE_ROOT;
+                dissect_image_flags |= DISSECT_IMAGE_GENERIC_ROOT | DISSECT_IMAGE_REQUIRE_ROOT;
 
                 /* Make the whole image read-only if we can determine that we only access it in a read-only fashion. */
                 if (root_read_only(read_only_paths,
index 06808a231e44c81dd759fec0bddb5ff396285b98..10ab834f0d971fdde14ced6727f9bd0747a077ec 100644 (file)
@@ -44,7 +44,13 @@ static const char *arg_image = NULL;
 static const char *arg_path = NULL;
 static const char *arg_source = NULL;
 static const char *arg_target = NULL;
-static DissectImageFlags arg_flags = DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_DISCARD_ON_LOOP|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK|DISSECT_IMAGE_USR_NO_ROOT;
+static DissectImageFlags arg_flags =
+        DISSECT_IMAGE_GENERIC_ROOT |
+        DISSECT_IMAGE_REQUIRE_ROOT |
+        DISSECT_IMAGE_DISCARD_ON_LOOP |
+        DISSECT_IMAGE_RELAX_VAR_CHECK |
+        DISSECT_IMAGE_FSCK |
+        DISSECT_IMAGE_USR_NO_ROOT;
 static VeritySettings arg_verity_settings = VERITY_SETTINGS_DEFAULT;
 static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
 static PagerFlags arg_pager_flags = 0;
index 8e3028717e79dbccc4d07acb3e93d9e331befabb..aa7251d1ef286c02969fe8886b29afd2aff48edd 100644 (file)
@@ -1291,7 +1291,11 @@ static int run(int argc, char *argv[]) {
 
                 r = mount_image_privately_interactively(
                                 arg_image,
-                                DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_VALIDATE_OS|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK,
+                                DISSECT_IMAGE_GENERIC_ROOT |
+                                DISSECT_IMAGE_REQUIRE_ROOT |
+                                DISSECT_IMAGE_VALIDATE_OS |
+                                DISSECT_IMAGE_RELAX_VAR_CHECK |
+                                DISSECT_IMAGE_FSCK,
                                 &unlink_dir,
                                 &loop_device,
                                 &decrypted_image);
index 6b06320d78285fd53119cd3fc2be9225a0e26be3..4b3e697855b34ab389e26c587410063129710fbe 100644 (file)
@@ -2150,7 +2150,10 @@ int main(int argc, char *argv[]) {
 
                 r = mount_image_privately_interactively(
                                 arg_image,
-                                DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_VALIDATE_OS|DISSECT_IMAGE_RELAX_VAR_CHECK|
+                                DISSECT_IMAGE_GENERIC_ROOT |
+                                DISSECT_IMAGE_REQUIRE_ROOT |
+                                DISSECT_IMAGE_VALIDATE_OS |
+                                DISSECT_IMAGE_RELAX_VAR_CHECK |
                                 (arg_action == ACTION_UPDATE_CATALOG ? DISSECT_IMAGE_FSCK : DISSECT_IMAGE_READ_ONLY),
                                 &unlink_dir,
                                 &loop_device,
index 00e2ba2654a54c0699ff405ecd9f725b29768f1e..f89fa1a573852a56c9c5c4c2aa70d89236c520b3 100644 (file)
@@ -5389,6 +5389,7 @@ static int run(int argc, char *argv[]) {
 
         } else {
                 DissectImageFlags dissect_image_flags =
+                        DISSECT_IMAGE_GENERIC_ROOT |
                         DISSECT_IMAGE_REQUIRE_ROOT |
                         DISSECT_IMAGE_RELAX_VAR_CHECK |
                         DISSECT_IMAGE_USR_NO_ROOT;
index aacc573ef6ecaea21c49f915aef57d51f72a5619..5651db67227d7d0136136cbed6785ebdcfe4ba0e 100644 (file)
@@ -380,7 +380,16 @@ static int portable_extract_by_path(
                 if (r < 0)
                         return log_debug_errno(r, "Failed to create temporary directory: %m");
 
-                r = dissect_image(d->fd, NULL, NULL, DISSECT_IMAGE_READ_ONLY|DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_DISCARD_ON_LOOP|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_USR_NO_ROOT, &m);
+                r = dissect_image(
+                                d->fd,
+                                NULL, NULL,
+                                DISSECT_IMAGE_READ_ONLY |
+                                DISSECT_IMAGE_GENERIC_ROOT |
+                                DISSECT_IMAGE_REQUIRE_ROOT |
+                                DISSECT_IMAGE_DISCARD_ON_LOOP |
+                                DISSECT_IMAGE_RELAX_VAR_CHECK |
+                                DISSECT_IMAGE_USR_NO_ROOT,
+                                &m);
                 if (r == -ENOPKG)
                         sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Couldn't identify a suitable partition table or file system in '%s'.", path);
                 else if (r == -EADDRNOTAVAIL)
index a2f226198077e9171f27768f4799374ab9854fad..43138e0a6f600437d1c6c484c2b050b7639f9a26 100644 (file)
@@ -1201,8 +1201,9 @@ int image_read_metadata(Image *i) {
                 r = dissect_image(
                                 d->fd,
                                 NULL, NULL,
-                                DISSECT_IMAGE_REQUIRE_ROOT|
-                                DISSECT_IMAGE_RELAX_VAR_CHECK|
+                                DISSECT_IMAGE_GENERIC_ROOT |
+                                DISSECT_IMAGE_REQUIRE_ROOT |
+                                DISSECT_IMAGE_RELAX_VAR_CHECK |
                                 DISSECT_IMAGE_USR_NO_ROOT, &m);
                 if (r < 0)
                         return r;
index 843fd41bb9dea287e4e8c0acb9e322a072017c7b..bdd357034890ac643719de7c9d4ca2ebafd37651 100644 (file)
@@ -630,7 +630,7 @@ int dissect_image(
         }
 
         if ((!(flags & DISSECT_IMAGE_GPT_ONLY) &&
-            (flags & DISSECT_IMAGE_REQUIRE_ROOT)) ||
+            (flags & DISSECT_IMAGE_GENERIC_ROOT)) ||
             (flags & DISSECT_IMAGE_NO_PARTITION_TABLE)) {
                 const char *usage = NULL;
 
@@ -1178,45 +1178,47 @@ int dissect_image(
         } else if (m->partitions[PARTITION_USR_SECONDARY_VERITY].found)
                 return -EADDRNOTAVAIL; /* as above */
 
-        else if (flags & DISSECT_IMAGE_REQUIRE_ROOT) {
-                _cleanup_free_ char *o = NULL;
-                const char *options = NULL;
+        else if ((flags & DISSECT_IMAGE_GENERIC_ROOT) &&
+                 (!verity || !verity->root_hash)) {
 
                 /* OK, we found nothing usable, then check if there's a single generic one distro, and use
-                 * that. */
-
-                /* If the root hash was set, then we won't fall back to a generic node, because the root hash
-                 * decides. */
-                if (verity && verity->root_hash)
-                        return -EADDRNOTAVAIL;
-
-                /* If we didn't find a generic node, then we can't fix this up either */
-                if (!generic_node)
-                        return -ENXIO;
+                 * that. If the root hash was set however, then we won't fall back to a generic node, because
+                 * the root hash decides. */
 
                 /* If we didn't find a properly marked root partition, but we did find a single suitable
                  * generic Linux partition, then use this as root partition, if the caller asked for it. */
                 if (multiple_generic)
                         return -ENOTUNIQ;
 
-                options = mount_options_from_designator(mount_options, PARTITION_ROOT);
-                if (options) {
-                        o = strdup(options);
-                        if (!o)
-                                return -ENOMEM;
-                }
+                /* If we didn't find a generic node, then we can't fix this up either */
+                if (generic_node) {
+                        _cleanup_free_ char *o = NULL;
+                        const char *options;
+
+                        options = mount_options_from_designator(mount_options, PARTITION_ROOT);
+                        if (options) {
+                                o = strdup(options);
+                                if (!o)
+                                        return -ENOMEM;
+                        }
 
-                m->partitions[PARTITION_ROOT] = (DissectedPartition) {
-                        .found = true,
-                        .rw = generic_rw,
-                        .partno = generic_nr,
-                        .architecture = _ARCHITECTURE_INVALID,
-                        .node = TAKE_PTR(generic_node),
-                        .uuid = generic_uuid,
-                        .mount_options = TAKE_PTR(o),
-                };
+                        m->partitions[PARTITION_ROOT] = (DissectedPartition) {
+                                .found = true,
+                                .rw = generic_rw,
+                                .partno = generic_nr,
+                                .architecture = _ARCHITECTURE_INVALID,
+                                .node = TAKE_PTR(generic_node),
+                                .uuid = generic_uuid,
+                                .mount_options = TAKE_PTR(o),
+                        };
+                }
         }
 
+        /* Check if we have a root fs if we are told to do check. /usr alone is fine too, but only if appropriate flag for that is set too */
+        if (FLAGS_SET(flags, DISSECT_IMAGE_REQUIRE_ROOT) &&
+            !(m->partitions[PARTITION_ROOT].found || (m->partitions[PARTITION_USR].found && FLAGS_SET(flags, DISSECT_IMAGE_USR_NO_ROOT))))
+                return -ENXIO;
+
         /* Refuse if we found a verity partition for /usr but no matching file system partition */
         if (!m->partitions[PARTITION_USR].found && m->partitions[PARTITION_USR_VERITY].found)
                 return -EADDRNOTAVAIL;
index 0e01c5e403b5e9c408a916622a0336f0555e7fad..f07955230bad8d8cdd58742055b2872557885425 100644 (file)
@@ -95,7 +95,7 @@ typedef enum DissectImageFlags {
                                     DISSECT_IMAGE_DISCARD |
                                     DISSECT_IMAGE_DISCARD_ON_CRYPTO,
         DISSECT_IMAGE_GPT_ONLY            = 1 << 4,  /* Only recognize images with GPT partition tables */
-        DISSECT_IMAGE_REQUIRE_ROOT        = 1 << 5,  /* Don't accept disks without root partition (and if no partition table or only single generic partition, assume it's root) */
+        DISSECT_IMAGE_GENERIC_ROOT        = 1 << 5,  /* If no partition table or only single generic partition, assume it's the root fs */
         DISSECT_IMAGE_MOUNT_ROOT_ONLY     = 1 << 6,  /* Mount only the root and /usr partitions */
         DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY = 1 << 7,  /* Mount only the non-root and non-/usr partitions */
         DISSECT_IMAGE_VALIDATE_OS         = 1 << 8,  /* Refuse mounting images that aren't identifiable as OS images */
@@ -106,6 +106,7 @@ typedef enum DissectImageFlags {
         DISSECT_IMAGE_VERITY_SHARE        = 1 << 13, /* When activating a verity device, reuse existing one if already open */
         DISSECT_IMAGE_MKDIR               = 1 << 14, /* Make top-level directory to mount right before mounting, if missing */
         DISSECT_IMAGE_USR_NO_ROOT         = 1 << 15, /* If no root fs is in the image, but /usr is, then allow this (so that we can mount the rootfs as tmpfs or so */
+        DISSECT_IMAGE_REQUIRE_ROOT        = 1 << 16, /* Don't accept disks without root partition (or at least /usr partition if DISSECT_IMAGE_USR_NO_ROOT is set) */
 } DissectImageFlags;
 
 struct DissectedImage {
index 2ebb96c397829a7842d37f35030ef9c6bb9fb435..49ec23d93430637033a3b915eb2d8b028a8d7bd4 100644 (file)
@@ -510,9 +510,10 @@ static int merge_subprocess(Hashmap *images, const char *workspace) {
                         _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|
+                                DISSECT_IMAGE_READ_ONLY |
+                                DISSECT_IMAGE_GENERIC_ROOT |
+                                DISSECT_IMAGE_REQUIRE_ROOT |
+                                DISSECT_IMAGE_MOUNT_ROOT_ONLY |
                                 DISSECT_IMAGE_USR_NO_ROOT;
 
                         r = verity_settings_load(&verity_settings, img->path, NULL, NULL);
index b098eb27cd46468fbeb711f2433a82d247da7ed5..27573b74e6da194c0ea01a34a0462a1641fac719 100644 (file)
@@ -1946,7 +1946,11 @@ static int run(int argc, char *argv[]) {
 
                 r = mount_image_privately_interactively(
                                 arg_image,
-                                DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_VALIDATE_OS|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK,
+                                DISSECT_IMAGE_GENERIC_ROOT |
+                                DISSECT_IMAGE_REQUIRE_ROOT |
+                                DISSECT_IMAGE_VALIDATE_OS |
+                                DISSECT_IMAGE_RELAX_VAR_CHECK |
+                                DISSECT_IMAGE_FSCK,
                                 &unlink_dir,
                                 &loop_device,
                                 &decrypted_image);
index 846e456551ee66d7e1822f09725e5be2a7669f2a..f11b4eed7cc91135d97bc9427dccdc21790b94db 100644 (file)
@@ -3431,7 +3431,11 @@ static int run(int argc, char *argv[]) {
 
                 r = mount_image_privately_interactively(
                                 arg_image,
-                                DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_VALIDATE_OS|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK,
+                                DISSECT_IMAGE_GENERIC_ROOT |
+                                DISSECT_IMAGE_REQUIRE_ROOT |
+                                DISSECT_IMAGE_VALIDATE_OS |
+                                DISSECT_IMAGE_RELAX_VAR_CHECK |
+                                DISSECT_IMAGE_FSCK,
                                 &unlink_dir,
                                 &loop_device,
                                 &decrypted_image);