Commit fb8e9ee3 authored by Li Nan's avatar Li Nan
Browse files

md/dm-raid: don't call md_reap_sync_thread() directly

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/?id=cd32b27a66db8776d8b8e82ec7d7dde97a8693b0



--------------------------------

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 130443d6 ("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: be83651f ("DM RAID: Add message/status support for changing sync action")
Cc: stable@vger.kernel.org # v6.7+
Signed-off-by: default avatarYu Kuai <yukuai3@huawei.com>
Signed-off-by: default avatarXiao Ni <xni@redhat.com>
Acked-by: default avatarMike Snitzer <snitzer@kernel.org>
Signed-off-by: default avatarSong 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: default avatarLi Nan <linan122@huawei.com>
parent c96c2b4f
Loading
Loading
Loading
Loading
+5 −9
Original line number Diff line number Diff line
@@ -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 */
+4 −2
Original line number Diff line number Diff line
@@ -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)
+2 −0
Original line number Diff line number Diff line
@@ -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);