From 6248a0666c8a408dcc5bd952536274d5bd0f02cb Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 4 May 2020 19:33:54 -0700 Subject: 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 --- fs/pstore/platform.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'fs/pstore') 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); -- cgit v1.2.3