Li Nan (2): md/dm-raid: don't call md_reap_sync_thread() directly md/dm-raid: don't clear MD_RECOVERY_FROZEN after setting frozen
drivers/md/md.h | 2 ++ drivers/md/dm-raid.c | 11 ++++------- drivers/md/md.c | 6 ++++-- 3 files changed, 10 insertions(+), 9 deletions(-)
mainline inclusion from mainline-v6.9-rc1 commit cd32b27a66db8776d8b8e82ec7d7dde97a8693b0 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I9Q98W CVE: CVE-2024-35808
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
Currently md_reap_sync_thread() is called from raid_message() directly without holding 'reconfig_mutex', this is definitely unsafe because md_reap_sync_thread() can change many fields that is protected by 'reconfig_mutex'.
However, hold 'reconfig_mutex' here is still problematic because this will cause deadlock, for example, commit 130443d60b1b ("md: refactor idle/frozen_sync_thread() to fix deadlock").
Fix this problem by using stop_sync_thread() to unregister sync_thread, like md/raid did.
Fixes: be83651f0050 ("DM RAID: Add message/status support for changing sync action") Cc: stable@vger.kernel.org # v6.7+ Signed-off-by: Yu Kuai yukuai3@huawei.com Signed-off-by: Xiao Ni xni@redhat.com Acked-by: Mike Snitzer snitzer@kernel.org Signed-off-by: Song Liu song@kernel.org Link: https://lore.kernel.org/r/20240305072306.2562024-7-yukuai1@huaweicloud.com Conflicts: drivers/md/dm-raid.c drivers/md/md.c drivers/md/md.h [ mainline uses new helper exported by commit 7a2347e284d7 ("md: export helpers to stop sync_thread"), just use exist helper and export them here. stop_sync_thread() is changed many times, but doesn't affect the logic of this patch. ] Signed-off-by: Li Nan linan122@huawei.com --- drivers/md/md.h | 2 ++ drivers/md/dm-raid.c | 14 +++++--------- drivers/md/md.c | 6 ++++-- 3 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/md/md.h b/drivers/md/md.h index df78553b4e5a..6eba883eddd6 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -773,6 +773,8 @@ extern void md_rdev_clear(struct md_rdev *rdev); extern void md_handle_request(struct mddev *mddev, struct bio *bio); extern void mddev_suspend(struct mddev *mddev); extern void mddev_resume(struct mddev *mddev); +extern void idle_sync_thread(struct mddev *mddev); +extern void frozen_sync_thread(struct mddev *mddev); extern struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs, struct mddev *mddev);
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index fcdaba156211..3e3d4ed0c087 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c @@ -3684,16 +3684,12 @@ static int raid_message(struct dm_target *ti, unsigned int argc, char **argv, return -EINVAL;
if (!strcasecmp(argv[0], "frozen")) - set_bit(MD_RECOVERY_FROZEN, &mddev->recovery); - else - clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); + frozen_sync_thread(mddev); + else if (!strcasecmp(argv[0], "idle")) + idle_sync_thread(mddev);
- if (!strcasecmp(argv[0], "idle") || !strcasecmp(argv[0], "frozen")) { - if (mddev->sync_thread) { - set_bit(MD_RECOVERY_INTR, &mddev->recovery); - md_reap_sync_thread(mddev); - } - } else if (decipher_sync_action(mddev, mddev->recovery) != st_idle) + clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); + if (decipher_sync_action(mddev, mddev->recovery) != st_idle) return -EBUSY; else if (!strcasecmp(argv[0], "resync")) ; /* MD_RECOVERY_NEEDED set below */ diff --git a/drivers/md/md.c b/drivers/md/md.c index a7faf6153085..6df154ab9802 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -4890,7 +4890,7 @@ static void stop_sync_thread(struct mddev *mddev) mddev_unlock(mddev); }
-static void idle_sync_thread(struct mddev *mddev) +void idle_sync_thread(struct mddev *mddev) { int sync_seq = atomic_read(&mddev->sync_seq);
@@ -4906,8 +4906,9 @@ static void idle_sync_thread(struct mddev *mddev)
mutex_unlock(&mddev->sync_mutex); } +EXPORT_SYMBOL_GPL(idle_sync_thread);
-static void frozen_sync_thread(struct mddev *mddev) +void frozen_sync_thread(struct mddev *mddev) { if (mutex_lock_interruptible(&mddev->sync_mutex)) return; @@ -4920,6 +4921,7 @@ static void frozen_sync_thread(struct mddev *mddev)
mutex_unlock(&mddev->sync_mutex); } +EXPORT_SYMBOL_GPL(frozen_sync_thread);
static ssize_t action_store(struct mddev *mddev, const char *page, size_t len)
hulk inclusion category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I9Q98W CVE: CVE-2024-35808
--------------------------------
MD_RECOVERY_FROZEN should always remain set after array is frozen. But in raid_message(), this flag is cleared soon after frozen. Fix it. This flag will be cleared in md_idle_sync_thread(), there is no need to clear it again for idle.
Fixes: cd32b27a66db ("md/dm-raid: don't call md_reap_sync_thread() directly") Signed-off-by: Li Nan linan122@huawei.com --- drivers/md/dm-raid.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index 3e3d4ed0c087..82ef3cbb8373 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c @@ -3687,8 +3687,9 @@ static int raid_message(struct dm_target *ti, unsigned int argc, char **argv, frozen_sync_thread(mddev); else if (!strcasecmp(argv[0], "idle")) idle_sync_thread(mddev); + else + clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
- clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); if (decipher_sync_action(mddev, mddev->recovery) != st_idle) return -EBUSY; else if (!strcasecmp(argv[0], "resync"))
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/8468 邮件列表地址:https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/G...
FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/8468 Mailing list address: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/G...