Commit 34817a24 authored by Li Nan's avatar Li Nan Committed by Song Liu

md/raid10: fix null-ptr-deref of mreplace in raid10_sync_request

There are two check of 'mreplace' in raid10_sync_request(). In the first
check, 'need_replace' will be set and 'mreplace' will be used later if
no-Faulty 'mreplace' exists, In the second check, 'mreplace' will be
set to NULL if it is Faulty, but 'need_replace' will not be changed
accordingly. null-ptr-deref occurs if Faulty is set between two check.

Fix it by merging two checks into one. And replace 'need_replace' with
'mreplace' because their values are always the same.

Fixes: ee37d731 ("md/raid10: Fix raid10 replace hang when new added disk faulty")
Signed-off-by: default avatarLi Nan <linan122@huawei.com>
Reviewed-by: default avatarYu Kuai <yukuai3@huawei.com>
Signed-off-by: default avatarSong Liu <song@kernel.org>
Link: https://lore.kernel.org/r/20230527072218.2365857-2-linan666@huaweicloud.com
parent 75aa7a1b
...@@ -3441,7 +3441,6 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, ...@@ -3441,7 +3441,6 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
int must_sync; int must_sync;
int any_working; int any_working;
int need_recover = 0; int need_recover = 0;
int need_replace = 0;
struct raid10_info *mirror = &conf->mirrors[i]; struct raid10_info *mirror = &conf->mirrors[i];
struct md_rdev *mrdev, *mreplace; struct md_rdev *mrdev, *mreplace;
...@@ -3453,11 +3452,10 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, ...@@ -3453,11 +3452,10 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
!test_bit(Faulty, &mrdev->flags) && !test_bit(Faulty, &mrdev->flags) &&
!test_bit(In_sync, &mrdev->flags)) !test_bit(In_sync, &mrdev->flags))
need_recover = 1; need_recover = 1;
if (mreplace != NULL && if (mreplace && test_bit(Faulty, &mreplace->flags))
!test_bit(Faulty, &mreplace->flags)) mreplace = NULL;
need_replace = 1;
if (!need_recover && !need_replace) { if (!need_recover && !mreplace) {
rcu_read_unlock(); rcu_read_unlock();
continue; continue;
} }
...@@ -3473,8 +3471,6 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, ...@@ -3473,8 +3471,6 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
rcu_read_unlock(); rcu_read_unlock();
continue; continue;
} }
if (mreplace && test_bit(Faulty, &mreplace->flags))
mreplace = NULL;
/* Unless we are doing a full sync, or a replacement /* Unless we are doing a full sync, or a replacement
* we only need to recover the block if it is set in * we only need to recover the block if it is set in
* the bitmap * the bitmap
...@@ -3597,11 +3593,11 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, ...@@ -3597,11 +3593,11 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
bio = r10_bio->devs[1].repl_bio; bio = r10_bio->devs[1].repl_bio;
if (bio) if (bio)
bio->bi_end_io = NULL; bio->bi_end_io = NULL;
/* Note: if need_replace, then bio /* Note: if replace is not NULL, then bio
* cannot be NULL as r10buf_pool_alloc will * cannot be NULL as r10buf_pool_alloc will
* have allocated it. * have allocated it.
*/ */
if (!need_replace) if (!mreplace)
break; break;
bio->bi_next = biolist; bio->bi_next = biolist;
biolist = bio; biolist = bio;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment