BACKPORT: random32: add prandom_reseed_late() and call when
authorHannes Frederic Sowa <hannes@stressinduktion.org>
Mon, 11 Nov 2013 11:20:34 +0000 (12:20 +0100)
committerDanny Wood <danwood76@gmail.com>
Fri, 30 Nov 2018 10:58:42 +0000 (10:58 +0000)
 nonblocking pool becomes initialized

Clean cherry pick of commit 4af712e8df998475736f3e2727701bd31e3751a9.

The Tausworthe PRNG is initialized at late_initcall time. At that time the
entropy pool serving get_random_bytes is not filled sufficiently. This
patch adds an additional reseeding step as soon as the nonblocking pool
gets marked as initialized.

On some machines it might be possible that late_initcall gets called after
the pool has been initialized. In this situation we won't reseed again.

(A call to prandom_seed_late blocks later invocations of early reseed
attempts.)

Joint work with Daniel Borkmann.

Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Acked-by: "Theodore Ts'o" <tytso@mit.edu>
Signed-off-by: David S. Miller <davem@davemloft.net>
Bug: http://b/29621447
Change-Id: I4d20e60b5df16228f3a3699d16ed2b1dddcceb2b
(cherry picked from commit 4af712e8df998475736f3e2727701bd31e3751a9)

drivers/char/random.c
include/linux/random.h
lib/random32.c

index 3eba5b24ae5f892c204d818a5eca359ef51b71d0..ad6465795698449984f47968067f9e8a888db038 100644 (file)
@@ -614,8 +614,11 @@ retry:
 
        if (!r->initialized && nbits > 0) {
                r->entropy_total += nbits;
-               if (r->entropy_total > 128)
+               if (r->entropy_total > 128) {
                        r->initialized = 1;
+                       if (r == &nonblocking_pool)
+                               prandom_reseed_late();
+               }
        }
 
        trace_credit_entropy_bits(r->name, nbits, entropy_count,
index 8795f23507d8c41f0acebf11c981953ab5adb15a..bbf19524d3f4ee0d7d6197218ab8f54fa3fd0b92 100644 (file)
@@ -29,6 +29,7 @@ unsigned long randomize_range(unsigned long start, unsigned long end, unsigned l
 u32 prandom_u32(void);
 void prandom_bytes(void *buf, int nbytes);
 void prandom_seed(u32 seed);
+void prandom_reseed_late(void);
 
 u32 prandom_u32_state(struct rnd_state *);
 void prandom_bytes_state(struct rnd_state *state, void *buf, int nbytes);
index ee901bfb222d643176ae04c33dfebb158905132b..afea9d4bb17e45731d8c0e55c270a6a43f7cdaa8 100644 (file)
@@ -197,9 +197,17 @@ static DEFINE_TIMER(seed_timer, __prandom_timer, 0, 0);
  *     Generate better values after random number generator
  *     is fully initialized.
  */
-static int __init prandom_reseed(void)
+static void __prandom_reseed(bool late)
 {
        int i;
+       unsigned long flags;
+       static bool latch = false;
+       static DEFINE_SPINLOCK(lock);
+       /* only allow initial seeding (late == false) once */
+       spin_lock_irqsave(&lock, flags);
+       if (latch && !late)
+               goto out;
+       latch = true;
 
        for_each_possible_cpu(i) {
                struct rnd_state *state = &per_cpu(net_rand_state,i);
@@ -213,6 +221,18 @@ static int __init prandom_reseed(void)
                /* mix it in */
                prandom_u32_state(state);
        }
+out:
+       spin_unlock_irqrestore(&lock, flags);
+}
+
+void prandom_reseed_late(void)
+{
+       __prandom_reseed(true);
+}
+
+static int __init prandom_reseed(void)
+{
+       __prandom_reseed(false);
        prandom_start_seed_timer();
        return 0;
 }