summaryrefslogtreecommitdiff
path: root/drivers/md/dm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/dm.c')
-rw-r--r--drivers/md/dm.c24
1 files changed, 21 insertions, 3 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index e178fe19973e..1334c411c722 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -735,7 +735,16 @@ static struct table_device *open_table_device(struct mapped_device *md,
return ERR_PTR(-ENOMEM);
refcount_set(&td->count, 1);
- bdev_file = bdev_file_open_by_dev(dev, mode, _dm_claim_ptr, NULL);
+ /*
+ * Open the backing device with kernel rather than caller
+ * credentials. Otherwise the caller's credentials would be
+ * pinned in bdev_file->f_cred until the table device is closed.
+ * That would keep the caller's thread keyring alive long beyond the
+ * lifetime of the caller, breaking userspace expectation (e.g.
+ * cryptsetup(8) leaking the LUKS volume key).
+ */
+ scoped_with_kernel_creds()
+ bdev_file = bdev_file_open_by_dev(dev, mode, _dm_claim_ptr, NULL);
if (IS_ERR(bdev_file)) {
r = PTR_ERR(bdev_file);
goto out_free_td;
@@ -2098,8 +2107,17 @@ static bool dm_poll_dm_io(struct dm_io *io, struct io_comp_batch *iob,
WARN_ON_ONCE(!dm_tio_is_normal(&io->tio));
/* don't poll if the mapped io is done */
- if (atomic_read(&io->io_count) > 1)
- bio_poll(&io->tio.clone, iob, flags);
+ if (atomic_read(&io->io_count) > 1) {
+ /*
+ * DM hides the target queues from the upper poller, which may
+ * decide it is safe to spin on a single stacked queue. Do not
+ * pass that spinning policy down to a target queue: one slow
+ * clone could keep the task inside dm_poll_bio() for a long
+ * time. Poll target bios once and let the caller decide
+ * whether to keep polling, reap completions or reschedule.
+ */
+ bio_poll(&io->tio.clone, iob, flags | BLK_POLL_ONESHOT);
+ }
/* bio_poll holds the last reference */
return atomic_read(&io->io_count) == 1;