]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dissect: ignore old uevents when waiting for loopback partition scan
authorLennart Poettering <lennart@poettering.net>
Tue, 20 Apr 2021 13:57:29 +0000 (15:57 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 20 Apr 2021 15:14:10 +0000 (17:14 +0200)
Let's drop all monitor uevent that were enqueued before we actually
started setting up the device.

This doesn't fix the race, but it makes the race window smaller: since
we cannot determine the uevent seqnum and the loopback attachment
atomically, there's a tiny window where uevents might be generated by
the device which we mistake for being associated with out use of the
loopback device.

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 9f9d47d34a2cd276161f3498f489fa96c7e357f1..bffcb5ac86e4e79b11e7373a4ba294418091ca70 100644 (file)
@@ -1863,6 +1863,7 @@ int setup_namespace(
                                 loop_device->fd,
                                 &verity,
                                 root_image_options,
+                                loop_device->uevent_seqnum_not_before,
                                 dissect_image_flags,
                                 &dissected_image);
                 if (r < 0)
index c21d3e47e40af9a5a45e2ca9910731bb10dc311a..d70f1e791f607e71cfcc4cca8fcfa8bc52d369fd 100644 (file)
@@ -781,6 +781,7 @@ static int run(int argc, char *argv[]) {
                         arg_image,
                         &arg_verity_settings,
                         NULL,
+                        d->uevent_seqnum_not_before,
                         arg_flags,
                         &m);
         if (r < 0)
index 42549a2cd8c6785c864767433fc30376b175b2ff..eb80165bbee92581815880e7754d68268cddcb93 100644 (file)
@@ -672,6 +672,7 @@ static int enumerate_partitions(dev_t devnum) {
         r = dissect_image(
                         fd,
                         NULL, NULL,
+                        UINT64_MAX,
                         DISSECT_IMAGE_GPT_ONLY|
                         DISSECT_IMAGE_NO_UDEV|
                         DISSECT_IMAGE_USR_NO_ROOT,
index 164a3302072cc5d575ee48beb32eb176533e83d5..070160241881360d0d1a636abe71e0655c394716 100644 (file)
@@ -5483,6 +5483,7 @@ static int run(int argc, char *argv[]) {
                                 arg_image,
                                 &arg_verity_settings,
                                 NULL,
+                                loop->uevent_seqnum_not_before,
                                 dissect_image_flags,
                                 &dissected_image);
                 if (r == -ENOPKG) {
index e2bce279473c26a42d94db36b16f672156b44ab2..28d884a95139c1788e331a9eccc16327bb9941b6 100644 (file)
@@ -395,6 +395,7 @@ static int portable_extract_by_path(
                 r = dissect_image(
                                 d->fd,
                                 NULL, NULL,
+                                d->uevent_seqnum_not_before,
                                 DISSECT_IMAGE_READ_ONLY |
                                 DISSECT_IMAGE_GENERIC_ROOT |
                                 DISSECT_IMAGE_REQUIRE_ROOT |
index 43138e0a6f600437d1c6c484c2b050b7639f9a26..c343d089316e946d38dd2ea178e0fe3a1b0d89ee 100644 (file)
@@ -1201,10 +1201,12 @@ int image_read_metadata(Image *i) {
                 r = dissect_image(
                                 d->fd,
                                 NULL, NULL,
+                                d->uevent_seqnum_not_before,
                                 DISSECT_IMAGE_GENERIC_ROOT |
                                 DISSECT_IMAGE_REQUIRE_ROOT |
                                 DISSECT_IMAGE_RELAX_VAR_CHECK |
-                                DISSECT_IMAGE_USR_NO_ROOT, &m);
+                                DISSECT_IMAGE_USR_NO_ROOT,
+                                &m);
                 if (r < 0)
                         return r;
 
index f6971038def6b1982bca7a29cd692520b80dc683..345e1db9a7def9a089f7f96b678501dbed49bc78 100644 (file)
@@ -260,6 +260,7 @@ struct wait_data {
         sd_device *parent_device;
         blkid_partition blkidp;
         sd_device *found;
+        uint64_t uevent_seqnum_not_before;
 };
 
 static inline void wait_data_done(struct wait_data *d) {
@@ -275,6 +276,20 @@ static int device_monitor_handler(sd_device_monitor *monitor, sd_device *device,
         if (device_for_action(device, SD_DEVICE_REMOVE))
                 return 0;
 
+        if (w->uevent_seqnum_not_before != UINT64_MAX) {
+                uint64_t seqnum;
+
+                r = sd_device_get_seqnum(device, &seqnum);
+                if (r < 0)
+                        goto finish;
+
+                if (seqnum <= w->uevent_seqnum_not_before) { /* From an older use of this loop device */
+                        log_debug("Dropping event because seqnum too old (%" PRIu64 " <= %" PRIu64 ")",
+                                  seqnum, w->uevent_seqnum_not_before);
+                        return 0;
+                }
+        }
+
         r = device_is_partition(device, w->parent_device, w->blkidp);
         if (r < 0)
                 goto finish;
@@ -294,6 +309,7 @@ static int wait_for_partition_device(
                 sd_device *parent,
                 blkid_partition pp,
                 usec_t deadline,
+                uint64_t uevent_seqnum_not_before,
                 sd_device **ret) {
 
         _cleanup_(sd_event_source_unrefp) sd_event_source *timeout_source = NULL;
@@ -336,6 +352,7 @@ static int wait_for_partition_device(
         _cleanup_(wait_data_done) struct wait_data w = {
                 .parent_device = parent,
                 .blkidp = pp,
+                .uevent_seqnum_not_before = uevent_seqnum_not_before,
         };
 
         r = sd_device_monitor_start(monitor, device_monitor_handler, &w);
@@ -492,6 +509,7 @@ int dissect_image(
                 int fd,
                 const VeritySettings *verity,
                 const MountOptions *mount_options,
+                uint64_t uevent_seqnum_not_before,
                 DissectImageFlags flags,
                 DissectedImage **ret) {
 
@@ -744,7 +762,7 @@ int dissect_image(
                 if (!pp)
                         return errno_or_else(EIO);
 
-                r = wait_for_partition_device(d, pp, deadline, &q);
+                r = wait_for_partition_device(d, pp, deadline, uevent_seqnum_not_before, &q);
                 if (r < 0)
                         return r;
 
@@ -2579,6 +2597,7 @@ int dissect_image_and_warn(
                 const char *name,
                 const VeritySettings *verity,
                 const MountOptions *mount_options,
+                uint64_t uevent_seqnum_not_before,
                 DissectImageFlags flags,
                 DissectedImage **ret) {
 
@@ -2593,7 +2612,7 @@ int dissect_image_and_warn(
                 name = buffer;
         }
 
-        r = dissect_image(fd, verity, mount_options, flags, ret);
+        r = dissect_image(fd, verity, mount_options, uevent_seqnum_not_before, flags, ret);
         switch (r) {
 
         case -EOPNOTSUPP:
@@ -2701,7 +2720,7 @@ int mount_image_privately_interactively(
         if (r < 0)
                 return log_error_errno(r, "Failed to set up loopback device: %m");
 
-        r = dissect_image_and_warn(d->fd, image, &verity, NULL, flags, &dissected_image);
+        r = dissect_image_and_warn(d->fd, image, &verity, NULL, d->uevent_seqnum_not_before, flags, &dissected_image);
         if (r < 0)
                 return r;
 
@@ -2792,6 +2811,7 @@ int verity_dissect_and_mount(
                         loop_device->fd,
                         &verity,
                         options,
+                        loop_device->uevent_seqnum_not_before,
                         dissect_image_flags,
                         &dissected_image);
         /* No partition table? Might be a single-filesystem image, try again */
@@ -2800,7 +2820,8 @@ int verity_dissect_and_mount(
                                 loop_device->fd,
                                 &verity,
                                 options,
-                                dissect_image_flags|DISSECT_IMAGE_NO_PARTITION_TABLE,
+                                loop_device->uevent_seqnum_not_before,
+                                dissect_image_flags | DISSECT_IMAGE_NO_PARTITION_TABLE,
                                 &dissected_image);
         if (r < 0)
                 return log_debug_errno(r, "Failed to dissect image: %m");
index d51049e78a6fc9d0049f4aa158a40873c2bd5b1f..5d0b1d5e65eceb208dfc235725d400e2785d887e 100644 (file)
@@ -159,8 +159,8 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(MountOptions*, mount_options_free_all);
 const char* mount_options_from_designator(const MountOptions *options, PartitionDesignator designator);
 
 int probe_filesystem(const char *node, char **ret_fstype);
-int dissect_image(int fd, const VeritySettings *verity, const MountOptions *mount_options, DissectImageFlags flags, DissectedImage **ret);
-int dissect_image_and_warn(int fd, const char *name, const VeritySettings *verity, const MountOptions *mount_options, DissectImageFlags flags, DissectedImage **ret);
+int dissect_image(int fd, const VeritySettings *verity, const MountOptions *mount_options, uint64_t uevent_seqnum_not_before, DissectImageFlags flags, DissectedImage **ret);
+int dissect_image_and_warn(int fd, const char *name, const VeritySettings *verity, const MountOptions *mount_options, uint64_t uevent_seqnum_not_before, DissectImageFlags flags, DissectedImage **ret);
 
 DissectedImage* dissected_image_unref(DissectedImage *m);
 DEFINE_TRIVIAL_CLEANUP_FUNC(DissectedImage*, dissected_image_unref);
index 49ec23d93430637033a3b915eb2d8b028a8d7bd4..c305a30faef31696048aa2477b59cbb4347ac8bc 100644 (file)
@@ -532,6 +532,7 @@ static int merge_subprocess(Hashmap *images, const char *workspace) {
                                         img->path,
                                         &verity_settings,
                                         NULL,
+                                        d->uevent_seqnum_not_before,
                                         flags,
                                         &m);
                         if (r < 0)
index 93f2da70e77502537f28fbf8efc9e1c9c927129c..cfa999eff746ca41e0bf72869a6f5a21a4a307f0 100644 (file)
@@ -51,7 +51,7 @@ static void* thread_func(void *ptr) {
 
                 log_notice("Acquired loop device %s, will mount on %s", loop->node, mounted);
 
-                r = dissect_image(loop->fd, NULL, NULL, DISSECT_IMAGE_READ_ONLY, &dissected);
+                r = dissect_image(loop->fd, NULL, NULL, loop->uevent_seqnum_not_before, DISSECT_IMAGE_READ_ONLY, &dissected);
                 if (r < 0)
                         log_error_errno(r, "Failed dissect loopback device %s: %m", loop->node);
                 assert_se(r >= 0);
@@ -188,7 +188,7 @@ int main(int argc, char *argv[]) {
         sfdisk = NULL;
 
         assert_se(loop_device_make(fd, O_RDWR, 0, UINT64_MAX, LO_FLAGS_PARTSCAN, &loop) >= 0);
-        assert_se(dissect_image(loop->fd, NULL, NULL, 0, &dissected) >= 0);
+        assert_se(dissect_image(loop->fd, NULL, NULL, loop->uevent_seqnum_not_before, 0, &dissected) >= 0);
 
         assert_se(dissected->partitions[PARTITION_ESP].found);
         assert_se(dissected->partitions[PARTITION_ESP].node);
@@ -212,7 +212,7 @@ int main(int argc, char *argv[]) {
         assert_se(make_filesystem(dissected->partitions[PARTITION_HOME].node, "ext4", "home", id, true) >= 0);
 
         dissected = dissected_image_unref(dissected);
-        assert_se(dissect_image(loop->fd, NULL, NULL, 0, &dissected) >= 0);
+        assert_se(dissect_image(loop->fd, NULL, NULL, loop->uevent_seqnum_not_before, 0, &dissected) >= 0);
 
         assert_se(mkdtemp_malloc(NULL, &mounted) >= 0);