Skip to content

Commit 21989cb

Browse files
zhouyun1306gregkh
authored andcommitted
md: fix rcu protection in md_wakeup_thread
[ Upstream commit 0dc7620 ] We attempted to use RCU to protect the pointer 'thread', but directly passed the value when calling md_wakeup_thread(). This means that the RCU pointer has been acquired before rcu_read_lock(), which renders rcu_read_lock() ineffective and could lead to a use-after-free. Link: https://lore.kernel.org/linux-raid/20251015083227.1079009-1-yun.zhou@windriver.com Fixes: 4469315 ("md: protect md_thread with rcu") Signed-off-by: Yun Zhou <yun.zhou@windriver.com> Reviewed-by: Li Nan <linan122@huawei.com> Reviewed-by: Yu Kuai <yukuai@fnnas.com> Signed-off-by: Yu Kuai <yukuai@fnnas.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent b991eda commit 21989cb

File tree

2 files changed

+13
-9
lines changed

2 files changed

+13
-9
lines changed

drivers/md/md.c

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ static int remove_and_add_spares(struct mddev *mddev,
106106
struct md_rdev *this);
107107
static void mddev_detach(struct mddev *mddev);
108108
static void export_rdev(struct md_rdev *rdev, struct mddev *mddev);
109-
static void md_wakeup_thread_directly(struct md_thread __rcu *thread);
109+
static void md_wakeup_thread_directly(struct md_thread __rcu **thread);
110110

111111
/*
112112
* Default number of read corrections we'll attempt on an rdev
@@ -4899,7 +4899,7 @@ static void stop_sync_thread(struct mddev *mddev, bool locked)
48994899
* Thread might be blocked waiting for metadata update which will now
49004900
* never happen
49014901
*/
4902-
md_wakeup_thread_directly(mddev->sync_thread);
4902+
md_wakeup_thread_directly(&mddev->sync_thread);
49034903
if (work_pending(&mddev->sync_work))
49044904
flush_work(&mddev->sync_work);
49054905

@@ -8051,32 +8051,30 @@ static int md_thread(void *arg)
80518051
return 0;
80528052
}
80538053

8054-
static void md_wakeup_thread_directly(struct md_thread __rcu *thread)
8054+
static void md_wakeup_thread_directly(struct md_thread __rcu **thread)
80558055
{
80568056
struct md_thread *t;
80578057

80588058
rcu_read_lock();
8059-
t = rcu_dereference(thread);
8059+
t = rcu_dereference(*thread);
80608060
if (t)
80618061
wake_up_process(t->tsk);
80628062
rcu_read_unlock();
80638063
}
80648064

8065-
void md_wakeup_thread(struct md_thread __rcu *thread)
8065+
void __md_wakeup_thread(struct md_thread __rcu *thread)
80668066
{
80678067
struct md_thread *t;
80688068

8069-
rcu_read_lock();
80708069
t = rcu_dereference(thread);
80718070
if (t) {
80728071
pr_debug("md: waking up MD thread %s.\n", t->tsk->comm);
80738072
set_bit(THREAD_WAKEUP, &t->flags);
80748073
if (wq_has_sleeper(&t->wqueue))
80758074
wake_up(&t->wqueue);
80768075
}
8077-
rcu_read_unlock();
80788076
}
8079-
EXPORT_SYMBOL(md_wakeup_thread);
8077+
EXPORT_SYMBOL(__md_wakeup_thread);
80808078

80818079
struct md_thread *md_register_thread(void (*run) (struct md_thread *),
80828080
struct mddev *mddev, const char *name)

drivers/md/md.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,12 @@ struct md_io_clone {
838838

839839
#define THREAD_WAKEUP 0
840840

841+
#define md_wakeup_thread(thread) do { \
842+
rcu_read_lock(); \
843+
__md_wakeup_thread(thread); \
844+
rcu_read_unlock(); \
845+
} while (0)
846+
841847
static inline void safe_put_page(struct page *p)
842848
{
843849
if (p) put_page(p);
@@ -855,7 +861,7 @@ extern struct md_thread *md_register_thread(
855861
struct mddev *mddev,
856862
const char *name);
857863
extern void md_unregister_thread(struct mddev *mddev, struct md_thread __rcu **threadp);
858-
extern void md_wakeup_thread(struct md_thread __rcu *thread);
864+
extern void __md_wakeup_thread(struct md_thread __rcu *thread);
859865
extern void md_check_recovery(struct mddev *mddev);
860866
extern void md_reap_sync_thread(struct mddev *mddev);
861867
extern enum sync_action md_sync_action(struct mddev *mddev);

0 commit comments

Comments
 (0)