1
0
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:
Lennart Poettering 2021-04-20 15:57:29 +02:00
parent 31c75fcc41
commit 75dc190d39
10 changed files with 39 additions and 10 deletions

View 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)

View 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)

View 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,

View 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) {

View 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 |

View 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;

View 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");

View 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);

View 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)

View 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);