+++ /dev/null
-From ff0b64256d28c7fe0d141fbd210bef93233a6461 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 11 Jun 2025 15:31:06 +0800
-Subject: md: call del_gendisk in control path
-
-From: Xiao Ni <xni@redhat.com>
-
-[ Upstream commit 9e59d609763f70a992a8f3808dabcce60f14eb5c ]
-
-Now del_gendisk and put_disk are called asynchronously in workqueue work.
-The asynchronous way has a problem that the device node can still exist
-after mdadm --stop command returns in a short window. So udev rule can
-open this device node and create the struct mddev in kernel again. So put
-del_gendisk in control path and still leave put_disk in md_kobj_release
-to avoid uaf of gendisk.
-
-Function del_gendisk can't be called with reconfig_mutex. If it's called
-with reconfig mutex, a deadlock can happen. del_gendisk waits all sysfs
-files access to finish and sysfs file access waits reconfig mutex. So
-put del_gendisk after releasing reconfig mutex.
-
-But there is still a window that sysfs can be accessed between mddev_unlock
-and del_gendisk. So some actions (add disk, change level, .e.g) can happen
-which lead unexpected results. MD_DELETED is used to resolve this problem.
-MD_DELETED is set before releasing reconfig mutex and it should be checked
-for these sysfs access which need reconfig mutex. For sysfs access which
-don't need reconfig mutex, del_gendisk will wait them to finish.
-
-But it doesn't need to do this in function mddev_lock_nointr. There are
-ten places that call it.
-* Five of them are in dm raid which we don't need to care. MD_DELETED is
-only used for md raid.
-* stop_sync_thread, md_do_sync and md_start_sync are related sync request,
-and it needs to wait sync thread to finish before stopping an array.
-* md_ioctl: md_open is called before md_ioctl, so ->openers is added. It
-will fail to stop the array. So it doesn't need to check MD_DELETED here
-* md_set_readonly:
-It needs to call mddev_set_closing_and_sync_blockdev when setting readonly
-or read_auto. So it will fail to stop the array too because MD_CLOSING is
-already set.
-
-Reviewed-by: Yu Kuai <yukuai3@huawei.com>
-Signed-off-by: Xiao Ni <xni@redhat.com>
-Link: https://lore.kernel.org/linux-raid/20250611073108.25463-2-xni@redhat.com
-Signed-off-by: Yu Kuai <yukuai3@huawei.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/md/md.c | 33 +++++++++++++++++++++++----------
- drivers/md/md.h | 26 ++++++++++++++++++++++++--
- 2 files changed, 47 insertions(+), 12 deletions(-)
-
-diff --git a/drivers/md/md.c b/drivers/md/md.c
-index 4b3291723670..91cece996250 100644
---- a/drivers/md/md.c
-+++ b/drivers/md/md.c
-@@ -619,9 +619,6 @@ static void __mddev_put(struct mddev *mddev)
- mddev->ctime || mddev->hold_active)
- return;
-
-- /* Array is not configured at all, and not held active, so destroy it */
-- set_bit(MD_DELETED, &mddev->flags);
--
- /*
- * Call queue_work inside the spinlock so that flush_workqueue() after
- * mddev_find will succeed in waiting for the work to be done.
-@@ -856,6 +853,16 @@ void mddev_unlock(struct mddev *mddev)
- kobject_del(&rdev->kobj);
- export_rdev(rdev, mddev);
- }
-+
-+ /* Call del_gendisk after release reconfig_mutex to avoid
-+ * deadlock (e.g. call del_gendisk under the lock and an
-+ * access to sysfs files waits the lock)
-+ * And MD_DELETED is only used for md raid which is set in
-+ * 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))
-+ del_gendisk(mddev->gendisk);
- }
- EXPORT_SYMBOL_GPL(mddev_unlock);
-
-@@ -5720,19 +5727,30 @@ md_attr_store(struct kobject *kobj, struct attribute *attr,
- struct md_sysfs_entry *entry = container_of(attr, struct md_sysfs_entry, attr);
- struct mddev *mddev = container_of(kobj, struct mddev, kobj);
- ssize_t rv;
-+ struct kernfs_node *kn = NULL;
-
- if (!entry->store)
- return -EIO;
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
-+
-+ if (entry->store == array_state_store && cmd_match(page, "clear"))
-+ kn = sysfs_break_active_protection(kobj, attr);
-+
- spin_lock(&all_mddevs_lock);
- if (!mddev_get(mddev)) {
- spin_unlock(&all_mddevs_lock);
-+ if (kn)
-+ sysfs_unbreak_active_protection(kn);
- return -EBUSY;
- }
- spin_unlock(&all_mddevs_lock);
- rv = entry->store(mddev, page, length);
- mddev_put(mddev);
-+
-+ if (kn)
-+ sysfs_unbreak_active_protection(kn);
-+
- return rv;
- }
-
-@@ -5740,12 +5758,6 @@ static void md_kobj_release(struct kobject *ko)
- {
- struct mddev *mddev = container_of(ko, struct mddev, kobj);
-
-- if (mddev->sysfs_state)
-- sysfs_put(mddev->sysfs_state);
-- if (mddev->sysfs_level)
-- sysfs_put(mddev->sysfs_level);
--
-- del_gendisk(mddev->gendisk);
- put_disk(mddev->gendisk);
- }
-
-@@ -6601,8 +6613,9 @@ static int do_md_stop(struct mddev *mddev, int mode)
- mddev->bitmap_info.offset = 0;
-
- export_array(mddev);
--
- md_clean(mddev);
-+ set_bit(MD_DELETED, &mddev->flags);
-+
- if (mddev->hold_active == UNTIL_STOP)
- mddev->hold_active = 0;
- }
-diff --git a/drivers/md/md.h b/drivers/md/md.h
-index 8826dce9717d..cf06a9de6f19 100644
---- a/drivers/md/md.h
-+++ b/drivers/md/md.h
-@@ -669,11 +669,26 @@ static inline bool reshape_interrupted(struct mddev *mddev)
-
- static inline int __must_check mddev_lock(struct mddev *mddev)
- {
-- return mutex_lock_interruptible(&mddev->reconfig_mutex);
-+ int ret;
-+
-+ ret = mutex_lock_interruptible(&mddev->reconfig_mutex);
-+
-+ /* MD_DELETED is set in do_md_stop with reconfig_mutex.
-+ * So check it here.
-+ */
-+ if (!ret && test_bit(MD_DELETED, &mddev->flags)) {
-+ ret = -ENODEV;
-+ mutex_unlock(&mddev->reconfig_mutex);
-+ }
-+
-+ return ret;
- }
-
- /* Sometimes we need to take the lock in a situation where
- * failure due to interrupts is not acceptable.
-+ * It doesn't need to check MD_DELETED here, the owner which
-+ * holds the lock here can't be stopped. And all paths can't
-+ * call this function after do_md_stop.
- */
- static inline void mddev_lock_nointr(struct mddev *mddev)
- {
-@@ -682,7 +697,14 @@ static inline void mddev_lock_nointr(struct mddev *mddev)
-
- static inline int mddev_trylock(struct mddev *mddev)
- {
-- return mutex_trylock(&mddev->reconfig_mutex);
-+ int ret;
-+
-+ ret = mutex_trylock(&mddev->reconfig_mutex);
-+ if (!ret && test_bit(MD_DELETED, &mddev->flags)) {
-+ ret = -ENODEV;
-+ mutex_unlock(&mddev->reconfig_mutex);
-+ }
-+ return ret;
- }
- extern void mddev_unlock(struct mddev *mddev);
-
---
-2.39.5
-
+++ /dev/null
-From 880e342d560e6fd3280ec8a359395bcc2f4e1f04 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 11 Jun 2025 15:31:07 +0800
-Subject: md: Don't clear MD_CLOSING until mddev is freed
-
-From: Xiao Ni <xni@redhat.com>
-
-[ Upstream commit 5f286f33553d600e6c2fb5a23dd6afcf99b3ebac ]
-
-UNTIL_STOP is used to avoid mddev is freed on the last close before adding
-disks to mddev. And it should be cleared when stopping an array which is
-mentioned in commit efeb53c0e572 ("md: Allow md devices to be created by
-name."). So reset ->hold_active to 0 in md_clean.
-
-And MD_CLOSING should be kept until mddev is freed to avoid reopen.
-
-Reviewed-by: Yu Kuai <yukuai3@huawei.com>
-Signed-off-by: Xiao Ni <xni@redhat.com>
-Link: https://lore.kernel.org/linux-raid/20250611073108.25463-3-xni@redhat.com
-Signed-off-by: Yu Kuai <yukuai3@huawei.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/md/md.c | 16 ++++------------
- 1 file changed, 4 insertions(+), 12 deletions(-)
-
-diff --git a/drivers/md/md.c b/drivers/md/md.c
-index 91cece996250..6b5b69a7a3f0 100644
---- a/drivers/md/md.c
-+++ b/drivers/md/md.c
-@@ -6380,15 +6380,10 @@ static void md_clean(struct mddev *mddev)
- mddev->persistent = 0;
- mddev->level = LEVEL_NONE;
- mddev->clevel[0] = 0;
-- /*
-- * Don't clear MD_CLOSING, or mddev can be opened again.
-- * 'hold_active != 0' means mddev is still in the creation
-- * process and will be used later.
-- */
-- if (mddev->hold_active)
-- mddev->flags = 0;
-- else
-- mddev->flags &= BIT_ULL_MASK(MD_CLOSING);
-+ /* if UNTIL_STOP is set, it's cleared here */
-+ mddev->hold_active = 0;
-+ /* Don't clear MD_CLOSING, or mddev can be opened again. */
-+ mddev->flags &= BIT_ULL_MASK(MD_CLOSING);
- mddev->sb_flags = 0;
- mddev->ro = MD_RDWR;
- mddev->metadata_type[0] = 0;
-@@ -6615,9 +6610,6 @@ static int do_md_stop(struct mddev *mddev, int mode)
- export_array(mddev);
- md_clean(mddev);
- set_bit(MD_DELETED, &mddev->flags);
--
-- if (mddev->hold_active == UNTIL_STOP)
-- mddev->hold_active = 0;
- }
- md_new_event();
- sysfs_notify_dirent_safe(mddev->sysfs_state);
---
-2.39.5
-
+++ /dev/null
-From 1df1fc845d221eb646539836dbf509eb96b41afd Mon Sep 17 00:00:00 2001
-From: Yu Kuai <yukuai3@huawei.com>
-Date: Wed, 30 Jul 2025 15:33:21 +0800
-Subject: md: fix create on open mddev lifetime regression
-
-From: Yu Kuai <yukuai3@huawei.com>
-
-commit 1df1fc845d221eb646539836dbf509eb96b41afd upstream.
-
-Commit 9e59d609763f ("md: call del_gendisk in control path") moves
-setting MD_DELETED from __mddev_put() to do_md_stop(), however, for the
-case create on open, mddev can be freed without do_md_stop():
-
-1) open
-
-md_probe
- md_alloc_and_put
- md_alloc
- mddev_alloc
- atomic_set(&mddev->active, 1);
- mddev->hold_active = UNTIL_IOCTL
- mddev_put
- atomic_dec_and_test(&mddev->active)
- if (mddev->hold_active)
- -> active is 0, hold_active is set
-md_open
- mddev_get
- atomic_inc(&mddev->active);
-
-2) ioctl that is not STOP_ARRAY, for example, GET_ARRAY_INFO:
-
-md_ioctl
- mddev->hold_active = 0
-
-3) close
-
-md_release
- mddev_put(mddev);
- atomic_dec_and_lock(&mddev->active, &all_mddevs_lock)
- __mddev_put
- -> hold_active is cleared, mddev will be freed
- queue_work(md_misc_wq, &mddev->del_work)
-
-Now that MD_DELETED is not set, before mddev is freed by
-mddev_delayed_delete(), md_open can still succeed and break mddev
-lifetime, causing mddev->kobj refcount underflow or mddev uaf
-problem.
-
-Fix this problem by setting MD_DELETED before queuing del_work.
-
-Reported-by: syzbot+9921e319bd6168140b40@syzkaller.appspotmail.com
-Closes: https://lore.kernel.org/all/68894408.a00a0220.26d0e1.0012.GAE@google.com/
-Reported-by: syzbot+fa3a12519f0d3fd4ec16@syzkaller.appspotmail.com
-Closes: https://lore.kernel.org/all/68894408.a00a0220.26d0e1.0013.GAE@google.com/
-Fixes: 9e59d609763f ("md: call del_gendisk in control path")
-Link: https://lore.kernel.org/linux-raid/20250730073321.2583158-1-yukuai1@huaweicloud.com
-Signed-off-by: Yu Kuai <yukuai3@huawei.com>
-Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
-Reviewed-by: Xiao Ni <xni@redhat.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/md/md.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
---- a/drivers/md/md.c
-+++ b/drivers/md/md.c
-@@ -620,6 +620,12 @@ static void __mddev_put(struct mddev *md
- return;
-
- /*
-+ * If array is freed by stopping array, MD_DELETED is set by
-+ * do_md_stop(), MD_DELETED is still set here in case mddev is freed
-+ * directly by closing a mddev that is created by create_on_open.
-+ */
-+ set_bit(MD_DELETED, &mddev->flags);
-+ /*
- * Call queue_work inside the spinlock so that flush_workqueue() after
- * mddev_find will succeed in waiting for the work to be done.
- */
nvme-tcp-log-tls-handshake-failures-at-error-level.patch
gfs2-validate-i_depth-for-exhash-directories.patch
gfs2-set-.migrate_folio-in-gfs2_-rgrp-meta-_aops.patch
-md-call-del_gendisk-in-control-path.patch
loop-avoid-updating-block-size-under-exclusive-owner.patch
udf-verify-partition-map-count.patch
drbd-add-missing-kref_get-in-handle_write_conflicts.patch
ata-libata-sata-disallow-changing-lpm-state-if-not-s.patch
fs-ntfs3-add-sanity-check-for-file-name.patch
fs-ntfs3-correctly-create-symlink-for-relative-path.patch
-md-don-t-clear-md_closing-until-mddev-is-freed.patch
pidfs-raise-sb_i_nodev-and-sb_i_noexec.patch
ext2-handle-fiemap-on-empty-files-to-prevent-einval.patch
fix-locking-in-efi_secret_unlink.patch
io_uring-rw-cast-rw-flags-assignment-to-rwf_t.patch
firmware-arm_scmi-convert-to-system_sleep_pm_ops.patch
drm-amd-display-allow-dcn301-to-clear-update-flags.patch
-md-fix-create-on-open-mddev-lifetime-regression.patch
rcu-fix-racy-re-initialization-of-irq_work-causing-hangs.patch
dm-split-write-bios-on-zone-boundaries-when-zone-append-is-not-emulated.patch
pci-honor-max-link-speed-when-determining-supported-speeds.patch
+++ /dev/null
-From b47c5676ac28d0b0ce7e97be53bba3c761ab7552 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 11 Jun 2025 15:31:06 +0800
-Subject: md: call del_gendisk in control path
-
-From: Xiao Ni <xni@redhat.com>
-
-[ Upstream commit 9e59d609763f70a992a8f3808dabcce60f14eb5c ]
-
-Now del_gendisk and put_disk are called asynchronously in workqueue work.
-The asynchronous way has a problem that the device node can still exist
-after mdadm --stop command returns in a short window. So udev rule can
-open this device node and create the struct mddev in kernel again. So put
-del_gendisk in control path and still leave put_disk in md_kobj_release
-to avoid uaf of gendisk.
-
-Function del_gendisk can't be called with reconfig_mutex. If it's called
-with reconfig mutex, a deadlock can happen. del_gendisk waits all sysfs
-files access to finish and sysfs file access waits reconfig mutex. So
-put del_gendisk after releasing reconfig mutex.
-
-But there is still a window that sysfs can be accessed between mddev_unlock
-and del_gendisk. So some actions (add disk, change level, .e.g) can happen
-which lead unexpected results. MD_DELETED is used to resolve this problem.
-MD_DELETED is set before releasing reconfig mutex and it should be checked
-for these sysfs access which need reconfig mutex. For sysfs access which
-don't need reconfig mutex, del_gendisk will wait them to finish.
-
-But it doesn't need to do this in function mddev_lock_nointr. There are
-ten places that call it.
-* Five of them are in dm raid which we don't need to care. MD_DELETED is
-only used for md raid.
-* stop_sync_thread, md_do_sync and md_start_sync are related sync request,
-and it needs to wait sync thread to finish before stopping an array.
-* md_ioctl: md_open is called before md_ioctl, so ->openers is added. It
-will fail to stop the array. So it doesn't need to check MD_DELETED here
-* md_set_readonly:
-It needs to call mddev_set_closing_and_sync_blockdev when setting readonly
-or read_auto. So it will fail to stop the array too because MD_CLOSING is
-already set.
-
-Reviewed-by: Yu Kuai <yukuai3@huawei.com>
-Signed-off-by: Xiao Ni <xni@redhat.com>
-Link: https://lore.kernel.org/linux-raid/20250611073108.25463-2-xni@redhat.com
-Signed-off-by: Yu Kuai <yukuai3@huawei.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/md/md.c | 33 +++++++++++++++++++++++----------
- drivers/md/md.h | 26 ++++++++++++++++++++++++--
- 2 files changed, 47 insertions(+), 12 deletions(-)
-
-diff --git a/drivers/md/md.c b/drivers/md/md.c
-index 47f3253c4757..aa053bb818bc 100644
---- a/drivers/md/md.c
-+++ b/drivers/md/md.c
-@@ -613,9 +613,6 @@ static void __mddev_put(struct mddev *mddev)
- mddev->ctime || mddev->hold_active)
- return;
-
-- /* Array is not configured at all, and not held active, so destroy it */
-- set_bit(MD_DELETED, &mddev->flags);
--
- /*
- * Call queue_work inside the spinlock so that flush_workqueue() after
- * mddev_find will succeed in waiting for the work to be done.
-@@ -850,6 +847,16 @@ void mddev_unlock(struct mddev *mddev)
- kobject_del(&rdev->kobj);
- export_rdev(rdev, mddev);
- }
-+
-+ /* Call del_gendisk after release reconfig_mutex to avoid
-+ * deadlock (e.g. call del_gendisk under the lock and an
-+ * access to sysfs files waits the lock)
-+ * And MD_DELETED is only used for md raid which is set in
-+ * 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))
-+ del_gendisk(mddev->gendisk);
- }
- EXPORT_SYMBOL_GPL(mddev_unlock);
-
-@@ -5721,19 +5728,30 @@ md_attr_store(struct kobject *kobj, struct attribute *attr,
- struct md_sysfs_entry *entry = container_of(attr, struct md_sysfs_entry, attr);
- struct mddev *mddev = container_of(kobj, struct mddev, kobj);
- ssize_t rv;
-+ struct kernfs_node *kn = NULL;
-
- if (!entry->store)
- return -EIO;
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
-+
-+ if (entry->store == array_state_store && cmd_match(page, "clear"))
-+ kn = sysfs_break_active_protection(kobj, attr);
-+
- spin_lock(&all_mddevs_lock);
- if (!mddev_get(mddev)) {
- spin_unlock(&all_mddevs_lock);
-+ if (kn)
-+ sysfs_unbreak_active_protection(kn);
- return -EBUSY;
- }
- spin_unlock(&all_mddevs_lock);
- rv = entry->store(mddev, page, length);
- mddev_put(mddev);
-+
-+ if (kn)
-+ sysfs_unbreak_active_protection(kn);
-+
- return rv;
- }
-
-@@ -5741,12 +5759,6 @@ static void md_kobj_release(struct kobject *ko)
- {
- struct mddev *mddev = container_of(ko, struct mddev, kobj);
-
-- if (mddev->sysfs_state)
-- sysfs_put(mddev->sysfs_state);
-- if (mddev->sysfs_level)
-- sysfs_put(mddev->sysfs_level);
--
-- del_gendisk(mddev->gendisk);
- put_disk(mddev->gendisk);
- }
-
-@@ -6593,8 +6605,9 @@ static int do_md_stop(struct mddev *mddev, int mode)
- mddev->bitmap_info.offset = 0;
-
- export_array(mddev);
--
- md_clean(mddev);
-+ set_bit(MD_DELETED, &mddev->flags);
-+
- if (mddev->hold_active == UNTIL_STOP)
- mddev->hold_active = 0;
- }
-diff --git a/drivers/md/md.h b/drivers/md/md.h
-index 1cf00a04bcdd..b851fc0dc085 100644
---- a/drivers/md/md.h
-+++ b/drivers/md/md.h
-@@ -697,11 +697,26 @@ static inline bool reshape_interrupted(struct mddev *mddev)
-
- static inline int __must_check mddev_lock(struct mddev *mddev)
- {
-- return mutex_lock_interruptible(&mddev->reconfig_mutex);
-+ int ret;
-+
-+ ret = mutex_lock_interruptible(&mddev->reconfig_mutex);
-+
-+ /* MD_DELETED is set in do_md_stop with reconfig_mutex.
-+ * So check it here.
-+ */
-+ if (!ret && test_bit(MD_DELETED, &mddev->flags)) {
-+ ret = -ENODEV;
-+ mutex_unlock(&mddev->reconfig_mutex);
-+ }
-+
-+ return ret;
- }
-
- /* Sometimes we need to take the lock in a situation where
- * failure due to interrupts is not acceptable.
-+ * It doesn't need to check MD_DELETED here, the owner which
-+ * holds the lock here can't be stopped. And all paths can't
-+ * call this function after do_md_stop.
- */
- static inline void mddev_lock_nointr(struct mddev *mddev)
- {
-@@ -710,7 +725,14 @@ static inline void mddev_lock_nointr(struct mddev *mddev)
-
- static inline int mddev_trylock(struct mddev *mddev)
- {
-- return mutex_trylock(&mddev->reconfig_mutex);
-+ int ret;
-+
-+ ret = mutex_trylock(&mddev->reconfig_mutex);
-+ if (!ret && test_bit(MD_DELETED, &mddev->flags)) {
-+ ret = -ENODEV;
-+ mutex_unlock(&mddev->reconfig_mutex);
-+ }
-+ return ret;
- }
- extern void mddev_unlock(struct mddev *mddev);
-
---
-2.39.5
-
+++ /dev/null
-From 5f84794f063aaab62d86317011de7cc392c66111 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 11 Jun 2025 15:31:07 +0800
-Subject: md: Don't clear MD_CLOSING until mddev is freed
-
-From: Xiao Ni <xni@redhat.com>
-
-[ Upstream commit 5f286f33553d600e6c2fb5a23dd6afcf99b3ebac ]
-
-UNTIL_STOP is used to avoid mddev is freed on the last close before adding
-disks to mddev. And it should be cleared when stopping an array which is
-mentioned in commit efeb53c0e572 ("md: Allow md devices to be created by
-name."). So reset ->hold_active to 0 in md_clean.
-
-And MD_CLOSING should be kept until mddev is freed to avoid reopen.
-
-Reviewed-by: Yu Kuai <yukuai3@huawei.com>
-Signed-off-by: Xiao Ni <xni@redhat.com>
-Link: https://lore.kernel.org/linux-raid/20250611073108.25463-3-xni@redhat.com
-Signed-off-by: Yu Kuai <yukuai3@huawei.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/md/md.c | 16 ++++------------
- 1 file changed, 4 insertions(+), 12 deletions(-)
-
-diff --git a/drivers/md/md.c b/drivers/md/md.c
-index aa053bb818bc..13a6287e7415 100644
---- a/drivers/md/md.c
-+++ b/drivers/md/md.c
-@@ -6372,15 +6372,10 @@ static void md_clean(struct mddev *mddev)
- mddev->persistent = 0;
- mddev->level = LEVEL_NONE;
- mddev->clevel[0] = 0;
-- /*
-- * Don't clear MD_CLOSING, or mddev can be opened again.
-- * 'hold_active != 0' means mddev is still in the creation
-- * process and will be used later.
-- */
-- if (mddev->hold_active)
-- mddev->flags = 0;
-- else
-- mddev->flags &= BIT_ULL_MASK(MD_CLOSING);
-+ /* if UNTIL_STOP is set, it's cleared here */
-+ mddev->hold_active = 0;
-+ /* Don't clear MD_CLOSING, or mddev can be opened again. */
-+ mddev->flags &= BIT_ULL_MASK(MD_CLOSING);
- mddev->sb_flags = 0;
- mddev->ro = MD_RDWR;
- mddev->metadata_type[0] = 0;
-@@ -6607,9 +6602,6 @@ static int do_md_stop(struct mddev *mddev, int mode)
- export_array(mddev);
- md_clean(mddev);
- set_bit(MD_DELETED, &mddev->flags);
--
-- if (mddev->hold_active == UNTIL_STOP)
-- mddev->hold_active = 0;
- }
- md_new_event();
- sysfs_notify_dirent_safe(mddev->sysfs_state);
---
-2.39.5
-
+++ /dev/null
-From 1df1fc845d221eb646539836dbf509eb96b41afd Mon Sep 17 00:00:00 2001
-From: Yu Kuai <yukuai3@huawei.com>
-Date: Wed, 30 Jul 2025 15:33:21 +0800
-Subject: md: fix create on open mddev lifetime regression
-
-From: Yu Kuai <yukuai3@huawei.com>
-
-commit 1df1fc845d221eb646539836dbf509eb96b41afd upstream.
-
-Commit 9e59d609763f ("md: call del_gendisk in control path") moves
-setting MD_DELETED from __mddev_put() to do_md_stop(), however, for the
-case create on open, mddev can be freed without do_md_stop():
-
-1) open
-
-md_probe
- md_alloc_and_put
- md_alloc
- mddev_alloc
- atomic_set(&mddev->active, 1);
- mddev->hold_active = UNTIL_IOCTL
- mddev_put
- atomic_dec_and_test(&mddev->active)
- if (mddev->hold_active)
- -> active is 0, hold_active is set
-md_open
- mddev_get
- atomic_inc(&mddev->active);
-
-2) ioctl that is not STOP_ARRAY, for example, GET_ARRAY_INFO:
-
-md_ioctl
- mddev->hold_active = 0
-
-3) close
-
-md_release
- mddev_put(mddev);
- atomic_dec_and_lock(&mddev->active, &all_mddevs_lock)
- __mddev_put
- -> hold_active is cleared, mddev will be freed
- queue_work(md_misc_wq, &mddev->del_work)
-
-Now that MD_DELETED is not set, before mddev is freed by
-mddev_delayed_delete(), md_open can still succeed and break mddev
-lifetime, causing mddev->kobj refcount underflow or mddev uaf
-problem.
-
-Fix this problem by setting MD_DELETED before queuing del_work.
-
-Reported-by: syzbot+9921e319bd6168140b40@syzkaller.appspotmail.com
-Closes: https://lore.kernel.org/all/68894408.a00a0220.26d0e1.0012.GAE@google.com/
-Reported-by: syzbot+fa3a12519f0d3fd4ec16@syzkaller.appspotmail.com
-Closes: https://lore.kernel.org/all/68894408.a00a0220.26d0e1.0013.GAE@google.com/
-Fixes: 9e59d609763f ("md: call del_gendisk in control path")
-Link: https://lore.kernel.org/linux-raid/20250730073321.2583158-1-yukuai1@huaweicloud.com
-Signed-off-by: Yu Kuai <yukuai3@huawei.com>
-Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
-Reviewed-by: Xiao Ni <xni@redhat.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/md/md.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
---- a/drivers/md/md.c
-+++ b/drivers/md/md.c
-@@ -614,6 +614,12 @@ static void __mddev_put(struct mddev *md
- return;
-
- /*
-+ * If array is freed by stopping array, MD_DELETED is set by
-+ * do_md_stop(), MD_DELETED is still set here in case mddev is freed
-+ * directly by closing a mddev that is created by create_on_open.
-+ */
-+ set_bit(MD_DELETED, &mddev->flags);
-+ /*
- * Call queue_work inside the spinlock so that flush_workqueue() after
- * mddev_find will succeed in waiting for the work to be done.
- */
nvme-tcp-log-tls-handshake-failures-at-error-level.patch
gfs2-validate-i_depth-for-exhash-directories.patch
gfs2-set-.migrate_folio-in-gfs2_-rgrp-meta-_aops.patch
-md-call-del_gendisk-in-control-path.patch
loop-avoid-updating-block-size-under-exclusive-owner.patch
udf-verify-partition-map-count.patch
drbd-add-missing-kref_get-in-handle_write_conflicts.patch
ata-libata-sata-disallow-changing-lpm-state-if-not-s.patch
fs-ntfs3-add-sanity-check-for-file-name.patch
fs-ntfs3-correctly-create-symlink-for-relative-path.patch
-md-don-t-clear-md_closing-until-mddev-is-freed.patch
pidfs-raise-sb_i_nodev-and-sb_i_noexec.patch
landlock-opened-file-never-has-a-negative-dentry.patch
ext2-handle-fiemap-on-empty-files-to-prevent-einval.patch
io_uring-rw-cast-rw-flags-assignment-to-rwf_t.patch
firmware-arm_scmi-convert-to-system_sleep_pm_ops.patch
drm-amd-display-allow-dcn301-to-clear-update-flags.patch
-md-fix-create-on-open-mddev-lifetime-regression.patch
rcu-fix-racy-re-initialization-of-irq_work-causing-hangs.patch
dm-split-write-bios-on-zone-boundaries-when-zone-append-is-not-emulated.patch
+++ /dev/null
-From bbd219cd5c5f8380c07ab02a591bd0c557d43c86 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 11 Jun 2025 15:31:06 +0800
-Subject: md: call del_gendisk in control path
-
-From: Xiao Ni <xni@redhat.com>
-
-[ Upstream commit 9e59d609763f70a992a8f3808dabcce60f14eb5c ]
-
-Now del_gendisk and put_disk are called asynchronously in workqueue work.
-The asynchronous way has a problem that the device node can still exist
-after mdadm --stop command returns in a short window. So udev rule can
-open this device node and create the struct mddev in kernel again. So put
-del_gendisk in control path and still leave put_disk in md_kobj_release
-to avoid uaf of gendisk.
-
-Function del_gendisk can't be called with reconfig_mutex. If it's called
-with reconfig mutex, a deadlock can happen. del_gendisk waits all sysfs
-files access to finish and sysfs file access waits reconfig mutex. So
-put del_gendisk after releasing reconfig mutex.
-
-But there is still a window that sysfs can be accessed between mddev_unlock
-and del_gendisk. So some actions (add disk, change level, .e.g) can happen
-which lead unexpected results. MD_DELETED is used to resolve this problem.
-MD_DELETED is set before releasing reconfig mutex and it should be checked
-for these sysfs access which need reconfig mutex. For sysfs access which
-don't need reconfig mutex, del_gendisk will wait them to finish.
-
-But it doesn't need to do this in function mddev_lock_nointr. There are
-ten places that call it.
-* Five of them are in dm raid which we don't need to care. MD_DELETED is
-only used for md raid.
-* stop_sync_thread, md_do_sync and md_start_sync are related sync request,
-and it needs to wait sync thread to finish before stopping an array.
-* md_ioctl: md_open is called before md_ioctl, so ->openers is added. It
-will fail to stop the array. So it doesn't need to check MD_DELETED here
-* md_set_readonly:
-It needs to call mddev_set_closing_and_sync_blockdev when setting readonly
-or read_auto. So it will fail to stop the array too because MD_CLOSING is
-already set.
-
-Reviewed-by: Yu Kuai <yukuai3@huawei.com>
-Signed-off-by: Xiao Ni <xni@redhat.com>
-Link: https://lore.kernel.org/linux-raid/20250611073108.25463-2-xni@redhat.com
-Signed-off-by: Yu Kuai <yukuai3@huawei.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/md/md.c | 33 +++++++++++++++++++++++----------
- drivers/md/md.h | 26 ++++++++++++++++++++++++--
- 2 files changed, 47 insertions(+), 12 deletions(-)
-
-diff --git a/drivers/md/md.c b/drivers/md/md.c
-index 10670c62b09e..c16c7feb6034 100644
---- a/drivers/md/md.c
-+++ b/drivers/md/md.c
-@@ -636,9 +636,6 @@ static void __mddev_put(struct mddev *mddev)
- mddev->ctime || mddev->hold_active)
- return;
-
-- /* Array is not configured at all, and not held active, so destroy it */
-- set_bit(MD_DELETED, &mddev->flags);
--
- /*
- * Call queue_work inside the spinlock so that flush_workqueue() after
- * mddev_find will succeed in waiting for the work to be done.
-@@ -873,6 +870,16 @@ void mddev_unlock(struct mddev *mddev)
- kobject_del(&rdev->kobj);
- export_rdev(rdev, mddev);
- }
-+
-+ /* Call del_gendisk after release reconfig_mutex to avoid
-+ * deadlock (e.g. call del_gendisk under the lock and an
-+ * access to sysfs files waits the lock)
-+ * And MD_DELETED is only used for md raid which is set in
-+ * 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))
-+ del_gendisk(mddev->gendisk);
- }
- EXPORT_SYMBOL_GPL(mddev_unlock);
-
-@@ -5774,19 +5781,30 @@ md_attr_store(struct kobject *kobj, struct attribute *attr,
- struct md_sysfs_entry *entry = container_of(attr, struct md_sysfs_entry, attr);
- struct mddev *mddev = container_of(kobj, struct mddev, kobj);
- ssize_t rv;
-+ struct kernfs_node *kn = NULL;
-
- if (!entry->store)
- return -EIO;
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
-+
-+ if (entry->store == array_state_store && cmd_match(page, "clear"))
-+ kn = sysfs_break_active_protection(kobj, attr);
-+
- spin_lock(&all_mddevs_lock);
- if (!mddev_get(mddev)) {
- spin_unlock(&all_mddevs_lock);
-+ if (kn)
-+ sysfs_unbreak_active_protection(kn);
- return -EBUSY;
- }
- spin_unlock(&all_mddevs_lock);
- rv = entry->store(mddev, page, length);
- mddev_put(mddev);
-+
-+ if (kn)
-+ sysfs_unbreak_active_protection(kn);
-+
- return rv;
- }
-
-@@ -5794,12 +5812,6 @@ static void md_kobj_release(struct kobject *ko)
- {
- struct mddev *mddev = container_of(ko, struct mddev, kobj);
-
-- if (mddev->sysfs_state)
-- sysfs_put(mddev->sysfs_state);
-- if (mddev->sysfs_level)
-- sysfs_put(mddev->sysfs_level);
--
-- del_gendisk(mddev->gendisk);
- put_disk(mddev->gendisk);
- }
-
-@@ -6646,8 +6658,9 @@ static int do_md_stop(struct mddev *mddev, int mode)
- mddev->bitmap_info.offset = 0;
-
- export_array(mddev);
--
- md_clean(mddev);
-+ set_bit(MD_DELETED, &mddev->flags);
-+
- if (mddev->hold_active == UNTIL_STOP)
- mddev->hold_active = 0;
- }
-diff --git a/drivers/md/md.h b/drivers/md/md.h
-index d45a9e6ead80..67b365621507 100644
---- a/drivers/md/md.h
-+++ b/drivers/md/md.h
-@@ -700,11 +700,26 @@ static inline bool reshape_interrupted(struct mddev *mddev)
-
- static inline int __must_check mddev_lock(struct mddev *mddev)
- {
-- return mutex_lock_interruptible(&mddev->reconfig_mutex);
-+ int ret;
-+
-+ ret = mutex_lock_interruptible(&mddev->reconfig_mutex);
-+
-+ /* MD_DELETED is set in do_md_stop with reconfig_mutex.
-+ * So check it here.
-+ */
-+ if (!ret && test_bit(MD_DELETED, &mddev->flags)) {
-+ ret = -ENODEV;
-+ mutex_unlock(&mddev->reconfig_mutex);
-+ }
-+
-+ return ret;
- }
-
- /* Sometimes we need to take the lock in a situation where
- * failure due to interrupts is not acceptable.
-+ * It doesn't need to check MD_DELETED here, the owner which
-+ * holds the lock here can't be stopped. And all paths can't
-+ * call this function after do_md_stop.
- */
- static inline void mddev_lock_nointr(struct mddev *mddev)
- {
-@@ -713,7 +728,14 @@ static inline void mddev_lock_nointr(struct mddev *mddev)
-
- static inline int mddev_trylock(struct mddev *mddev)
- {
-- return mutex_trylock(&mddev->reconfig_mutex);
-+ int ret;
-+
-+ ret = mutex_trylock(&mddev->reconfig_mutex);
-+ if (!ret && test_bit(MD_DELETED, &mddev->flags)) {
-+ ret = -ENODEV;
-+ mutex_unlock(&mddev->reconfig_mutex);
-+ }
-+ return ret;
- }
- extern void mddev_unlock(struct mddev *mddev);
-
---
-2.39.5
-
+++ /dev/null
-From 2c6366ab6d14425f251da6bccb6f1dde7ed2459a Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 11 Jun 2025 15:31:07 +0800
-Subject: md: Don't clear MD_CLOSING until mddev is freed
-
-From: Xiao Ni <xni@redhat.com>
-
-[ Upstream commit 5f286f33553d600e6c2fb5a23dd6afcf99b3ebac ]
-
-UNTIL_STOP is used to avoid mddev is freed on the last close before adding
-disks to mddev. And it should be cleared when stopping an array which is
-mentioned in commit efeb53c0e572 ("md: Allow md devices to be created by
-name."). So reset ->hold_active to 0 in md_clean.
-
-And MD_CLOSING should be kept until mddev is freed to avoid reopen.
-
-Reviewed-by: Yu Kuai <yukuai3@huawei.com>
-Signed-off-by: Xiao Ni <xni@redhat.com>
-Link: https://lore.kernel.org/linux-raid/20250611073108.25463-3-xni@redhat.com
-Signed-off-by: Yu Kuai <yukuai3@huawei.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/md/md.c | 16 ++++------------
- 1 file changed, 4 insertions(+), 12 deletions(-)
-
-diff --git a/drivers/md/md.c b/drivers/md/md.c
-index c16c7feb6034..81d786a3851b 100644
---- a/drivers/md/md.c
-+++ b/drivers/md/md.c
-@@ -6425,15 +6425,10 @@ static void md_clean(struct mddev *mddev)
- mddev->persistent = 0;
- mddev->level = LEVEL_NONE;
- mddev->clevel[0] = 0;
-- /*
-- * Don't clear MD_CLOSING, or mddev can be opened again.
-- * 'hold_active != 0' means mddev is still in the creation
-- * process and will be used later.
-- */
-- if (mddev->hold_active)
-- mddev->flags = 0;
-- else
-- mddev->flags &= BIT_ULL_MASK(MD_CLOSING);
-+ /* if UNTIL_STOP is set, it's cleared here */
-+ mddev->hold_active = 0;
-+ /* Don't clear MD_CLOSING, or mddev can be opened again. */
-+ mddev->flags &= BIT_ULL_MASK(MD_CLOSING);
- mddev->sb_flags = 0;
- mddev->ro = MD_RDWR;
- mddev->metadata_type[0] = 0;
-@@ -6660,9 +6655,6 @@ static int do_md_stop(struct mddev *mddev, int mode)
- export_array(mddev);
- md_clean(mddev);
- set_bit(MD_DELETED, &mddev->flags);
--
-- if (mddev->hold_active == UNTIL_STOP)
-- mddev->hold_active = 0;
- }
- md_new_event();
- sysfs_notify_dirent_safe(mddev->sysfs_state);
---
-2.39.5
-
+++ /dev/null
-From 1df1fc845d221eb646539836dbf509eb96b41afd Mon Sep 17 00:00:00 2001
-From: Yu Kuai <yukuai3@huawei.com>
-Date: Wed, 30 Jul 2025 15:33:21 +0800
-Subject: md: fix create on open mddev lifetime regression
-
-From: Yu Kuai <yukuai3@huawei.com>
-
-commit 1df1fc845d221eb646539836dbf509eb96b41afd upstream.
-
-Commit 9e59d609763f ("md: call del_gendisk in control path") moves
-setting MD_DELETED from __mddev_put() to do_md_stop(), however, for the
-case create on open, mddev can be freed without do_md_stop():
-
-1) open
-
-md_probe
- md_alloc_and_put
- md_alloc
- mddev_alloc
- atomic_set(&mddev->active, 1);
- mddev->hold_active = UNTIL_IOCTL
- mddev_put
- atomic_dec_and_test(&mddev->active)
- if (mddev->hold_active)
- -> active is 0, hold_active is set
-md_open
- mddev_get
- atomic_inc(&mddev->active);
-
-2) ioctl that is not STOP_ARRAY, for example, GET_ARRAY_INFO:
-
-md_ioctl
- mddev->hold_active = 0
-
-3) close
-
-md_release
- mddev_put(mddev);
- atomic_dec_and_lock(&mddev->active, &all_mddevs_lock)
- __mddev_put
- -> hold_active is cleared, mddev will be freed
- queue_work(md_misc_wq, &mddev->del_work)
-
-Now that MD_DELETED is not set, before mddev is freed by
-mddev_delayed_delete(), md_open can still succeed and break mddev
-lifetime, causing mddev->kobj refcount underflow or mddev uaf
-problem.
-
-Fix this problem by setting MD_DELETED before queuing del_work.
-
-Reported-by: syzbot+9921e319bd6168140b40@syzkaller.appspotmail.com
-Closes: https://lore.kernel.org/all/68894408.a00a0220.26d0e1.0012.GAE@google.com/
-Reported-by: syzbot+fa3a12519f0d3fd4ec16@syzkaller.appspotmail.com
-Closes: https://lore.kernel.org/all/68894408.a00a0220.26d0e1.0013.GAE@google.com/
-Fixes: 9e59d609763f ("md: call del_gendisk in control path")
-Link: https://lore.kernel.org/linux-raid/20250730073321.2583158-1-yukuai1@huaweicloud.com
-Signed-off-by: Yu Kuai <yukuai3@huawei.com>
-Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
-Reviewed-by: Xiao Ni <xni@redhat.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/md/md.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
---- a/drivers/md/md.c
-+++ b/drivers/md/md.c
-@@ -637,6 +637,12 @@ static void __mddev_put(struct mddev *md
- return;
-
- /*
-+ * If array is freed by stopping array, MD_DELETED is set by
-+ * do_md_stop(), MD_DELETED is still set here in case mddev is freed
-+ * directly by closing a mddev that is created by create_on_open.
-+ */
-+ set_bit(MD_DELETED, &mddev->flags);
-+ /*
- * Call queue_work inside the spinlock so that flush_workqueue() after
- * mddev_find will succeed in waiting for the work to be done.
- */
nvme-tcp-log-tls-handshake-failures-at-error-level.patch
gfs2-validate-i_depth-for-exhash-directories.patch
gfs2-set-.migrate_folio-in-gfs2_-rgrp-meta-_aops.patch
-md-call-del_gendisk-in-control-path.patch
loop-avoid-updating-block-size-under-exclusive-owner.patch
udf-verify-partition-map-count.patch
drbd-add-missing-kref_get-in-handle_write_conflicts.patch
ata-libata-sata-disallow-changing-lpm-state-if-not-s.patch
fs-ntfs3-add-sanity-check-for-file-name.patch
fs-ntfs3-correctly-create-symlink-for-relative-path.patch
-md-don-t-clear-md_closing-until-mddev-is-freed.patch
pidfs-raise-sb_i_nodev-and-sb_i_noexec.patch
landlock-opened-file-never-has-a-negative-dentry.patch
ext2-handle-fiemap-on-empty-files-to-prevent-einval.patch
io_uring-rw-cast-rw-flags-assignment-to-rwf_t.patch
firmware-arm_scmi-convert-to-system_sleep_pm_ops.patch
drm-amd-display-allow-dcn301-to-clear-update-flags.patch
-md-fix-create-on-open-mddev-lifetime-regression.patch
rcu-fix-racy-re-initialization-of-irq_work-causing-hangs.patch
irqchip-mvebu-gicp-use-resource_size-for-ioremap.patch
dm-split-write-bios-on-zone-boundaries-when-zone-append-is-not-emulated.patch
+++ /dev/null
-From fa738623105e2dd4865274dc8525856feaec3ae9 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 11 Jun 2025 15:31:06 +0800
-Subject: md: call del_gendisk in control path
-
-From: Xiao Ni <xni@redhat.com>
-
-[ Upstream commit 9e59d609763f70a992a8f3808dabcce60f14eb5c ]
-
-Now del_gendisk and put_disk are called asynchronously in workqueue work.
-The asynchronous way has a problem that the device node can still exist
-after mdadm --stop command returns in a short window. So udev rule can
-open this device node and create the struct mddev in kernel again. So put
-del_gendisk in control path and still leave put_disk in md_kobj_release
-to avoid uaf of gendisk.
-
-Function del_gendisk can't be called with reconfig_mutex. If it's called
-with reconfig mutex, a deadlock can happen. del_gendisk waits all sysfs
-files access to finish and sysfs file access waits reconfig mutex. So
-put del_gendisk after releasing reconfig mutex.
-
-But there is still a window that sysfs can be accessed between mddev_unlock
-and del_gendisk. So some actions (add disk, change level, .e.g) can happen
-which lead unexpected results. MD_DELETED is used to resolve this problem.
-MD_DELETED is set before releasing reconfig mutex and it should be checked
-for these sysfs access which need reconfig mutex. For sysfs access which
-don't need reconfig mutex, del_gendisk will wait them to finish.
-
-But it doesn't need to do this in function mddev_lock_nointr. There are
-ten places that call it.
-* Five of them are in dm raid which we don't need to care. MD_DELETED is
-only used for md raid.
-* stop_sync_thread, md_do_sync and md_start_sync are related sync request,
-and it needs to wait sync thread to finish before stopping an array.
-* md_ioctl: md_open is called before md_ioctl, so ->openers is added. It
-will fail to stop the array. So it doesn't need to check MD_DELETED here
-* md_set_readonly:
-It needs to call mddev_set_closing_and_sync_blockdev when setting readonly
-or read_auto. So it will fail to stop the array too because MD_CLOSING is
-already set.
-
-Reviewed-by: Yu Kuai <yukuai3@huawei.com>
-Signed-off-by: Xiao Ni <xni@redhat.com>
-Link: https://lore.kernel.org/linux-raid/20250611073108.25463-2-xni@redhat.com
-Signed-off-by: Yu Kuai <yukuai3@huawei.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/md/md.c | 33 +++++++++++++++++++++++----------
- drivers/md/md.h | 26 ++++++++++++++++++++++++--
- 2 files changed, 47 insertions(+), 12 deletions(-)
-
-diff --git a/drivers/md/md.c b/drivers/md/md.c
-index b086cbf24086..8e3939c0d2ed 100644
---- a/drivers/md/md.c
-+++ b/drivers/md/md.c
-@@ -639,9 +639,6 @@ static void __mddev_put(struct mddev *mddev)
- mddev->ctime || mddev->hold_active)
- return;
-
-- /* Array is not configured at all, and not held active, so destroy it */
-- set_bit(MD_DELETED, &mddev->flags);
--
- /*
- * Call queue_work inside the spinlock so that flush_workqueue() after
- * mddev_find will succeed in waiting for the work to be done.
-@@ -837,6 +834,16 @@ void mddev_unlock(struct mddev *mddev)
- kobject_del(&rdev->kobj);
- export_rdev(rdev, mddev);
- }
-+
-+ /* Call del_gendisk after release reconfig_mutex to avoid
-+ * deadlock (e.g. call del_gendisk under the lock and an
-+ * access to sysfs files waits the lock)
-+ * And MD_DELETED is only used for md raid which is set in
-+ * 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))
-+ del_gendisk(mddev->gendisk);
- }
- EXPORT_SYMBOL_GPL(mddev_unlock);
-
-@@ -5616,19 +5623,30 @@ md_attr_store(struct kobject *kobj, struct attribute *attr,
- struct md_sysfs_entry *entry = container_of(attr, struct md_sysfs_entry, attr);
- struct mddev *mddev = container_of(kobj, struct mddev, kobj);
- ssize_t rv;
-+ struct kernfs_node *kn = NULL;
-
- if (!entry->store)
- return -EIO;
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
-+
-+ if (entry->store == array_state_store && cmd_match(page, "clear"))
-+ kn = sysfs_break_active_protection(kobj, attr);
-+
- spin_lock(&all_mddevs_lock);
- if (!mddev_get(mddev)) {
- spin_unlock(&all_mddevs_lock);
-+ if (kn)
-+ sysfs_unbreak_active_protection(kn);
- return -EBUSY;
- }
- spin_unlock(&all_mddevs_lock);
- rv = entry->store(mddev, page, length);
- mddev_put(mddev);
-+
-+ if (kn)
-+ sysfs_unbreak_active_protection(kn);
-+
- return rv;
- }
-
-@@ -5636,12 +5654,6 @@ static void md_kobj_release(struct kobject *ko)
- {
- struct mddev *mddev = container_of(ko, struct mddev, kobj);
-
-- if (mddev->sysfs_state)
-- sysfs_put(mddev->sysfs_state);
-- if (mddev->sysfs_level)
-- sysfs_put(mddev->sysfs_level);
--
-- del_gendisk(mddev->gendisk);
- put_disk(mddev->gendisk);
- }
-
-@@ -6531,8 +6543,9 @@ static int do_md_stop(struct mddev *mddev, int mode,
- mddev->bitmap_info.offset = 0;
-
- export_array(mddev);
--
- md_clean(mddev);
-+ set_bit(MD_DELETED, &mddev->flags);
-+
- if (mddev->hold_active == UNTIL_STOP)
- mddev->hold_active = 0;
- }
-diff --git a/drivers/md/md.h b/drivers/md/md.h
-index 46995558d3bd..0a7c9122db50 100644
---- a/drivers/md/md.h
-+++ b/drivers/md/md.h
-@@ -589,11 +589,26 @@ static inline bool is_md_suspended(struct mddev *mddev)
-
- static inline int __must_check mddev_lock(struct mddev *mddev)
- {
-- return mutex_lock_interruptible(&mddev->reconfig_mutex);
-+ int ret;
-+
-+ ret = mutex_lock_interruptible(&mddev->reconfig_mutex);
-+
-+ /* MD_DELETED is set in do_md_stop with reconfig_mutex.
-+ * So check it here.
-+ */
-+ if (!ret && test_bit(MD_DELETED, &mddev->flags)) {
-+ ret = -ENODEV;
-+ mutex_unlock(&mddev->reconfig_mutex);
-+ }
-+
-+ return ret;
- }
-
- /* Sometimes we need to take the lock in a situation where
- * failure due to interrupts is not acceptable.
-+ * It doesn't need to check MD_DELETED here, the owner which
-+ * holds the lock here can't be stopped. And all paths can't
-+ * call this function after do_md_stop.
- */
- static inline void mddev_lock_nointr(struct mddev *mddev)
- {
-@@ -602,7 +617,14 @@ static inline void mddev_lock_nointr(struct mddev *mddev)
-
- static inline int mddev_trylock(struct mddev *mddev)
- {
-- return mutex_trylock(&mddev->reconfig_mutex);
-+ int ret;
-+
-+ ret = mutex_trylock(&mddev->reconfig_mutex);
-+ if (!ret && test_bit(MD_DELETED, &mddev->flags)) {
-+ ret = -ENODEV;
-+ mutex_unlock(&mddev->reconfig_mutex);
-+ }
-+ return ret;
- }
- extern void mddev_unlock(struct mddev *mddev);
-
---
-2.39.5
-
+++ /dev/null
-From c365a20552d7d7a9eb03cbefd91176c004e24340 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 11 Jun 2025 15:31:07 +0800
-Subject: md: Don't clear MD_CLOSING until mddev is freed
-
-From: Xiao Ni <xni@redhat.com>
-
-[ Upstream commit 5f286f33553d600e6c2fb5a23dd6afcf99b3ebac ]
-
-UNTIL_STOP is used to avoid mddev is freed on the last close before adding
-disks to mddev. And it should be cleared when stopping an array which is
-mentioned in commit efeb53c0e572 ("md: Allow md devices to be created by
-name."). So reset ->hold_active to 0 in md_clean.
-
-And MD_CLOSING should be kept until mddev is freed to avoid reopen.
-
-Reviewed-by: Yu Kuai <yukuai3@huawei.com>
-Signed-off-by: Xiao Ni <xni@redhat.com>
-Link: https://lore.kernel.org/linux-raid/20250611073108.25463-3-xni@redhat.com
-Signed-off-by: Yu Kuai <yukuai3@huawei.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/md/md.c | 16 ++++------------
- 1 file changed, 4 insertions(+), 12 deletions(-)
-
-diff --git a/drivers/md/md.c b/drivers/md/md.c
-index 8e3939c0d2ed..6a3b5b131111 100644
---- a/drivers/md/md.c
-+++ b/drivers/md/md.c
-@@ -6265,15 +6265,10 @@ static void md_clean(struct mddev *mddev)
- mddev->persistent = 0;
- mddev->level = LEVEL_NONE;
- mddev->clevel[0] = 0;
-- /*
-- * Don't clear MD_CLOSING, or mddev can be opened again.
-- * 'hold_active != 0' means mddev is still in the creation
-- * process and will be used later.
-- */
-- if (mddev->hold_active)
-- mddev->flags = 0;
-- else
-- mddev->flags &= BIT_ULL_MASK(MD_CLOSING);
-+ /* if UNTIL_STOP is set, it's cleared here */
-+ mddev->hold_active = 0;
-+ /* Don't clear MD_CLOSING, or mddev can be opened again. */
-+ mddev->flags &= BIT_ULL_MASK(MD_CLOSING);
- mddev->sb_flags = 0;
- mddev->ro = MD_RDWR;
- mddev->metadata_type[0] = 0;
-@@ -6545,9 +6540,6 @@ static int do_md_stop(struct mddev *mddev, int mode,
- export_array(mddev);
- md_clean(mddev);
- set_bit(MD_DELETED, &mddev->flags);
--
-- if (mddev->hold_active == UNTIL_STOP)
-- mddev->hold_active = 0;
- }
- md_new_event();
- sysfs_notify_dirent_safe(mddev->sysfs_state);
---
-2.39.5
-
+++ /dev/null
-From 1df1fc845d221eb646539836dbf509eb96b41afd Mon Sep 17 00:00:00 2001
-From: Yu Kuai <yukuai3@huawei.com>
-Date: Wed, 30 Jul 2025 15:33:21 +0800
-Subject: md: fix create on open mddev lifetime regression
-
-From: Yu Kuai <yukuai3@huawei.com>
-
-commit 1df1fc845d221eb646539836dbf509eb96b41afd upstream.
-
-Commit 9e59d609763f ("md: call del_gendisk in control path") moves
-setting MD_DELETED from __mddev_put() to do_md_stop(), however, for the
-case create on open, mddev can be freed without do_md_stop():
-
-1) open
-
-md_probe
- md_alloc_and_put
- md_alloc
- mddev_alloc
- atomic_set(&mddev->active, 1);
- mddev->hold_active = UNTIL_IOCTL
- mddev_put
- atomic_dec_and_test(&mddev->active)
- if (mddev->hold_active)
- -> active is 0, hold_active is set
-md_open
- mddev_get
- atomic_inc(&mddev->active);
-
-2) ioctl that is not STOP_ARRAY, for example, GET_ARRAY_INFO:
-
-md_ioctl
- mddev->hold_active = 0
-
-3) close
-
-md_release
- mddev_put(mddev);
- atomic_dec_and_lock(&mddev->active, &all_mddevs_lock)
- __mddev_put
- -> hold_active is cleared, mddev will be freed
- queue_work(md_misc_wq, &mddev->del_work)
-
-Now that MD_DELETED is not set, before mddev is freed by
-mddev_delayed_delete(), md_open can still succeed and break mddev
-lifetime, causing mddev->kobj refcount underflow or mddev uaf
-problem.
-
-Fix this problem by setting MD_DELETED before queuing del_work.
-
-Reported-by: syzbot+9921e319bd6168140b40@syzkaller.appspotmail.com
-Closes: https://lore.kernel.org/all/68894408.a00a0220.26d0e1.0012.GAE@google.com/
-Reported-by: syzbot+fa3a12519f0d3fd4ec16@syzkaller.appspotmail.com
-Closes: https://lore.kernel.org/all/68894408.a00a0220.26d0e1.0013.GAE@google.com/
-Fixes: 9e59d609763f ("md: call del_gendisk in control path")
-Link: https://lore.kernel.org/linux-raid/20250730073321.2583158-1-yukuai1@huaweicloud.com
-Signed-off-by: Yu Kuai <yukuai3@huawei.com>
-Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
-Reviewed-by: Xiao Ni <xni@redhat.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/md/md.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
---- a/drivers/md/md.c
-+++ b/drivers/md/md.c
-@@ -640,6 +640,12 @@ static void __mddev_put(struct mddev *md
- return;
-
- /*
-+ * If array is freed by stopping array, MD_DELETED is set by
-+ * do_md_stop(), MD_DELETED is still set here in case mddev is freed
-+ * directly by closing a mddev that is created by create_on_open.
-+ */
-+ set_bit(MD_DELETED, &mddev->flags);
-+ /*
- * Call queue_work inside the spinlock so that flush_workqueue() after
- * mddev_find will succeed in waiting for the work to be done.
- */
smb-server-avoid-deadlock-when-linking-with-replacei.patch
nvme-pci-try-function-level-reset-on-init-failure.patch
gfs2-set-.migrate_folio-in-gfs2_-rgrp-meta-_aops.patch
-md-call-del_gendisk-in-control-path.patch
loop-avoid-updating-block-size-under-exclusive-owner.patch
udf-verify-partition-map-count.patch
drbd-add-missing-kref_get-in-handle_write_conflicts.patch
ata-libata-sata-disallow-changing-lpm-state-if-not-s.patch
fs-ntfs3-add-sanity-check-for-file-name.patch
fs-ntfs3-correctly-create-symlink-for-relative-path.patch
-md-don-t-clear-md_closing-until-mddev-is-freed.patch
ext2-handle-fiemap-on-empty-files-to-prevent-einval.patch
fix-locking-in-efi_secret_unlink.patch
securityfs-don-t-pin-dentries-twice-once-is-enough.patch
rdma-siw-fix-the-sendmsg-byte-count-in-siw_tcp_sendpages.patch
hid-magicmouse-avoid-setting-up-battery-timer-when-not-needed.patch
hid-apple-avoid-setting-up-battery-timer-for-devices-without-battery.patch
-md-fix-create-on-open-mddev-lifetime-regression.patch
rcu-fix-racy-re-initialization-of-irq_work-causing-hangs.patch