| From 43838a23a05fbd13e47d750d3dfd77001536dd33 Mon Sep 17 00:00:00 2001 |
| From: Theodore Ts'o <tytso@mit.edu> |
| Date: Wed, 11 Apr 2018 13:27:52 -0400 |
| Subject: random: fix crng_ready() test |
| |
| From: Theodore Ts'o <tytso@mit.edu> |
| |
| commit 43838a23a05fbd13e47d750d3dfd77001536dd33 upstream. |
| |
| The crng_init variable has three states: |
| |
| 0: The CRNG is not initialized at all |
| 1: The CRNG has a small amount of entropy, hopefully good enough for |
| early-boot, non-cryptographical use cases |
| 2: The CRNG is fully initialized and we are sure it is safe for |
| cryptographic use cases. |
| |
| The crng_ready() function should only return true once we are in the |
| last state. This addresses CVE-2018-1108. |
| |
| Reported-by: Jann Horn <jannh@google.com> |
| Fixes: e192be9d9a30 ("random: replace non-blocking pool...") |
| Cc: stable@kernel.org # 4.8+ |
| Signed-off-by: Theodore Ts'o <tytso@mit.edu> |
| Reviewed-by: Jann Horn <jannh@google.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/char/random.c | 10 +++++----- |
| 1 file changed, 5 insertions(+), 5 deletions(-) |
| |
| --- a/drivers/char/random.c |
| +++ b/drivers/char/random.c |
| @@ -434,7 +434,7 @@ struct crng_state primary_crng = { |
| * its value (from 0->1->2). |
| */ |
| static int crng_init = 0; |
| -#define crng_ready() (likely(crng_init > 0)) |
| +#define crng_ready() (likely(crng_init > 1)) |
| static int crng_init_cnt = 0; |
| #define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE) |
| static void _extract_crng(struct crng_state *crng, |
| @@ -800,7 +800,7 @@ static int crng_fast_load(const char *cp |
| |
| if (!spin_trylock_irqsave(&primary_crng.lock, flags)) |
| return 0; |
| - if (crng_ready()) { |
| + if (crng_init != 0) { |
| spin_unlock_irqrestore(&primary_crng.lock, flags); |
| return 0; |
| } |
| @@ -872,7 +872,7 @@ static void _extract_crng(struct crng_st |
| { |
| unsigned long v, flags; |
| |
| - if (crng_init > 1 && |
| + if (crng_ready() && |
| time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL)) |
| crng_reseed(crng, crng == &primary_crng ? &input_pool : NULL); |
| spin_lock_irqsave(&crng->lock, flags); |
| @@ -1153,7 +1153,7 @@ void add_interrupt_randomness(int irq, i |
| fast_mix(fast_pool); |
| add_interrupt_bench(cycles); |
| |
| - if (!crng_ready()) { |
| + if (unlikely(crng_init == 0)) { |
| if ((fast_pool->count >= 64) && |
| crng_fast_load((char *) fast_pool->pool, |
| sizeof(fast_pool->pool))) { |
| @@ -2148,7 +2148,7 @@ void add_hwgenerator_randomness(const ch |
| { |
| struct entropy_store *poolp = &input_pool; |
| |
| - if (!crng_ready()) { |
| + if (unlikely(crng_init == 0)) { |
| crng_fast_load(buffer, count); |
| return; |
| } |