From b925c782d8d87378293a10e02bde34c2806644e4 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 12 May 2017 15:46:17 +0200 Subject: [PATCH 276/365] random: avoid preempt_disable()ed section extract_crng() will use sleeping locks while in a preempt_disable() section due to get_cpu_var(). Work around it with local_locks. Cc: stable-rt@vger.kernel.org # where it applies to Signed-off-by: Sebastian Andrzej Siewior --- drivers/char/random.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 3777a8ff637e..c033135f2a67 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -263,6 +263,7 @@ #include #include #include +#include #include #include @@ -1664,7 +1665,7 @@ void get_random_bytes_arch(void *buf, int nbytes) if (!arch_get_random_long(&v)) break; - + memcpy(p, &v, chunk); p += chunk; nbytes -= chunk; @@ -2118,18 +2119,22 @@ struct batched_entropy { * the goal of being quite fast and not depleting entropy. */ static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_long); +static DEFINE_LOCAL_IRQ_LOCK(batched_entropy_long_lock); unsigned long get_random_long(void) { unsigned long ret; struct batched_entropy *batch; - batch = &get_cpu_var(batched_entropy_long); + if (arch_get_random_long(&ret)) + return ret; + + batch = &get_locked_var(batched_entropy_long_lock, batched_entropy_long); if (batch->position % ARRAY_SIZE(batch->entropy_long) == 0) { extract_crng((u8 *)batch->entropy_long); batch->position = 0; } ret = batch->entropy_long[batch->position++]; - put_cpu_var(batched_entropy_long); + put_locked_var(batched_entropy_long_lock, batched_entropy_long); return ret; } EXPORT_SYMBOL(get_random_long); @@ -2141,18 +2146,23 @@ unsigned int get_random_int(void) } #else static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_int); +static DEFINE_LOCAL_IRQ_LOCK(batched_entropy_int_lock); + unsigned int get_random_int(void) { unsigned int ret; struct batched_entropy *batch; - batch = &get_cpu_var(batched_entropy_int); + if (arch_get_random_int(&ret)) + return ret; + + batch = &get_locked_var(batched_entropy_int_lock, batched_entropy_int); if (batch->position % ARRAY_SIZE(batch->entropy_int) == 0) { extract_crng((u8 *)batch->entropy_int); batch->position = 0; } ret = batch->entropy_int[batch->position++]; - put_cpu_var(batched_entropy_int); + put_locked_var(batched_entropy_int_lock, batched_entropy_int); return ret; } #endif -- 2.28.0