crypto: null - Use spin lock instead of mutex

[ Upstream commit dcc47a028c24e793ce6d6efebfef1a1e92f80297 ]

As the null algorithm may be freed in softirq context through
af_alg, use spin locks instead of mutexes to protect the default
null algorithm.

Reported-by: syzbot+b3e02953598f447d4d2a@syzkaller.appspotmail.com
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Herbert Xu 2025-02-12 14:10:07 +08:00 committed by Greg Kroah-Hartman
parent d999b11302
commit 1b66a5920b

View File

@ -17,10 +17,10 @@
#include <crypto/internal/skcipher.h> #include <crypto/internal/skcipher.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mm.h> #include <linux/spinlock.h>
#include <linux/string.h> #include <linux/string.h>
static DEFINE_MUTEX(crypto_default_null_skcipher_lock); static DEFINE_SPINLOCK(crypto_default_null_skcipher_lock);
static struct crypto_sync_skcipher *crypto_default_null_skcipher; static struct crypto_sync_skcipher *crypto_default_null_skcipher;
static int crypto_default_null_skcipher_refcnt; static int crypto_default_null_skcipher_refcnt;
@ -152,23 +152,32 @@ MODULE_ALIAS_CRYPTO("cipher_null");
struct crypto_sync_skcipher *crypto_get_default_null_skcipher(void) struct crypto_sync_skcipher *crypto_get_default_null_skcipher(void)
{ {
struct crypto_sync_skcipher *ntfm = NULL;
struct crypto_sync_skcipher *tfm; struct crypto_sync_skcipher *tfm;
mutex_lock(&crypto_default_null_skcipher_lock); spin_lock_bh(&crypto_default_null_skcipher_lock);
tfm = crypto_default_null_skcipher; tfm = crypto_default_null_skcipher;
if (!tfm) { if (!tfm) {
tfm = crypto_alloc_sync_skcipher("ecb(cipher_null)", 0, 0); spin_unlock_bh(&crypto_default_null_skcipher_lock);
if (IS_ERR(tfm))
goto unlock;
crypto_default_null_skcipher = tfm; ntfm = crypto_alloc_sync_skcipher("ecb(cipher_null)", 0, 0);
if (IS_ERR(ntfm))
return ntfm;
spin_lock_bh(&crypto_default_null_skcipher_lock);
tfm = crypto_default_null_skcipher;
if (!tfm) {
tfm = ntfm;
ntfm = NULL;
crypto_default_null_skcipher = tfm;
}
} }
crypto_default_null_skcipher_refcnt++; crypto_default_null_skcipher_refcnt++;
spin_unlock_bh(&crypto_default_null_skcipher_lock);
unlock: crypto_free_sync_skcipher(ntfm);
mutex_unlock(&crypto_default_null_skcipher_lock);
return tfm; return tfm;
} }
@ -176,12 +185,16 @@ EXPORT_SYMBOL_GPL(crypto_get_default_null_skcipher);
void crypto_put_default_null_skcipher(void) void crypto_put_default_null_skcipher(void)
{ {
mutex_lock(&crypto_default_null_skcipher_lock); struct crypto_sync_skcipher *tfm = NULL;
spin_lock_bh(&crypto_default_null_skcipher_lock);
if (!--crypto_default_null_skcipher_refcnt) { if (!--crypto_default_null_skcipher_refcnt) {
crypto_free_sync_skcipher(crypto_default_null_skcipher); tfm = crypto_default_null_skcipher;
crypto_default_null_skcipher = NULL; crypto_default_null_skcipher = NULL;
} }
mutex_unlock(&crypto_default_null_skcipher_lock); spin_unlock_bh(&crypto_default_null_skcipher_lock);
crypto_free_sync_skcipher(tfm);
} }
EXPORT_SYMBOL_GPL(crypto_put_default_null_skcipher); EXPORT_SYMBOL_GPL(crypto_put_default_null_skcipher);