]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
crypto: jitterentropy - replace long-held spinlock with mutex
authorHaixin Xu <jerryxucs@gmail.com>
Mon, 30 Mar 2026 07:23:46 +0000 (15:23 +0800)
committerHerbert Xu <herbert@gondor.apana.org.au>
Sun, 12 Apr 2026 08:46:29 +0000 (16:46 +0800)
jent_kcapi_random() serializes the shared jitterentropy state, but it
currently holds a spinlock across the jent_read_entropy() call. That
path performs expensive jitter collection and SHA3 conditioning, so
parallel readers can trigger stalls as contending waiters spin for
the same lock.

To prevent non-preemptible lock hold, replace rng->jent_lock with a
mutex so contended readers sleep instead of spinning on a shared lock
held across expensive entropy generation.

Fixes: bb5530e40824 ("crypto: jitterentropy - add jitterentropy RNG")
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Reported-by: Yuan Tan <yuantan098@gmail.com>
Suggested-by: Xin Liu <bird@lzu.edu.cn>
Signed-off-by: Haixin Xu <jerryxucs@gmail.com>
Reviewed-by: Stephan Mueller <smueller@chronox.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
crypto/jitterentropy-kcapi.c

index 7c880cf34c5233b539a414599cf82793e44054ce..5edc6d285aa1497e504e42774b506798ae46830b 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/fips.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <crypto/internal/rng.h>
@@ -193,7 +194,7 @@ int jent_read_random_block(void *hash_state, char *dst, unsigned int dst_len)
  ***************************************************************************/
 
 struct jitterentropy {
-       spinlock_t jent_lock;
+       struct mutex jent_lock;
        struct rand_data *entropy_collector;
        struct crypto_shash *tfm;
        struct shash_desc *sdesc;
@@ -203,7 +204,7 @@ static void jent_kcapi_cleanup(struct crypto_tfm *tfm)
 {
        struct jitterentropy *rng = crypto_tfm_ctx(tfm);
 
-       spin_lock(&rng->jent_lock);
+       mutex_lock(&rng->jent_lock);
 
        if (rng->sdesc) {
                shash_desc_zero(rng->sdesc);
@@ -218,7 +219,7 @@ static void jent_kcapi_cleanup(struct crypto_tfm *tfm)
        if (rng->entropy_collector)
                jent_entropy_collector_free(rng->entropy_collector);
        rng->entropy_collector = NULL;
-       spin_unlock(&rng->jent_lock);
+       mutex_unlock(&rng->jent_lock);
 }
 
 static int jent_kcapi_init(struct crypto_tfm *tfm)
@@ -228,7 +229,7 @@ static int jent_kcapi_init(struct crypto_tfm *tfm)
        struct shash_desc *sdesc;
        int size, ret = 0;
 
-       spin_lock_init(&rng->jent_lock);
+       mutex_init(&rng->jent_lock);
 
        /* Use SHA3-256 as conditioner */
        hash = crypto_alloc_shash(JENT_CONDITIONING_HASH, 0, 0);
@@ -257,7 +258,6 @@ static int jent_kcapi_init(struct crypto_tfm *tfm)
                goto err;
        }
 
-       spin_lock_init(&rng->jent_lock);
        return 0;
 
 err:
@@ -272,7 +272,7 @@ static int jent_kcapi_random(struct crypto_rng *tfm,
        struct jitterentropy *rng = crypto_rng_ctx(tfm);
        int ret = 0;
 
-       spin_lock(&rng->jent_lock);
+       mutex_lock(&rng->jent_lock);
 
        ret = jent_read_entropy(rng->entropy_collector, rdata, dlen);
 
@@ -298,7 +298,7 @@ static int jent_kcapi_random(struct crypto_rng *tfm,
                ret = -EINVAL;
        }
 
-       spin_unlock(&rng->jent_lock);
+       mutex_unlock(&rng->jent_lock);
 
        return ret;
 }