diff options
author | Yu Kuai <yukuai3@huawei.com> | 2023-08-08 13:49:12 +0300 |
---|---|---|
committer | Song Liu <song@kernel.org> | 2023-08-15 19:40:27 +0300 |
commit | 0d0bd28c500173bfca78aa840f8f36d261ef1765 (patch) | |
tree | aeac1e3759a484a8586396ed92f80edc76947792 /drivers/md | |
parent | 7b3c70c43c13ad8e59f5561b154663d6bdb77021 (diff) | |
download | linux-0d0bd28c500173bfca78aa840f8f36d261ef1765.tar.xz |
md/raid5-cache: fix null-ptr-deref for r5l_flush_stripe_to_raid()
r5l_flush_stripe_to_raid() will check if the list 'flushing_ios' is
empty, and then submit 'flush_bio', however, r5l_log_flush_endio()
is clearing the list first and then clear the bio, which will cause
null-ptr-deref:
T1: submit flush io
raid5d
handle_active_stripes
r5l_flush_stripe_to_raid
// list is empty
// add 'io_end_ios' to the list
bio_init
submit_bio
// io1
T2: io1 is done
r5l_log_flush_endio
list_splice_tail_init
// clear the list
T3: submit new flush io
...
r5l_flush_stripe_to_raid
// list is empty
// add 'io_end_ios' to the list
bio_init
bio_uninit
// clear bio->bi_blkg
submit_bio
// null-ptr-deref
Fix this problem by clearing bio before clearing the list in
r5l_log_flush_endio().
Fixes: 0dd00cba99c3 ("raid5-cache: fully initialize flush_bio when needed")
Reported-and-tested-by: Corey Hickey <bugfood-ml@fatooh.org>
Closes: https://lore.kernel.org/all/cddd7213-3dfd-4ab7-a3ac-edd54d74a626@fatooh.org/
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Song Liu <song@kernel.org>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/raid5-cache.c | 3 |
1 files changed, 1 insertions, 2 deletions
diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c index a29b9650260a..518b7cfa78b9 100644 --- a/drivers/md/raid5-cache.c +++ b/drivers/md/raid5-cache.c @@ -1260,14 +1260,13 @@ static void r5l_log_flush_endio(struct bio *bio) if (bio->bi_status) md_error(log->rdev->mddev, log->rdev); + bio_uninit(bio); spin_lock_irqsave(&log->io_list_lock, flags); list_for_each_entry(io, &log->flushing_ios, log_sibling) r5l_io_run_stripes(io); list_splice_tail_init(&log->flushing_ios, &log->finished_ios); spin_unlock_irqrestore(&log->io_list_lock, flags); - - bio_uninit(bio); } /* |