diff options
| author | Guoqing Jiang <guoqing.jiang@cloud.ionos.com> | 2022-04-29 16:49:09 +0800 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2022-06-14 16:52:40 +0200 |
| commit | ac8fd53fa022d57b16393e8cc3ab2f80ad315d4a (patch) | |
| tree | ebc4c7d627e5d532811d057be80496d356dfabdf | |
| parent | 6ae96e638739f040959610d44c0a696d6a80542f (diff) | |
| download | linux-ac8fd53fa022d57b16393e8cc3ab2f80ad315d4a.tar.gz linux-ac8fd53fa022d57b16393e8cc3ab2f80ad315d4a.tar.bz2 linux-ac8fd53fa022d57b16393e8cc3ab2f80ad315d4a.zip | |
md: protect md_unregister_thread from reentrancy
[ 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>
| -rw-r--r-- | drivers/md/md.c | 15 |
1 files 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); } |
