mirror of
https://github.com/systemd/systemd.git
synced 2025-03-23 10:50:16 +03:00
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.
This commit is contained in:
parent
31c75fcc41
commit
75dc190d39
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
@ -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 |
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user