Skip to content

Commit 3dc6645

Browse files
committed
md: make rdev_addable usable for rcu mode
JIRA: https://issues.redhat.com/browse/RHEL-94433 CVE: CVE-2025-38621 commit 13017b4 Author: Yang Erkun <yangerkun@huawei.com> Date: Thu Jul 31 19:45:30 2025 +0800 md: make rdev_addable usable for rcu mode Our testcase trigger panic: BUG: kernel NULL pointer dereference, address: 00000000000000e0 ... Oops: Oops: 0000 [#1] SMP NOPTI CPU: 2 UID: 0 PID: 85 Comm: kworker/2:1 Not tainted 6.16.0+ #94 PREEMPT(none) Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.1-2.fc37 04/01/2014 Workqueue: md_misc md_start_sync RIP: 0010:rdev_addable+0x4d/0xf0 ... Call Trace: <TASK> md_start_sync+0x329/0x480 process_one_work+0x226/0x6d0 worker_thread+0x19e/0x340 kthread+0x10f/0x250 ret_from_fork+0x14d/0x180 ret_from_fork_asm+0x1a/0x30 </TASK> Modules linked in: raid10 CR2: 00000000000000e0 ---[ end trace 0000000000000000 ]--- RIP: 0010:rdev_addable+0x4d/0xf0 md_spares_need_change in md_start_sync will call rdev_addable which protected by rcu_read_lock/rcu_read_unlock. This rcu context will help protect rdev won't be released, but rdev->mddev will be set to NULL before we call synchronize_rcu in md_kick_rdev_from_array. Fix this by using READ_ONCE and check does rdev->mddev still alive. Fixes: bc08041 ("md: suspend array in md_start_sync() if array need reconfiguration") Fixes: 570b914 ("md: use RCU lock to protect traversal in md_spares_need_change()") Signed-off-by: Yang Erkun <yangerkun@huawei.com> Link: https://lore.kernel.org/linux-raid/20250731114530.776670-1-yangerkun@huawei.com Signed-off-by: Yu Kuai <yukuai3@huawei.com> Signed-off-by: Nigel Croxon <ncroxon@redhat.com>
1 parent 1d368c1 commit 3dc6645

File tree

1 file changed

+7
-1
lines changed

1 file changed

+7
-1
lines changed

drivers/md/md.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9453,6 +9453,12 @@ static bool rdev_is_spare(struct md_rdev *rdev)
94539453

94549454
static bool rdev_addable(struct md_rdev *rdev)
94559455
{
9456+
struct mddev *mddev;
9457+
9458+
mddev = READ_ONCE(rdev->mddev);
9459+
if (!mddev)
9460+
return false;
9461+
94569462
/* rdev is already used, don't add it again. */
94579463
if (test_bit(Candidate, &rdev->flags) || rdev->raid_disk >= 0 ||
94589464
test_bit(Faulty, &rdev->flags))
@@ -9463,7 +9469,7 @@ static bool rdev_addable(struct md_rdev *rdev)
94639469
return true;
94649470

94659471
/* Allow to add if array is read-write. */
9466-
if (md_is_rdwr(rdev->mddev))
9472+
if (md_is_rdwr(mddev))
94679473
return true;
94689474

94699475
/*

0 commit comments

Comments
 (0)