summaryrefslogtreecommitdiff
path: root/drivers/md
diff options
context:
space:
mode:
authorXiao Ni <xni@redhat.com>2025-10-29 14:34:19 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-12-18 14:02:53 +0100
commitf0fae1debeb9102398ddf2ef69b4f5d395afafed (patch)
tree8779c112a1a5d5d64b473e72183807fbc590881d /drivers/md
parentf98b191f78124405294481dea85f8a22a3eb0a59 (diff)
md: avoid repeated calls to del_gendisk
[ Upstream commit 90e3bb44c0a86e245d8e5c6520206fa113acb1ee ] There is a uaf problem which is found by case 23rdev-lifetime: Oops: general protection fault, probably for non-canonical address 0xdead000000000122 RIP: 0010:bdi_unregister+0x4b/0x170 Call Trace: <TASK> __del_gendisk+0x356/0x3e0 mddev_unlock+0x351/0x360 rdev_attr_store+0x217/0x280 kernfs_fop_write_iter+0x14a/0x210 vfs_write+0x29e/0x550 ksys_write+0x74/0xf0 do_syscall_64+0xbb/0x380 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7ff5250a177e The sequence is: 1. rdev remove path gets reconfig_mutex 2. rdev remove path release reconfig_mutex in mddev_unlock 3. md stop calls do_md_stop and sets MD_DELETED 4. rdev remove path calls del_gendisk because MD_DELETED is set 5. md stop path release reconfig_mutex and calls del_gendisk again So there is a race condition we should resolve. This patch adds a flag MD_DO_DELETE to avoid the race condition. Link: https://lore.kernel.org/linux-raid/20251029063419.21700-1-xni@redhat.com Fixes: 9e59d609763f ("md: call del_gendisk in control path") Signed-off-by: Xiao Ni <xni@redhat.com> Suggested-by: Yu Kuai <yukuai@fnnas.com> Reviewed-by: Li Nan <linan122@huawei.com> Signed-off-by: Yu Kuai <yukuai@fnnas.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/md.c3
-rw-r--r--drivers/md/md.h1
2 files changed, 3 insertions, 1 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 6062e0deb616..5d40beaecc9c 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -941,7 +941,8 @@ void mddev_unlock(struct mddev *mddev)
* do_md_stop. dm raid only uses md_stop to stop. So dm raid
* doesn't need to check MD_DELETED when getting reconfig lock
*/
- if (test_bit(MD_DELETED, &mddev->flags)) {
+ if (test_bit(MD_DELETED, &mddev->flags) &&
+ !test_and_set_bit(MD_DO_DELETE, &mddev->flags)) {
kobject_del(&mddev->kobj);
del_gendisk(mddev->gendisk);
}
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 5d5f780b8447..fd6e001c1d38 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -354,6 +354,7 @@ enum mddev_flags {
MD_HAS_MULTIPLE_PPLS,
MD_NOT_READY,
MD_BROKEN,
+ MD_DO_DELETE,
MD_DELETED,
};