random: group initialization wait functions
authorJason A. Donenfeld <Jason@zx2c4.com>
Fri, 11 Feb 2022 11:53:34 +0000 (12:53 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 30 May 2022 07:29:07 +0000 (09:29 +0200)
commit 5f1bb112006b104b3e2a1e1b39bbb9b2617581e6 upstream.

This pulls all of the readiness waiting-focused functions into the first
labeled section.

No functional changes.

Cc: Theodore Ts'o <tytso@mit.edu>
Reviewed-by: Dominik Brodowski <linux@dominikbrodowski.net>
Reviewed-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/char/random.c

index 007eee1..c68a3e3 100644 (file)
 #include <asm/irq_regs.h>
 #include <asm/io.h>
 
-enum {
-       POOL_BITS = BLAKE2S_HASH_SIZE * 8,
-       POOL_MIN_BITS = POOL_BITS /* No point in settling for less. */
-};
-
-/*
- * Static global variables
- */
-static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
-static struct fasync_struct *fasync;
-
-static DEFINE_SPINLOCK(random_ready_list_lock);
-static LIST_HEAD(random_ready_list);
+/*********************************************************************
+ *
+ * Initialization and readiness waiting.
+ *
+ * Much of the RNG infrastructure is devoted to various dependencies
+ * being able to wait until the RNG has collected enough entropy and
+ * is ready for safe consumption.
+ *
+ *********************************************************************/
 
 /*
  * crng_init =  0 --> Uninitialized
  *             1 --> Initialized
  *             2 --> Initialized from input_pool
  *
- * crng_init is protected by primary_crng->lock, and only increases
+ * crng_init is protected by base_crng->lock, and only increases
  * its value (from 0->1->2).
  */
 static int crng_init = 0;
 #define crng_ready() (likely(crng_init > 1))
-static int crng_init_cnt = 0;
-static void process_random_ready_list(void);
-static void _get_random_bytes(void *buf, size_t nbytes);
+/* Various types of waiters for crng_init->2 transition. */
+static DECLARE_WAIT_QUEUE_HEAD(crng_init_wait);
+static struct fasync_struct *fasync;
+static DEFINE_SPINLOCK(random_ready_list_lock);
+static LIST_HEAD(random_ready_list);
 
+/* Control how we warn userspace. */
 static struct ratelimit_state unseeded_warning =
        RATELIMIT_STATE_INIT("warn_unseeded_randomness", HZ, 3);
 static struct ratelimit_state urandom_warning =
        RATELIMIT_STATE_INIT("warn_urandom_randomness", HZ, 3);
-
 static int ratelimit_disable __read_mostly;
-
 module_param_named(ratelimit_disable, ratelimit_disable, int, 0644);
 MODULE_PARM_DESC(ratelimit_disable, "Disable random ratelimit suppression");
 
+/*
+ * Returns whether or not the input pool has been seeded and thus guaranteed
+ * to supply cryptographically secure random numbers. This applies to: the
+ * /dev/urandom device, the get_random_bytes function, and the get_random_{u32,
+ * ,u64,int,long} family of functions.
+ *
+ * Returns: true if the input pool has been seeded.
+ *          false if the input pool has not been seeded.
+ */
+bool rng_is_initialized(void)
+{
+       return crng_ready();
+}
+EXPORT_SYMBOL(rng_is_initialized);
+
+/* Used by wait_for_random_bytes(), and considered an entropy collector, below. */
+static void try_to_generate_entropy(void);
+
+/*
+ * Wait for the input pool to be seeded and thus guaranteed to supply
+ * cryptographically secure random numbers. This applies to: the /dev/urandom
+ * device, the get_random_bytes function, and the get_random_{u32,u64,int,long}
+ * family of functions. Using any of these functions without first calling
+ * this function forfeits the guarantee of security.
+ *
+ * Returns: 0 if the input pool has been seeded.
+ *          -ERESTARTSYS if the function was interrupted by a signal.
+ */
+int wait_for_random_bytes(void)
+{
+       if (likely(crng_ready()))
+               return 0;
+
+       do {
+               int ret;
+               ret = wait_event_interruptible_timeout(crng_init_wait, crng_ready(), HZ);
+               if (ret)
+                       return ret > 0 ? 0 : ret;
+
+               try_to_generate_entropy();
+       } while (!crng_ready());
+
+       return 0;
+}
+EXPORT_SYMBOL(wait_for_random_bytes);
+
+/*
+ * Add a callback function that will be invoked when the input
+ * pool is initialised.
+ *
+ * returns: 0 if callback is successfully added
+ *         -EALREADY if pool is already initialised (callback not called)
+ *         -ENOENT if module for callback is not alive
+ */
+int add_random_ready_callback(struct random_ready_callback *rdy)
+{
+       struct module *owner;
+       unsigned long flags;
+       int err = -EALREADY;
+
+       if (crng_ready())
+               return err;
+
+       owner = rdy->owner;
+       if (!try_module_get(owner))
+               return -ENOENT;
+
+       spin_lock_irqsave(&random_ready_list_lock, flags);
+       if (crng_ready())
+               goto out;
+
+       owner = NULL;
+
+       list_add(&rdy->list, &random_ready_list);
+       err = 0;
+
+out:
+       spin_unlock_irqrestore(&random_ready_list_lock, flags);
+
+       module_put(owner);
+
+       return err;
+}
+EXPORT_SYMBOL(add_random_ready_callback);
+
+/*
+ * Delete a previously registered readiness callback function.
+ */
+void del_random_ready_callback(struct random_ready_callback *rdy)
+{
+       unsigned long flags;
+       struct module *owner = NULL;
+
+       spin_lock_irqsave(&random_ready_list_lock, flags);
+       if (!list_empty(&rdy->list)) {
+               list_del_init(&rdy->list);
+               owner = rdy->owner;
+       }
+       spin_unlock_irqrestore(&random_ready_list_lock, flags);
+
+       module_put(owner);
+}
+EXPORT_SYMBOL(del_random_ready_callback);
+
+static void process_random_ready_list(void)
+{
+       unsigned long flags;
+       struct random_ready_callback *rdy, *tmp;
+
+       spin_lock_irqsave(&random_ready_list_lock, flags);
+       list_for_each_entry_safe(rdy, tmp, &random_ready_list, list) {
+               struct module *owner = rdy->owner;
+
+               list_del_init(&rdy->list);
+               rdy->func(rdy);
+               module_put(owner);
+       }
+       spin_unlock_irqrestore(&random_ready_list_lock, flags);
+}
+
+#define warn_unseeded_randomness(previous) \
+       _warn_unseeded_randomness(__func__, (void *)_RET_IP_, (previous))
+
+static void _warn_unseeded_randomness(const char *func_name, void *caller, void **previous)
+{
+#ifdef CONFIG_WARN_ALL_UNSEEDED_RANDOM
+       const bool print_once = false;
+#else
+       static bool print_once __read_mostly;
+#endif
+
+       if (print_once || crng_ready() ||
+           (previous && (caller == READ_ONCE(*previous))))
+               return;
+       WRITE_ONCE(*previous, caller);
+#ifndef CONFIG_WARN_ALL_UNSEEDED_RANDOM
+       print_once = true;
+#endif
+       if (__ratelimit(&unseeded_warning))
+               printk_deferred(KERN_NOTICE "random: %s called from %pS with crng_init=%d\n",
+                               func_name, caller, crng_init);
+}
+
+
+enum {
+       POOL_BITS = BLAKE2S_HASH_SIZE * 8,
+       POOL_MIN_BITS = POOL_BITS /* No point in settling for less. */
+};
+
+/*
+ * Static global variables
+ */
+static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
+
+static int crng_init_cnt = 0;
+
 /**********************************************************************
  *
  * OS independent entropy store.   Here are the functions which handle
@@ -322,22 +475,6 @@ static void fast_mix(u32 pool[4])
        pool[2] = c;  pool[3] = d;
 }
 
-static void process_random_ready_list(void)
-{
-       unsigned long flags;
-       struct random_ready_callback *rdy, *tmp;
-
-       spin_lock_irqsave(&random_ready_list_lock, flags);
-       list_for_each_entry_safe(rdy, tmp, &random_ready_list, list) {
-               struct module *owner = rdy->owner;
-
-               list_del_init(&rdy->list);
-               rdy->func(rdy);
-               module_put(owner);
-       }
-       spin_unlock_irqrestore(&random_ready_list_lock, flags);
-}
-
 static void credit_entropy_bits(size_t nbits)
 {
        unsigned int entropy_count, orig, add;
@@ -387,8 +524,6 @@ static DEFINE_PER_CPU(struct crng, crngs) = {
        .lock = INIT_LOCAL_LOCK(crngs.lock),
 };
 
-static DECLARE_WAIT_QUEUE_HEAD(crng_init_wait);
-
 /*
  * crng_fast_load() can be called by code in the interrupt service
  * path.  So we can't afford to dilly-dally. Returns the number of
@@ -909,29 +1044,6 @@ static bool drain_entropy(void *buf, size_t nbytes)
        return true;
 }
 
-#define warn_unseeded_randomness(previous) \
-       _warn_unseeded_randomness(__func__, (void *)_RET_IP_, (previous))
-
-static void _warn_unseeded_randomness(const char *func_name, void *caller, void **previous)
-{
-#ifdef CONFIG_WARN_ALL_UNSEEDED_RANDOM
-       const bool print_once = false;
-#else
-       static bool print_once __read_mostly;
-#endif
-
-       if (print_once || crng_ready() ||
-           (previous && (caller == READ_ONCE(*previous))))
-               return;
-       WRITE_ONCE(*previous, caller);
-#ifndef CONFIG_WARN_ALL_UNSEEDED_RANDOM
-       print_once = true;
-#endif
-       if (__ratelimit(&unseeded_warning))
-               printk_deferred(KERN_NOTICE "random: %s called from %pS with crng_init=%d\n",
-                               func_name, caller, crng_init);
-}
-
 /*
  * This function is the exported kernel interface.  It returns some
  * number of good random numbers, suitable for key generation, seeding
@@ -1033,107 +1145,6 @@ static void try_to_generate_entropy(void)
 }
 
 /*
- * Wait for the urandom pool to be seeded and thus guaranteed to supply
- * cryptographically secure random numbers. This applies to: the /dev/urandom
- * device, the get_random_bytes function, and the get_random_{u32,u64,int,long}
- * family of functions. Using any of these functions without first calling
- * this function forfeits the guarantee of security.
- *
- * Returns: 0 if the urandom pool has been seeded.
- *          -ERESTARTSYS if the function was interrupted by a signal.
- */
-int wait_for_random_bytes(void)
-{
-       if (likely(crng_ready()))
-               return 0;
-
-       do {
-               int ret;
-               ret = wait_event_interruptible_timeout(crng_init_wait, crng_ready(), HZ);
-               if (ret)
-                       return ret > 0 ? 0 : ret;
-
-               try_to_generate_entropy();
-       } while (!crng_ready());
-
-       return 0;
-}
-EXPORT_SYMBOL(wait_for_random_bytes);
-
-/*
- * Returns whether or not the urandom pool has been seeded and thus guaranteed
- * to supply cryptographically secure random numbers. This applies to: the
- * /dev/urandom device, the get_random_bytes function, and the get_random_{u32,
- * ,u64,int,long} family of functions.
- *
- * Returns: true if the urandom pool has been seeded.
- *          false if the urandom pool has not been seeded.
- */
-bool rng_is_initialized(void)
-{
-       return crng_ready();
-}
-EXPORT_SYMBOL(rng_is_initialized);
-
-/*
- * Add a callback function that will be invoked when the nonblocking
- * pool is initialised.
- *
- * returns: 0 if callback is successfully added
- *         -EALREADY if pool is already initialised (callback not called)
- *         -ENOENT if module for callback is not alive
- */
-int add_random_ready_callback(struct random_ready_callback *rdy)
-{
-       struct module *owner;
-       unsigned long flags;
-       int err = -EALREADY;
-
-       if (crng_ready())
-               return err;
-
-       owner = rdy->owner;
-       if (!try_module_get(owner))
-               return -ENOENT;
-
-       spin_lock_irqsave(&random_ready_list_lock, flags);
-       if (crng_ready())
-               goto out;
-
-       owner = NULL;
-
-       list_add(&rdy->list, &random_ready_list);
-       err = 0;
-
-out:
-       spin_unlock_irqrestore(&random_ready_list_lock, flags);
-
-       module_put(owner);
-
-       return err;
-}
-EXPORT_SYMBOL(add_random_ready_callback);
-
-/*
- * Delete a previously registered readiness callback function.
- */
-void del_random_ready_callback(struct random_ready_callback *rdy)
-{
-       unsigned long flags;
-       struct module *owner = NULL;
-
-       spin_lock_irqsave(&random_ready_list_lock, flags);
-       if (!list_empty(&rdy->list)) {
-               list_del_init(&rdy->list);
-               owner = rdy->owner;
-       }
-       spin_unlock_irqrestore(&random_ready_list_lock, flags);
-
-       module_put(owner);
-}
-EXPORT_SYMBOL(del_random_ready_callback);
-
-/*
  * This function will use the architecture-specific hardware random
  * number generator if it is available. It is not recommended for
  * use. Use get_random_bytes() instead. It returns the number of