[PATCH] dm: fix accessing of freed memory in dm_put_live_table_bio

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

 



dm_put_live_table_bio is called from the end of dm_submit_bio. However, at
this point, the bio may be already finished and the caller may have freed
the bio. Consequently, dm_put_live_table_bio accesses the stale "bio"
pointer.

This patch fixes the bug by loading the bi_opf value and passing this
value to dm_get_live_table_bio and dm_put_live_table_bio
instead of the bio.

This bug was found by running the lvm testsuite with kasan.

Signed-off-by: Mikulas Patocka <mpatocka@xxxxxxxxxx>
Fixes: 563a225c9fd20 ("dm: introduce dm_{get,put}_live_table_bio called from dm_submit_bio")

---
 drivers/md/dm.c |   13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

Index: linux-2.6/drivers/md/dm.c
===================================================================
--- linux-2.6.orig/drivers/md/dm.c	2022-06-13 13:01:16.000000000 +0200
+++ linux-2.6/drivers/md/dm.c	2022-06-16 09:20:45.000000000 +0200
@@ -711,18 +711,18 @@ static void dm_put_live_table_fast(struc
 }
 
 static inline struct dm_table *dm_get_live_table_bio(struct mapped_device *md,
-						     int *srcu_idx, struct bio *bio)
+						     int *srcu_idx, unsigned bio_opf)
 {
-	if (bio->bi_opf & REQ_NOWAIT)
+	if (bio_opf & REQ_NOWAIT)
 		return dm_get_live_table_fast(md);
 	else
 		return dm_get_live_table(md, srcu_idx);
 }
 
 static inline void dm_put_live_table_bio(struct mapped_device *md, int srcu_idx,
-					 struct bio *bio)
+					 unsigned bio_opf)
 {
-	if (bio->bi_opf & REQ_NOWAIT)
+	if (bio_opf & REQ_NOWAIT)
 		dm_put_live_table_fast(md);
 	else
 		dm_put_live_table(md, srcu_idx);
@@ -1711,8 +1711,9 @@ static void dm_submit_bio(struct bio *bi
 	struct mapped_device *md = bio->bi_bdev->bd_disk->private_data;
 	int srcu_idx;
 	struct dm_table *map;
+	unsigned bio_opf = bio->bi_opf;
 
-	map = dm_get_live_table_bio(md, &srcu_idx, bio);
+	map = dm_get_live_table_bio(md, &srcu_idx, bio_opf);
 
 	/* If suspended, or map not yet available, queue this IO for later */
 	if (unlikely(test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) ||
@@ -1728,7 +1729,7 @@ static void dm_submit_bio(struct bio *bi
 
 	dm_split_and_process_bio(md, map, bio);
 out:
-	dm_put_live_table_bio(md, srcu_idx, bio);
+	dm_put_live_table_bio(md, srcu_idx, bio_opf);
 }
 
 static bool dm_poll_dm_io(struct dm_io *io, struct io_comp_batch *iob,
--
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