summaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2022-03-01 20:03:49 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2022-03-12 18:00:56 -0700
commit5acd35487dc911541672b3ffc322851769c32a56 (patch)
treeea7d9e993383b44e483fcd44fc85df78222f8af8 /drivers/char
parenta4107d34f960df99ca07fa8eb022425a804f59f3 (diff)
downloadlinux-5acd35487dc911541672b3ffc322851769c32a56.tar.bz2
random: replace custom notifier chain with standard one
We previously rolled our own randomness readiness notifier, which only has two users in the whole kernel. Replace this with a more standard atomic notifier block that serves the same purpose with less code. Also unexport the symbols, because no modules use it, only unconditional builtins. The only drawback is that it's possible for a notification handler returning the "stop" code to prevent further processing, but given that there are only two users, and that we're unexporting this anyway, that doesn't seem like a significant drawback for the simplification we receive here. Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Theodore Ts'o <tytso@mit.edu> Reviewed-by: Dominik Brodowski <linux@dominikbrodowski.net> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/random.c67
1 files changed, 19 insertions, 48 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c
index bc2a4f7e3655..aa7bc9a3a864 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -83,8 +83,8 @@ static int crng_init = 0;
/* 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);
+static DEFINE_SPINLOCK(random_ready_chain_lock);
+static RAW_NOTIFIER_HEAD(random_ready_chain);
/* Control how we warn userspace. */
static struct ratelimit_state unseeded_warning =
@@ -144,72 +144,43 @@ EXPORT_SYMBOL(wait_for_random_bytes);
*
* 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)
+int register_random_ready_notifier(struct notifier_block *nb)
{
- struct module *owner;
unsigned long flags;
- int err = -EALREADY;
+ int ret = -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 ret;
- return err;
+ spin_lock_irqsave(&random_ready_chain_lock, flags);
+ if (!crng_ready())
+ ret = raw_notifier_chain_register(&random_ready_chain, nb);
+ spin_unlock_irqrestore(&random_ready_chain_lock, flags);
+ return ret;
}
-EXPORT_SYMBOL(add_random_ready_callback);
/*
* Delete a previously registered readiness callback function.
*/
-void del_random_ready_callback(struct random_ready_callback *rdy)
+int unregister_random_ready_notifier(struct notifier_block *nb)
{
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);
+ int ret;
- module_put(owner);
+ spin_lock_irqsave(&random_ready_chain_lock, flags);
+ ret = raw_notifier_chain_unregister(&random_ready_chain, nb);
+ spin_unlock_irqrestore(&random_ready_chain_lock, flags);
+ return ret;
}
-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);
+ spin_lock_irqsave(&random_ready_chain_lock, flags);
+ raw_notifier_call_chain(&random_ready_chain, 0, NULL);
+ spin_unlock_irqrestore(&random_ready_chain_lock, flags);
}
#define warn_unseeded_randomness(previous) \