summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorPetr Mladek <pmladek@suse.com>2022-10-04 15:55:44 +0200
committerPetr Mladek <pmladek@suse.com>2022-10-04 15:55:44 +0200
commitda743a92e5895eb1b225de7d9806274fdbd43061 (patch)
treefb2808ba7bf7e4f03466ea5787ba89f85063da94 /lib
parentdc453dd89daacdc0da6d66234aa27e417df7edcd (diff)
parent6f0ac3b52a9075b7291a72fb338d08491c1f0a64 (diff)
Merge branch 'for-6.1-hash-pointer-init' into for-linus
Diffstat (limited to 'lib')
-rw-r--r--lib/vsprintf.c47
1 files changed, 26 insertions, 21 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 07b36d8b29c3..a7407ebe949c 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -750,37 +750,42 @@ static int __init debug_boot_weak_hash_enable(char *str)
}
early_param("debug_boot_weak_hash", debug_boot_weak_hash_enable);
-static DEFINE_STATIC_KEY_FALSE(filled_random_ptr_key);
+static bool filled_random_ptr_key __read_mostly;
+static siphash_key_t ptr_key __read_mostly;
+static void fill_ptr_key_workfn(struct work_struct *work);
+static DECLARE_DELAYED_WORK(fill_ptr_key_work, fill_ptr_key_workfn);
-static void enable_ptr_key_workfn(struct work_struct *work)
+static void fill_ptr_key_workfn(struct work_struct *work)
{
- static_branch_enable(&filled_random_ptr_key);
+ if (!rng_is_initialized()) {
+ queue_delayed_work(system_unbound_wq, &fill_ptr_key_work, HZ * 2);
+ return;
+ }
+
+ get_random_bytes(&ptr_key, sizeof(ptr_key));
+
+ /* Pairs with smp_rmb() before reading ptr_key. */
+ smp_wmb();
+ WRITE_ONCE(filled_random_ptr_key, true);
+}
+
+static int __init vsprintf_init_hashval(void)
+{
+ fill_ptr_key_workfn(NULL);
+ return 0;
}
+subsys_initcall(vsprintf_init_hashval)
/* Maps a pointer to a 32 bit unique identifier. */
static inline int __ptr_to_hashval(const void *ptr, unsigned long *hashval_out)
{
- static siphash_key_t ptr_key __read_mostly;
unsigned long hashval;
- if (!static_branch_likely(&filled_random_ptr_key)) {
- static bool filled = false;
- static DEFINE_SPINLOCK(filling);
- static DECLARE_WORK(enable_ptr_key_work, enable_ptr_key_workfn);
- unsigned long flags;
-
- if (!system_unbound_wq || !rng_is_initialized() ||
- !spin_trylock_irqsave(&filling, flags))
- return -EAGAIN;
-
- if (!filled) {
- get_random_bytes(&ptr_key, sizeof(ptr_key));
- queue_work(system_unbound_wq, &enable_ptr_key_work);
- filled = true;
- }
- spin_unlock_irqrestore(&filling, flags);
- }
+ if (!READ_ONCE(filled_random_ptr_key))
+ return -EBUSY;
+ /* Pairs with smp_wmb() after writing ptr_key. */
+ smp_rmb();
#ifdef CONFIG_64BIT
hashval = (unsigned long)siphash_1u64((u64)ptr, &ptr_key);