Skip to content

Commit

Permalink
BACKPORT: random32: add prandom_reseed_late() and call when nonblocki…
Browse files Browse the repository at this point in the history
…ng 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)
  • Loading branch information
strssndktn authored and chautruongthinh committed Dec 17, 2017
1 parent d8bcf67 commit d12f6a8
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 2 deletions.
16 changes: 15 additions & 1 deletion drivers/char/random.c
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,21 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
entropy_count = 0;
} else if (entropy_count > r->poolinfo->POOLBITS)
entropy_count = r->poolinfo->POOLBITS;
r->entropy_count = entropy_count;

if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
goto retry;

if (!r->initialized && nbits > 0) {
r->entropy_total += nbits;
if (r->entropy_total > 128) {
r->initialized = 1;
if (r == &nonblocking_pool)
prandom_reseed_late();
}
}

trace_credit_entropy_bits(r->name, nbits, entropy_count,
r->entropy_total, _RET_IP_);

/* should we wake readers? */
if (r == &input_pool && entropy_count >= random_read_wakeup_thresh) {
Expand Down
1 change: 1 addition & 0 deletions include/linux/random.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,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);

/*
* These macros are preserved for backward compatibility and should be
Expand Down
23 changes: 22 additions & 1 deletion lib/random32.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,18 @@ static void prandom_start_seed_timer(void)
* 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);
Expand All @@ -216,6 +225,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;
}
Expand Down

0 comments on commit d12f6a8

Please sign in to comment.