[PATCH 13/14] random: count only catastrophic reseeds forinitialization

From: Greg Price
Date: Sat Dec 14 2013 - 21:02:10 EST


In the earlier commit "random: direct all routine input via input pool",
we made sure that input comes in large reseeds which should be big
enough to prevent an attacker from brute-forcing any one of them.
This is important because a succession of small reseeds, if
interspersed with output an attacker sees, could be brute-forced one
by one. Now update our accounting accordingly so that we track the
largest single reseed, rather than the total of potentially small
reseeds, and call ourselves initialized only with one large reseed.

This shouldn't make much difference with the current code, as we
don't make repeated small reseeds anyway, but it's best to be clear.

Rename entropy_total to seed_entropy_bits to reflect its new function.

While touching the not-yet-initialized warnings, checkpatch complains
about printk(KERN_NOTICE, ...), so switch to pr_notice etc.

Signed-off-by: Greg Price <price@xxxxxxx>
---
drivers/char/random.c | 24 ++++++++++++------------
include/trace/events/random.h | 13 +++++++------
2 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index b354fd15f..855e401e5 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -432,7 +432,7 @@ struct entropy_store {
unsigned short input_rotate;
int entropy_count;
int entropy_since_push;
- int entropy_total;
+ int seed_entropy_bits;
unsigned int initialized:1;
unsigned int limit:1;
unsigned int last_data_init:1;
@@ -670,8 +670,9 @@ retry:
goto retry;

if (r == &nonblocking_pool) {
- r->entropy_total += nbits;
- if (!r->initialized && r->entropy_total >= min_reseed_bits) {
+ r->seed_entropy_bits = max(nbits, r->seed_entropy_bits);
+ if (!r->initialized &&
+ r->seed_entropy_bits >= min_reseed_bits) {
r->initialized = 1;
prandom_reseed_late();
pr_notice("random: %s pool is initialized\n", r->name);
@@ -681,7 +682,7 @@ retry:
trace_credit_entropy_bits(r->name, nbits,
entropy_count >> ENTROPY_SHIFT,
r->entropy_since_push,
- r->entropy_total, _RET_IP_);
+ r->seed_entropy_bits, _RET_IP_);

if (r == &input_pool) {
int entropy_bits = entropy_count >> ENTROPY_SHIFT;
@@ -944,7 +945,7 @@ static void account_xfer(struct entropy_store *dest, int nbytes,
* pool, except if we're hardly seeded at all, we'll
* settle for enough to double what we have. */
*min_bytes = min(min_reseed_bits / 8,
- (dest->entropy_total+7) / 8);
+ (2*dest->seed_entropy_bits + 7) / 8);
}

/* Reserve a reseed's worth for the nonblocking pool early on
@@ -1215,10 +1216,9 @@ void get_random_bytes(void *buf, int nbytes)
{
#if DEBUG_RANDOM_BOOT > 0
if (unlikely(nonblocking_pool.initialized == 0))
- printk(KERN_NOTICE "random: %pF get_random_bytes called "
- "with %d bits of entropy available\n",
- (void *) _RET_IP_,
- nonblocking_pool.entropy_total);
+ pr_notice(
+ "random: %pF get_random_bytes called with only %d bits of seed entropy available\n",
+ (void *) _RET_IP_, nonblocking_pool.seed_entropy_bits);
#endif
trace_get_random_bytes(nbytes, _RET_IP_);
extract_entropy(&nonblocking_pool, buf, nbytes, NULL, NULL);
@@ -1355,9 +1355,9 @@ urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
int ret;

if (unlikely(nonblocking_pool.initialized == 0))
- printk_once(KERN_NOTICE "random: %s urandom read "
- "with %d bits of entropy available\n",
- current->comm, nonblocking_pool.entropy_total);
+ pr_notice_once(
+ "random: %s urandom read with only %d bits of seed entropy available\n",
+ current->comm, nonblocking_pool.seed_entropy_bits);

ret = extract_entropy_user(&nonblocking_pool, buf, nbytes);

diff --git a/include/trace/events/random.h b/include/trace/events/random.h
index 4edf5ceb5..d07a80146 100644
--- a/include/trace/events/random.h
+++ b/include/trace/events/random.h
@@ -61,17 +61,18 @@ DEFINE_EVENT(random__mix_pool_bytes, mix_pool_bytes_nolock,

TRACE_EVENT(credit_entropy_bits,
TP_PROTO(const char *pool_name, int bits, int entropy_count,
- int entropy_since_push, int entropy_total, unsigned long IP),
+ int entropy_since_push, int seed_entropy_bits,
+ unsigned long IP),

TP_ARGS(pool_name, bits, entropy_count, entropy_since_push,
- entropy_total, IP),
+ seed_entropy_bits, IP),

TP_STRUCT__entry(
__field( const char *, pool_name )
__field( int, bits )
__field( int, entropy_count )
__field( int, entropy_since_push )
- __field( int, entropy_total )
+ __field( int, seed_entropy_bits )
__field(unsigned long, IP )
),

@@ -80,14 +81,14 @@ TRACE_EVENT(credit_entropy_bits,
__entry->bits = bits;
__entry->entropy_count = entropy_count;
__entry->entropy_since_push = entropy_since_push;
- __entry->entropy_total = entropy_total;
+ __entry->seed_entropy_bits = seed_entropy_bits;
__entry->IP = IP;
),

TP_printk("%s pool: bits %d entropy_count %d entropy_since_push %d "
- "entropy_total %d caller %pF", __entry->pool_name,
+ "seed_entropy_bits %d caller %pF", __entry->pool_name,
__entry->bits, __entry->entropy_count,
- __entry->entropy_since_push, __entry->entropy_total,
+ __entry->entropy_since_push, __entry->seed_entropy_bits,
(void *)__entry->IP)
);

--
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/