diff options
author | Kees Cook <keescook@chromium.org> | 2020-05-04 19:33:54 -0700 |
---|---|---|
committer | Kees Cook <keescook@chromium.org> | 2020-05-12 09:15:11 -0700 |
commit | 6248a0666c8a408dcc5bd952536274d5bd0f02cb (patch) | |
tree | 3514e03a0eb5b3cd72c85f303965ee63716365ec /fs/pstore/platform.c | |
parent | db23491c77207ef6bec2b232238710de4755db6a (diff) | |
download | linux-6248a0666c8a408dcc5bd952536274d5bd0f02cb.tar.bz2 |
pstore: Add proper unregister lock checking
The pstore backend lock wasn't being used during pstore_unregister().
Add sanity check and locking.
Link: https://lore.kernel.org/lkml/20200506152114.50375-7-keescook@chromium.org/
Signed-off-by: Kees Cook <keescook@chromium.org>
Diffstat (limited to 'fs/pstore/platform.c')
-rw-r--r-- | fs/pstore/platform.c | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index d0ce22237589..8c0076a1f896 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -69,8 +69,9 @@ static void pstore_dowork(struct work_struct *); static DECLARE_WORK(pstore_work, pstore_dowork); /* - * psinfo_lock just protects "psinfo" during - * calls to pstore_register() + * psinfo_lock protects "psinfo" during calls to + * pstore_register(), pstore_unregister(), and + * the filesystem mount/unmount routines. */ static DEFINE_MUTEX(psinfo_lock); struct pstore_info *psinfo; @@ -587,8 +588,6 @@ int pstore_register(struct pstore_info *psi) psinfo = psi; mutex_init(&psinfo->read_mutex); sema_init(&psinfo->buf_lock, 1); - mutex_unlock(&psinfo_lock); - if (psi->flags & PSTORE_FLAGS_DMESG) allocate_buf_for_compression(); @@ -620,12 +619,25 @@ int pstore_register(struct pstore_info *psi) pr_info("Registered %s as persistent store backend\n", psi->name); + mutex_unlock(&psinfo_lock); return 0; } EXPORT_SYMBOL_GPL(pstore_register); void pstore_unregister(struct pstore_info *psi) { + /* It's okay to unregister nothing. */ + if (!psi) + return; + + mutex_lock(&psinfo_lock); + + /* Only one backend can be registered at a time. */ + if (WARN_ON(psi != psinfo)) { + mutex_unlock(&psinfo_lock); + return; + } + /* Stop timer and make sure all work has finished. */ pstore_update_ms = -1; del_timer_sync(&pstore_timer); @@ -644,6 +656,7 @@ void pstore_unregister(struct pstore_info *psi) psinfo = NULL; backend = NULL; + mutex_unlock(&psinfo_lock); } EXPORT_SYMBOL_GPL(pstore_unregister); |