Re: [PATCH] Fixes 6890e9b8c7d0a1062bbf4f854b6be3723836ad9a

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The previous patch had a bug when hash verification failed in the
tasklet.  This happened because the tasklet has already advanced the
bvec_iter when it falls back to the work-queue implementation.  When the
work-queue job begins running, it attempts to restart verifiying at
block i, but the bvec_iter is at block i+1.

This causes several failures, the most noticeable is that there are not
enough bytes in the bvec_iter to finish verification.  Since there are
not enough bytes to finish, the work queue gets stuck in an infinite
loop in verity_for_io_block.

To fix this, we can make a local copy of the bvec_iter struct in
verity_verify_io.  This requires that we restart verification from the
first block when deferring to a work-queue rather than starting from the
last block verified in the tasklet.

This patch also fixes what appears to be a memory leak when FEC is
enabled.  The call to verity_fec_init_io should only be made if we are
in a work-queue since a tasklet does not use FEC and is unable to free
the memory.

Signed-off-by: Nathan Huckleberry <nhuck@xxxxxxxxxx>
---
 drivers/md/dm-verity-target.c | 23 ++++++++++++++---------
 drivers/md/dm-verity.h        |  1 -
 2 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c
index 144889ba43ea..0677795454d7 100644
--- a/drivers/md/dm-verity-target.c
+++ b/drivers/md/dm-verity-target.c
@@ -499,17 +499,23 @@ static int verity_verify_io(struct dm_verity_io *io)
 	bool is_zero;
 	struct dm_verity *v = io->v;
 	struct bvec_iter start;
+	/*
+	 * Copy the iterator in case we need to restart verification in a
+	 * work-queue.
+	 */
+	struct bvec_iter iter_copy = io->iter;
 	struct crypto_wait wait;
 	struct bio *bio = dm_bio_from_per_bio_data(io, v->ti->per_io_data_size);
+	unsigned int b;
 
-	for (; io->block_idx < io->n_blocks; io->block_idx++) {
+	for (b = 0; b < io->n_blocks; b++) {
 		int r;
-		sector_t cur_block = io->block + io->block_idx;
+		sector_t cur_block = io->block + b;
 		struct ahash_request *req = verity_io_hash_req(v, io);
 
 		if (v->validated_blocks &&
 		    likely(test_bit(cur_block, v->validated_blocks))) {
-			verity_bv_skip_block(v, io, &io->iter);
+			verity_bv_skip_block(v, io, &iter_copy);
 			continue;
 		}
 
@@ -524,7 +530,7 @@ static int verity_verify_io(struct dm_verity_io *io)
 			 * If we expect a zero block, don't validate, just
 			 * return zeros.
 			 */
-			r = verity_for_bv_block(v, io, &io->iter,
+			r = verity_for_bv_block(v, io, &iter_copy,
 						verity_bv_zero);
 			if (unlikely(r < 0))
 				return r;
@@ -536,8 +542,8 @@ static int verity_verify_io(struct dm_verity_io *io)
 		if (unlikely(r < 0))
 			return r;
 
-		start = io->iter;
-		r = verity_for_io_block(v, io, &io->iter, &wait);
+		start = iter_copy;
+		r = verity_for_io_block(v, io, &iter_copy, &wait);
 		if (unlikely(r < 0))
 			return r;
 
@@ -608,6 +614,8 @@ static void verity_work(struct work_struct *w)
 	struct dm_verity_io *io = container_of(w, struct dm_verity_io, work);
 
 	io->in_tasklet = false;
+	verity_fec_init_io(io);
+
 	verity_finish_io(io, errno_to_blk_status(verity_verify_io(io)));
 }
 
@@ -638,7 +646,6 @@ static void verity_end_io(struct bio *bio)
 		return;
 	}
 
-	io->block_idx = 0;
 	if (static_branch_unlikely(&use_tasklet_enabled) && io->v->use_tasklet) {
 		tasklet_init(&io->tasklet, verity_tasklet, (unsigned long)io);
 		tasklet_schedule(&io->tasklet);
@@ -756,8 +763,6 @@ static int verity_map(struct dm_target *ti, struct bio *bio)
 	bio->bi_private = io;
 	io->iter = bio->bi_iter;
 
-	verity_fec_init_io(io);
-
 	verity_submit_prefetch(v, io);
 
 	submit_bio_noacct(bio);
diff --git a/drivers/md/dm-verity.h b/drivers/md/dm-verity.h
index e73a7972c3e9..fb92b22a6404 100644
--- a/drivers/md/dm-verity.h
+++ b/drivers/md/dm-verity.h
@@ -78,7 +78,6 @@ struct dm_verity_io {
 
 	sector_t block;
 	unsigned n_blocks;
-	unsigned int block_idx;
 	bool in_tasklet;
 
 	struct bvec_iter iter;
-- 
2.37.1.455.g008518b4e5-goog

--
dm-devel mailing list
dm-devel@xxxxxxxxxx
https://listman.redhat.com/mailman/listinfo/dm-devel




[Index of Archives]     [DM Crypt]     [Fedora Desktop]     [ATA RAID]     [Fedora Marketing]     [Fedora Packaging]     [Fedora SELinux]     [Yosemite Discussion]     [KDE Users]     [Fedora Docs]

  Powered by Linux