]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dissect: ignore udev database entries from before the loopback attachment
authorLennart Poettering <lennart@poettering.net>
Tue, 20 Apr 2021 14:19:27 +0000 (16:19 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 20 Apr 2021 15:20:38 +0000 (17:20 +0200)
This tries to shorten the race of device reuse a bit more: let's ignore
udev database entries that are older than the time where we started to
use a loopback device.

This doesn't fix the whole loopback device raciness mess, but it makes
the race window a bit shorter.

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 bffcb5ac86e4e79b11e7373a4ba294418091ca70..77fb0d4394c6ed17eab2d1c89ccb1e579560bc0d 100644 (file)
@@ -1864,6 +1864,7 @@ int setup_namespace(
                                 &verity,
                                 root_image_options,
                                 loop_device->uevent_seqnum_not_before,
+                                loop_device->timestamp_not_before,
                                 dissect_image_flags,
                                 &dissected_image);
                 if (r < 0)
index d70f1e791f607e71cfcc4cca8fcfa8bc52d369fd..f1288b41a7264619f95c4f568a46627809c57aeb 100644 (file)
@@ -782,6 +782,7 @@ static int run(int argc, char *argv[]) {
                         &arg_verity_settings,
                         NULL,
                         d->uevent_seqnum_not_before,
+                        d->timestamp_not_before,
                         arg_flags,
                         &m);
         if (r < 0)
index eb80165bbee92581815880e7754d68268cddcb93..d3af81413605ffe2babd3d6c488552a2a0b6c7a9 100644 (file)
@@ -673,6 +673,7 @@ static int enumerate_partitions(dev_t devnum) {
                         fd,
                         NULL, NULL,
                         UINT64_MAX,
+                        USEC_INFINITY,
                         DISSECT_IMAGE_GPT_ONLY|
                         DISSECT_IMAGE_NO_UDEV|
                         DISSECT_IMAGE_USR_NO_ROOT,
index 070160241881360d0d1a636abe71e0655c394716..ed9b31e63ba1219ae5c9d8a7edc72d099c9a0446 100644 (file)
@@ -5484,6 +5484,7 @@ static int run(int argc, char *argv[]) {
                                 &arg_verity_settings,
                                 NULL,
                                 loop->uevent_seqnum_not_before,
+                                loop->timestamp_not_before,
                                 dissect_image_flags,
                                 &dissected_image);
                 if (r == -ENOPKG) {
index 28d884a95139c1788e331a9eccc16327bb9941b6..0799bff53d136d93c718136deb3399b07f91b659 100644 (file)
@@ -396,6 +396,7 @@ static int portable_extract_by_path(
                                 d->fd,
                                 NULL, NULL,
                                 d->uevent_seqnum_not_before,
+                                d->timestamp_not_before,
                                 DISSECT_IMAGE_READ_ONLY |
                                 DISSECT_IMAGE_GENERIC_ROOT |
                                 DISSECT_IMAGE_REQUIRE_ROOT |
index c343d089316e946d38dd2ea178e0fe3a1b0d89ee..8d04ba04fc3dc33f6b1b6e47b1f50bdf3d5b75ef 100644 (file)
@@ -1202,6 +1202,7 @@ int image_read_metadata(Image *i) {
                                 d->fd,
                                 NULL, NULL,
                                 d->uevent_seqnum_not_before,
+                                d->timestamp_not_before,
                                 DISSECT_IMAGE_GENERIC_ROOT |
                                 DISSECT_IMAGE_REQUIRE_ROOT |
                                 DISSECT_IMAGE_RELAX_VAR_CHECK |
index 345e1db9a7def9a089f7f96b678501dbed49bc78..53b613702e1b2c9b3c4c55a032c9984288a28995 100644 (file)
@@ -123,10 +123,6 @@ static int enumerator_for_parent(sd_device *d, sd_device_enumerator **ret) {
         if (r < 0)
                 return r;
 
-        r = sd_device_enumerator_allow_uninitialized(e);
-        if (r < 0)
-                return r;
-
         r = sd_device_enumerator_add_match_subsystem(e, "block", true);
         if (r < 0)
                 return r;
@@ -229,6 +225,7 @@ static int device_is_partition(sd_device *d, sd_device *expected_parent, blkid_p
 static int find_partition(
                 sd_device *parent,
                 blkid_partition pp,
+                usec_t timestamp_not_before,
                 sd_device **ret) {
 
         _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
@@ -244,6 +241,18 @@ static int find_partition(
                 return r;
 
         FOREACH_DEVICE(e, q) {
+                uint64_t usec;
+
+                r = sd_device_get_usec_initialized(q, &usec);
+                if (r == -EBUSY) /* Not initialized yet */
+                        continue;
+                if (r < 0)
+                        return r;
+
+                if (timestamp_not_before != USEC_INFINITY &&
+                    usec < timestamp_not_before) /* udev database entry older than our attachment? Then it's not ours */
+                        continue;
+
                 r = device_is_partition(q, parent, pp);
                 if (r < 0)
                         return r;
@@ -310,6 +319,7 @@ static int wait_for_partition_device(
                 blkid_partition pp,
                 usec_t deadline,
                 uint64_t uevent_seqnum_not_before,
+                usec_t timestamp_not_before,
                 sd_device **ret) {
 
         _cleanup_(sd_event_source_unrefp) sd_event_source *timeout_source = NULL;
@@ -321,7 +331,7 @@ static int wait_for_partition_device(
         assert(pp);
         assert(ret);
 
-        r = find_partition(parent, pp, ret);
+        r = find_partition(parent, pp, timestamp_not_before, ret);
         if (r != -ENXIO)
                 return r;
 
@@ -360,7 +370,7 @@ static int wait_for_partition_device(
                 return r;
 
         /* Check again, the partition might have appeared in the meantime */
-        r = find_partition(parent, pp, ret);
+        r = find_partition(parent, pp, timestamp_not_before, ret);
         if (r != -ENXIO)
                 return r;
 
@@ -510,6 +520,7 @@ int dissect_image(
                 const VeritySettings *verity,
                 const MountOptions *mount_options,
                 uint64_t uevent_seqnum_not_before,
+                usec_t timestamp_not_before,
                 DissectImageFlags flags,
                 DissectedImage **ret) {
 
@@ -762,7 +773,7 @@ int dissect_image(
                 if (!pp)
                         return errno_or_else(EIO);
 
-                r = wait_for_partition_device(d, pp, deadline, uevent_seqnum_not_before, &q);
+                r = wait_for_partition_device(d, pp, deadline, uevent_seqnum_not_before, timestamp_not_before, &q);
                 if (r < 0)
                         return r;
 
@@ -2598,6 +2609,7 @@ int dissect_image_and_warn(
                 const VeritySettings *verity,
                 const MountOptions *mount_options,
                 uint64_t uevent_seqnum_not_before,
+                usec_t timestamp_not_before,
                 DissectImageFlags flags,
                 DissectedImage **ret) {
 
@@ -2612,7 +2624,7 @@ int dissect_image_and_warn(
                 name = buffer;
         }
 
-        r = dissect_image(fd, verity, mount_options, uevent_seqnum_not_before, flags, ret);
+        r = dissect_image(fd, verity, mount_options, uevent_seqnum_not_before, timestamp_not_before, flags, ret);
         switch (r) {
 
         case -EOPNOTSUPP:
@@ -2720,7 +2732,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, d->uevent_seqnum_not_before, flags, &dissected_image);
+        r = dissect_image_and_warn(d->fd, image, &verity, NULL, d->uevent_seqnum_not_before, d->timestamp_not_before, flags, &dissected_image);
         if (r < 0)
                 return r;
 
@@ -2812,6 +2824,7 @@ int verity_dissect_and_mount(
                         &verity,
                         options,
                         loop_device->uevent_seqnum_not_before,
+                        loop_device->timestamp_not_before,
                         dissect_image_flags,
                         &dissected_image);
         /* No partition table? Might be a single-filesystem image, try again */
@@ -2821,6 +2834,7 @@ int verity_dissect_and_mount(
                                 &verity,
                                 options,
                                 loop_device->uevent_seqnum_not_before,
+                                loop_device->timestamp_not_before,
                                 dissect_image_flags | DISSECT_IMAGE_NO_PARTITION_TABLE,
                                 &dissected_image);
         if (r < 0)
index 5d0b1d5e65eceb208dfc235725d400e2785d887e..88106ee4f35ca932c5d4b43a285eaf60cdd56031 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, 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);
+int dissect_image(int fd, const VeritySettings *verity, const MountOptions *mount_options, uint64_t uevent_seqnum_not_before, usec_t timestamp_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, usec_t timestamp_not_before, DissectImageFlags flags, DissectedImage **ret);
 
 DissectedImage* dissected_image_unref(DissectedImage *m);
 DEFINE_TRIVIAL_CLEANUP_FUNC(DissectedImage*, dissected_image_unref);
index c305a30faef31696048aa2477b59cbb4347ac8bc..c5fdf99aa7fa57a31fdb46b55970d27d6dc36219 100644 (file)
@@ -533,6 +533,7 @@ static int merge_subprocess(Hashmap *images, const char *workspace) {
                                         &verity_settings,
                                         NULL,
                                         d->uevent_seqnum_not_before,
+                                        d->timestamp_not_before,
                                         flags,
                                         &m);
                         if (r < 0)
index cfa999eff746ca41e0bf72869a6f5a21a4a307f0..ba44b5f3f91829506accff80c11374b2a4fc8053 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, loop->uevent_seqnum_not_before, DISSECT_IMAGE_READ_ONLY, &dissected);
+                r = dissect_image(loop->fd, NULL, NULL, loop->uevent_seqnum_not_before, loop->timestamp_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, loop->uevent_seqnum_not_before, 0, &dissected) >= 0);
+        assert_se(dissect_image(loop->fd, NULL, NULL, loop->uevent_seqnum_not_before, loop->timestamp_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, loop->uevent_seqnum_not_before, 0, &dissected) >= 0);
+        assert_se(dissect_image(loop->fd, NULL, NULL, loop->uevent_seqnum_not_before, loop->timestamp_not_before, 0, &dissected) >= 0);
 
         assert_se(mkdtemp_malloc(NULL, &mounted) >= 0);