]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dissect: rework DISSECT_IMAGE_ADD_PARTITION_DEVICES + DISSECT_IMAGE_OPEN_PARTITION_DE...
authorLennart Poettering <lennart@poettering.net>
Wed, 30 Nov 2022 16:17:20 +0000 (17:17 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Thu, 1 Dec 2022 10:32:30 +0000 (11:32 +0100)
Curently, these two flags were implied by dissect_loop_device(), but
that's not right, because this means systemd-gpt-auto-generator will
dissect the root block device with these flags set and that's not
desirable: the generator should not cause the partition devices to be
created (we don't intend to use them right-away after all, but expect
udev to find/probe them first, and then mount them though .mount units).
And there's no point in opening the partition devices, since we do not
intend to mount them via fds either.

Hence, rework this: instead of implying the flags, specify them
explicitly.

While we are at it, let's also rename the flags to make them more
descriptive:

DISSECT_IMAGE_MANAGE_PARTITION_DEVICES becomes
DISSECT_IMAGE_ADD_PARTITION_DEVICES, since that's really all this does:
add the partition devices via BLKPG.

DISSECT_IMAGE_OPEN_PARTITION_DEVICES becomes
DISSECT_IMAGE_PIN_PARTITION_DEVICES, since we not only open the devices,
but keep the devices open continously (i.e. we "pin" them).

Also, drop the DISSECT_IMAGE_BLOCK_DEVICE combination flag, since it is
misleading, i.e. it suggests it was appropriate to specify on all
dissected blocking devices, but that's precisely not the case, see the
systemd-gpt-auto-generator case. My guess is that the confusion around
this was actually the cause for this bug we are addressing here.

Fixes: #25528
src/core/namespace.c
src/dissect/dissect.c
src/gpt-auto-generator/gpt-auto-generator.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/test/test-loop-block.c

index c0d0cc9715f3aec892dc07429c0a88f703bd65e1..4e9292f2de4993b3124ad4b8df892160a2c53017 100644 (file)
@@ -2051,7 +2051,9 @@ int setup_namespace(
                 DISSECT_IMAGE_RELAX_VAR_CHECK |
                 DISSECT_IMAGE_FSCK |
                 DISSECT_IMAGE_USR_NO_ROOT |
-                DISSECT_IMAGE_GROWFS;
+                DISSECT_IMAGE_GROWFS |
+                DISSECT_IMAGE_ADD_PARTITION_DEVICES |
+                DISSECT_IMAGE_PIN_PARTITION_DEVICES;
         size_t n_mounts;
         int r;
 
index 4ff86ba1dedc0aadaff0493f3a252f687dfac531..3cf250e8ec3aa504e5d629cb6d13b10eea57d2e1 100644 (file)
@@ -67,7 +67,9 @@ static DissectImageFlags arg_flags =
         DISSECT_IMAGE_RELAX_VAR_CHECK |
         DISSECT_IMAGE_FSCK |
         DISSECT_IMAGE_USR_NO_ROOT |
-        DISSECT_IMAGE_GROWFS;
+        DISSECT_IMAGE_GROWFS |
+        DISSECT_IMAGE_PIN_PARTITION_DEVICES |
+        DISSECT_IMAGE_ADD_PARTITION_DEVICES;
 static VeritySettings arg_verity_settings = VERITY_SETTINGS_DEFAULT;
 static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
 static PagerFlags arg_pager_flags = 0;
index f939b2e8c24a0de4e18e6ca6eab454a57b39b8f1..23a215231ca7063bc86d04322f939b76962888c4 100644 (file)
@@ -665,6 +665,11 @@ static int enumerate_partitions(dev_t devnum) {
                         NULL, NULL,
                         DISSECT_IMAGE_GPT_ONLY|
                         DISSECT_IMAGE_USR_NO_ROOT,
+                        /* NB! Unlike most other places where we dissect block devices we do not use
+                         * DISSECT_IMAGE_ADD_PARTITION_DEVICES here: we want that the kernel finds the
+                         * devices, and udev probes them before we mount them via .mount units much later
+                         * on. And thus we also don't set DISSECT_IMAGE_PIN_PARTITION_DEVICES here, because
+                         * we don't actually mount anything immediately. */
                         &m);
         if (r == -ENOPKG) {
                 log_debug_errno(r, "No suitable partition table found, ignoring.");
index d7b636209eb9e32203aa4184c7e2a1b20384bd23..f86222d1cc6ae2b4dd2ac82bd431a94d33366619 100644 (file)
@@ -5656,7 +5656,9 @@ static int run(int argc, char *argv[]) {
                         DISSECT_IMAGE_GENERIC_ROOT |
                         DISSECT_IMAGE_REQUIRE_ROOT |
                         DISSECT_IMAGE_RELAX_VAR_CHECK |
-                        DISSECT_IMAGE_USR_NO_ROOT;
+                        DISSECT_IMAGE_USR_NO_ROOT |
+                        DISSECT_IMAGE_ADD_PARTITION_DEVICES |
+                        DISSECT_IMAGE_PIN_PARTITION_DEVICES;
                 assert(arg_image);
                 assert(!arg_template);
 
index 76af743771ee5c05aca7378afc3792bb7fed6f35..0909e14aab664885853b6ba93c4540ac6e5b6651 100644 (file)
@@ -375,7 +375,9 @@ static int portable_extract_by_path(
                                 DISSECT_IMAGE_REQUIRE_ROOT |
                                 DISSECT_IMAGE_DISCARD_ON_LOOP |
                                 DISSECT_IMAGE_RELAX_VAR_CHECK |
-                                DISSECT_IMAGE_USR_NO_ROOT,
+                                DISSECT_IMAGE_USR_NO_ROOT |
+                                DISSECT_IMAGE_ADD_PARTITION_DEVICES |
+                                DISSECT_IMAGE_PIN_PARTITION_DEVICES,
                                 &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);
index 073e5e84338d50f0881bc4ad992e0774720c234d..9a7a1c990a74b6b1b4d9c5b072f639c00db61b05 100644 (file)
@@ -1201,7 +1201,9 @@ int image_read_metadata(Image *i) {
                                 DISSECT_IMAGE_REQUIRE_ROOT |
                                 DISSECT_IMAGE_RELAX_VAR_CHECK |
                                 DISSECT_IMAGE_READ_ONLY |
-                                DISSECT_IMAGE_USR_NO_ROOT,
+                                DISSECT_IMAGE_USR_NO_ROOT |
+                                DISSECT_IMAGE_ADD_PARTITION_DEVICES |
+                                DISSECT_IMAGE_PIN_PARTITION_DEVICES,
                                 &m);
                 if (r < 0)
                         return r;
index 4872fe4d6bdb0b0431a9c4670168635ae2068662..9ce9775049d58eca4730b781003cc188bec7e640 100644 (file)
@@ -458,7 +458,7 @@ static int dissect_image(
                         _cleanup_close_ int mount_node_fd = -1;
                         sd_id128_t uuid = SD_ID128_NULL;
 
-                        if (FLAGS_SET(flags, DISSECT_IMAGE_OPEN_PARTITION_DEVICES)) {
+                        if (FLAGS_SET(flags, DISSECT_IMAGE_PIN_PARTITION_DEVICES)) {
                                 mount_node_fd = open_partition(devname, /* is_partition = */ false, m->loop);
                                 if (mount_node_fd < 0)
                                         return mount_node_fd;
@@ -539,7 +539,7 @@ static int dissect_image(
         if (verity && verity->data_path)
                 return -EBADR;
 
-        if (FLAGS_SET(flags, DISSECT_IMAGE_MANAGE_PARTITION_DEVICES)) {
+        if (FLAGS_SET(flags, DISSECT_IMAGE_ADD_PARTITION_DEVICES)) {
                 /* Safety check: refuse block devices that carry a partition table but for which the kernel doesn't
                  * do partition scanning. */
                 r = blockdev_partscan_enabled(fd);
@@ -615,7 +615,7 @@ static int dissect_image(
                  * Kernel returns EBUSY if there's already a partition by that number or an overlapping
                  * partition already existent. */
 
-                if (FLAGS_SET(flags, DISSECT_IMAGE_MANAGE_PARTITION_DEVICES)) {
+                if (FLAGS_SET(flags, DISSECT_IMAGE_ADD_PARTITION_DEVICES)) {
                         r = block_device_add_partition(fd, node, nr, (uint64_t) start * 512, (uint64_t) size * 512);
                         if (r < 0) {
                                 if (r != -EBUSY)
@@ -870,7 +870,7 @@ static int dissect_image(
                                         dissected_partition_done(m->partitions + type.designator);
                                 }
 
-                                if (FLAGS_SET(flags, DISSECT_IMAGE_OPEN_PARTITION_DEVICES) &&
+                                if (FLAGS_SET(flags, DISSECT_IMAGE_PIN_PARTITION_DEVICES) &&
                                     type.designator != PARTITION_SWAP) {
                                         mount_node_fd = open_partition(node, /* is_partition = */ true, m->loop);
                                         if (mount_node_fd < 0)
@@ -945,7 +945,7 @@ static int dissect_image(
                                 if (m->partitions[PARTITION_XBOOTLDR].found)
                                         continue;
 
-                                if (FLAGS_SET(flags, DISSECT_IMAGE_OPEN_PARTITION_DEVICES)) {
+                                if (FLAGS_SET(flags, DISSECT_IMAGE_PIN_PARTITION_DEVICES)) {
                                         mount_node_fd = open_partition(node, /* is_partition = */ true, m->loop);
                                         if (mount_node_fd < 0)
                                                 return mount_node_fd;
@@ -1025,7 +1025,7 @@ static int dissect_image(
                         _cleanup_free_ char *o = NULL;
                         const char *options;
 
-                        if (FLAGS_SET(flags, DISSECT_IMAGE_OPEN_PARTITION_DEVICES)) {
+                        if (FLAGS_SET(flags, DISSECT_IMAGE_PIN_PARTITION_DEVICES)) {
                                 mount_node_fd = open_partition(generic_node, /* is_partition = */ true, m->loop);
                                 if (mount_node_fd < 0)
                                         return mount_node_fd;
@@ -1130,7 +1130,6 @@ int dissect_image_file(
         int r;
 
         assert(path);
-        assert((flags & DISSECT_IMAGE_BLOCK_DEVICE) == 0);
         assert(ret);
 
         fd = open(path, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
@@ -2945,7 +2944,7 @@ int dissect_loop_device(
 
         m->loop = loop_device_ref(loop);
 
-        r = dissect_image(m, loop->fd, loop->node, verity, mount_options, flags | DISSECT_IMAGE_BLOCK_DEVICE);
+        r = dissect_image(m, loop->fd, loop->node, verity, mount_options, flags);
         if (r < 0)
                 return r;
 
@@ -3108,6 +3107,10 @@ int mount_image_privately_interactively(
         assert(ret_directory);
         assert(ret_loop_device);
 
+        /* We intend to mount this right-away, hence add the partitions if needed and pin them*/
+        flags |= DISSECT_IMAGE_ADD_PARTITION_DEVICES |
+                DISSECT_IMAGE_PIN_PARTITION_DEVICES;
+
         r = verity_settings_load(&verity, image, NULL, NULL);
         if (r < 0)
                 return log_error_errno(r, "Failed to load root hash data: %m");
@@ -3202,7 +3205,9 @@ int verity_dissect_and_mount(
                 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_SYSEXT_CHECK : 0) |
+                DISSECT_IMAGE_ADD_PARTITION_DEVICES |
+                DISSECT_IMAGE_PIN_PARTITION_DEVICES;
 
         /* Note that we don't use loop_device_make here, as the FD is most likely O_PATH which would not be
          * accepted by LOOP_CONFIGURE, so just let loop_device_make_by_path reopen it as a regular FD. */
index 1a398010b53b9d9210c9fb8e4ea8336d12daa22f..52d8a2e5696ba19c053cd9d6da8c3233c745af49 100644 (file)
@@ -74,10 +74,8 @@ typedef enum DissectImageFlags {
                                                  DISSECT_IMAGE_MOUNT_READ_ONLY,
         DISSECT_IMAGE_GROWFS                   = 1 << 18, /* Grow file systems in partitions marked for that to the size of the partitions after mount */
         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_MANAGE_PARTITION_DEVICES = 1 << 20, /* Manage partition devices, e.g. probe each partition in more detail */
-        DISSECT_IMAGE_OPEN_PARTITION_DEVICES   = 1 << 21, /* Open dissected partitions and decrypted partitions */
-        DISSECT_IMAGE_BLOCK_DEVICE             = DISSECT_IMAGE_MANAGE_PARTITION_DEVICES |
-                                                 DISSECT_IMAGE_OPEN_PARTITION_DEVICES,
+        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 */
 } DissectImageFlags;
 
index 9a7ef8eb2906a29ed36cf87d77bf4ef96b61d06b..b9147fbd78d67b961cde87045656436702d75160 100644 (file)
@@ -522,7 +522,9 @@ static int merge_subprocess(Hashmap *images, const char *workspace) {
                                 DISSECT_IMAGE_GENERIC_ROOT |
                                 DISSECT_IMAGE_REQUIRE_ROOT |
                                 DISSECT_IMAGE_MOUNT_ROOT_ONLY |
-                                DISSECT_IMAGE_USR_NO_ROOT;
+                                DISSECT_IMAGE_USR_NO_ROOT |
+                                DISSECT_IMAGE_ADD_PARTITION_DEVICES |
+                                DISSECT_IMAGE_PIN_PARTITION_DEVICES;
 
                         r = verity_settings_load(&verity_settings, img->path, NULL, NULL);
                         if (r < 0)
index e2b97dd56ff5c7ff3d27b112876305da2e39c7a7..af2a9683a4319b0a3a8f85cd107478e5119531bd 100644 (file)
@@ -71,7 +71,7 @@ static void* thread_func(void *ptr) {
 
                 log_notice("Acquired loop device %s, will mount on %s", loop->node, mounted);
 
-                r = dissect_loop_device(loop, NULL, NULL, DISSECT_IMAGE_READ_ONLY, &dissected);
+                r = dissect_loop_device(loop, NULL, NULL, DISSECT_IMAGE_READ_ONLY|DISSECT_IMAGE_ADD_PARTITION_DEVICES|DISSECT_IMAGE_PIN_PARTITION_DEVICES, &dissected);
                 if (r < 0)
                         log_error_errno(r, "Failed dissect loopback device %s: %m", loop->node);
                 assert_se(r >= 0);
@@ -220,7 +220,7 @@ static int run(int argc, char *argv[]) {
         assert_se(loop_device_make(fd, O_RDWR, 0, UINT64_MAX, 0, LO_FLAGS_PARTSCAN, LOCK_EX, &loop) >= 0);
 
 #if HAVE_BLKID
-        assert_se(dissect_loop_device(loop, NULL, NULL, 0, &dissected) >= 0);
+        assert_se(dissect_loop_device(loop, NULL, NULL, DISSECT_IMAGE_ADD_PARTITION_DEVICES|DISSECT_IMAGE_PIN_PARTITION_DEVICES, &dissected) >= 0);
         verify_dissected_image(dissected);
 
         FOREACH_STRING(fs, "vfat", "ext4") {
@@ -246,7 +246,7 @@ static int run(int argc, char *argv[]) {
         assert_se(make_filesystem(dissected->partitions[PARTITION_HOME].node, "ext4", "home", NULL, id, true) >= 0);
 
         dissected = dissected_image_unref(dissected);
-        assert_se(dissect_loop_device(loop, NULL, NULL, 0, &dissected) >= 0);
+        assert_se(dissect_loop_device(loop, NULL, NULL, DISSECT_IMAGE_ADD_PARTITION_DEVICES|DISSECT_IMAGE_PIN_PARTITION_DEVICES, &dissected) >= 0);
         verify_dissected_image(dissected);
 
         assert_se(mkdtemp_malloc(NULL, &mounted) >= 0);