Skip to content

Commit 5d7362d

Browse files
Mikulas PatockaMike Snitzer
authored andcommitted
dm: fix use-after-free in dm_put_live_table_bio
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. Fix this bug by loading the bi_opf value and passing it to dm_get_live_table_bio and dm_put_live_table_bio instead of the bio. This bug was found by running the lvm2 testsuite with kasan. Fixes: 563a225 ("dm: introduce dm_{get,put}_live_table_bio called from dm_submit_bio") Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Mike Snitzer <snitzer@kernel.org>
1 parent 10eb3a0 commit 5d7362d

1 file changed

Lines changed: 7 additions & 6 deletions

File tree

drivers/md/dm.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -715,18 +715,18 @@ static void dm_put_live_table_fast(struct mapped_device *md) __releases(RCU)
715715
}
716716

717717
static inline struct dm_table *dm_get_live_table_bio(struct mapped_device *md,
718-
int *srcu_idx, struct bio *bio)
718+
int *srcu_idx, unsigned bio_opf)
719719
{
720-
if (bio->bi_opf & REQ_NOWAIT)
720+
if (bio_opf & REQ_NOWAIT)
721721
return dm_get_live_table_fast(md);
722722
else
723723
return dm_get_live_table(md, srcu_idx);
724724
}
725725

726726
static inline void dm_put_live_table_bio(struct mapped_device *md, int srcu_idx,
727-
struct bio *bio)
727+
unsigned bio_opf)
728728
{
729-
if (bio->bi_opf & REQ_NOWAIT)
729+
if (bio_opf & REQ_NOWAIT)
730730
dm_put_live_table_fast(md);
731731
else
732732
dm_put_live_table(md, srcu_idx);
@@ -1715,8 +1715,9 @@ static void dm_submit_bio(struct bio *bio)
17151715
struct mapped_device *md = bio->bi_bdev->bd_disk->private_data;
17161716
int srcu_idx;
17171717
struct dm_table *map;
1718+
unsigned bio_opf = bio->bi_opf;
17181719

1719-
map = dm_get_live_table_bio(md, &srcu_idx, bio);
1720+
map = dm_get_live_table_bio(md, &srcu_idx, bio_opf);
17201721

17211722
/* If suspended, or map not yet available, queue this IO for later */
17221723
if (unlikely(test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) ||
@@ -1732,7 +1733,7 @@ static void dm_submit_bio(struct bio *bio)
17321733

17331734
dm_split_and_process_bio(md, map, bio);
17341735
out:
1735-
dm_put_live_table_bio(md, srcu_idx, bio);
1736+
dm_put_live_table_bio(md, srcu_idx, bio_opf);
17361737
}
17371738

17381739
static bool dm_poll_dm_io(struct dm_io *io, struct io_comp_batch *iob,

0 commit comments

Comments
 (0)