From: Lennart Poettering Date: Tue, 20 Apr 2021 13:57:29 +0000 (+0200) Subject: dissect: ignore old uevents when waiting for loopback partition scan X-Git-Tag: v249-rc1~380^2~4 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=75dc190d39bb71428ab0a0e6185af42aef9451a1;p=thirdparty%2Fsystemd.git dissect: ignore old uevents when waiting for loopback partition scan 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. --- diff --git a/src/core/namespace.c b/src/core/namespace.c index 9f9d47d34a2..bffcb5ac86e 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -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) diff --git a/src/dissect/dissect.c b/src/dissect/dissect.c index c21d3e47e40..d70f1e791f6 100644 --- a/src/dissect/dissect.c +++ b/src/dissect/dissect.c @@ -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) diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c index 42549a2cd8c..eb80165bbee 100644 --- a/src/gpt-auto-generator/gpt-auto-generator.c +++ b/src/gpt-auto-generator/gpt-auto-generator.c @@ -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, diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 164a3302072..07016024188 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -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) { diff --git a/src/portable/portable.c b/src/portable/portable.c index e2bce279473..28d884a9513 100644 --- a/src/portable/portable.c +++ b/src/portable/portable.c @@ -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 | diff --git a/src/shared/discover-image.c b/src/shared/discover-image.c index 43138e0a6f6..c343d089316 100644 --- a/src/shared/discover-image.c +++ b/src/shared/discover-image.c @@ -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; diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index f6971038def..345e1db9a7d 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -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"); diff --git a/src/shared/dissect-image.h b/src/shared/dissect-image.h index d51049e78a6..5d0b1d5e65e 100644 --- a/src/shared/dissect-image.h +++ b/src/shared/dissect-image.h @@ -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); diff --git a/src/sysext/sysext.c b/src/sysext/sysext.c index 49ec23d9343..c305a30faef 100644 --- a/src/sysext/sysext.c +++ b/src/sysext/sysext.c @@ -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) diff --git a/src/test/test-loop-block.c b/src/test/test-loop-block.c index 93f2da70e77..cfa999eff74 100644 --- a/src/test/test-loop-block.c +++ b/src/test/test-loop-block.c @@ -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);