| From b167942dc2fa94209d4849a4cf5c2eb929089567 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 29 Apr 2022 16:49:09 +0800 |
| Subject: md: protect md_unregister_thread from reentrancy |
| |
| From: Guoqing Jiang <guoqing.jiang@cloud.ionos.com> |
| |
| [ Upstream commit 1e267742283a4b5a8ca65755c44166be27e9aa0f ] |
| |
| Generally, the md_unregister_thread is called with reconfig_mutex, but |
| raid_message in dm-raid doesn't hold reconfig_mutex to unregister thread, |
| so md_unregister_thread can be called simulitaneously from two call sites |
| in theory. |
| |
| Then after previous commit which remove the protection of reconfig_mutex |
| for md_unregister_thread completely, the potential issue could be worse |
| than before. |
| |
| Let's take pers_lock at the beginning of function to ensure reentrancy. |
| |
| Reported-by: Donald Buczek <buczek@molgen.mpg.de> |
| Signed-off-by: Guoqing Jiang <guoqing.jiang@linux.dev> |
| Signed-off-by: Song Liu <song@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/md/md.c | 15 ++++++++++----- |
| 1 file changed, 10 insertions(+), 5 deletions(-) |
| |
| diff --git a/drivers/md/md.c b/drivers/md/md.c |
| index 0197d18b5407..9e8373e7e287 100644 |
| --- a/drivers/md/md.c |
| +++ b/drivers/md/md.c |
| @@ -7254,17 +7254,22 @@ EXPORT_SYMBOL(md_register_thread); |
| |
| void md_unregister_thread(struct md_thread **threadp) |
| { |
| - struct md_thread *thread = *threadp; |
| - if (!thread) |
| - return; |
| - pr_debug("interrupting MD-thread pid %d\n", task_pid_nr(thread->tsk)); |
| - /* Locking ensures that mddev_unlock does not wake_up a |
| + struct md_thread *thread; |
| + |
| + /* |
| + * Locking ensures that mddev_unlock does not wake_up a |
| * non-existent thread |
| */ |
| spin_lock(&pers_lock); |
| + thread = *threadp; |
| + if (!thread) { |
| + spin_unlock(&pers_lock); |
| + return; |
| + } |
| *threadp = NULL; |
| spin_unlock(&pers_lock); |
| |
| + pr_debug("interrupting MD-thread pid %d\n", task_pid_nr(thread->tsk)); |
| kthread_stop(thread->tsk); |
| kfree(thread); |
| } |
| -- |
| 2.35.1 |
| |