random: make credit_entropy_bits() always safe
authorJason A. Donenfeld <Jason@zx2c4.com>
Fri, 4 Feb 2022 00:45:53 +0000 (01:45 +0100)
committerJason A. Donenfeld <Jason@zx2c4.com>
Mon, 21 Feb 2022 15:48:06 +0000 (16:48 +0100)
This is called from various hwgenerator drivers, so rather than having
one "safe" version for userspace and one "unsafe" version for the
kernel, just make everything safe; the checks are cheap and sensible to
have anyway.

Reported-by: Sultan Alsawaf <sultan@kerneltoast.com>
Reviewed-by: Eric Biggers <ebiggers@google.com>
Reviewed-by: Dominik Brodowski <linux@dominikbrodowski.net>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
drivers/char/random.c

index 3b30e76..92aca0a 100644 (file)
@@ -447,18 +447,15 @@ static void process_random_ready_list(void)
        spin_unlock_irqrestore(&random_ready_list_lock, flags);
 }
 
-/*
- * Credit (or debit) the entropy store with n bits of entropy.
- * Use credit_entropy_bits_safe() if the value comes from userspace
- * or otherwise should be checked for extreme values.
- */
 static void credit_entropy_bits(int nbits)
 {
        int entropy_count, orig;
 
-       if (!nbits)
+       if (nbits <= 0)
                return;
 
+       nbits = min(nbits, POOL_BITS);
+
        do {
                orig = READ_ONCE(input_pool.entropy_count);
                entropy_count = min(POOL_BITS, orig + nbits);
@@ -470,18 +467,6 @@ static void credit_entropy_bits(int nbits)
                crng_reseed(&primary_crng, true);
 }
 
-static int credit_entropy_bits_safe(int nbits)
-{
-       if (nbits < 0)
-               return -EINVAL;
-
-       /* Cap the value to avoid overflows */
-       nbits = min(nbits, POOL_BITS);
-
-       credit_entropy_bits(nbits);
-       return 0;
-}
-
 /*********************************************************************
  *
  * CRNG using CHACHA20
@@ -1526,7 +1511,10 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
                        return -EPERM;
                if (get_user(ent_count, p))
                        return -EFAULT;
-               return credit_entropy_bits_safe(ent_count);
+               if (ent_count < 0)
+                       return -EINVAL;
+               credit_entropy_bits(ent_count);
+               return 0;
        case RNDADDENTROPY:
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
@@ -1539,7 +1527,8 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
                retval = write_pool((const char __user *)p, size);
                if (retval < 0)
                        return retval;
-               return credit_entropy_bits_safe(ent_count);
+               credit_entropy_bits(ent_count);
+               return 0;
        case RNDZAPENTCNT:
        case RNDCLEARPOOL:
                /*