From: "Theodore Ts'o" This patch adds a separate pool for use with /dev/urandom. This prevents a /dev/urandom read from being able to completely drain the entropy in the /dev/random pool, and also makes it much more difficult for an attacker to carry out a state extension attack. Signed-off-by: Andrew Morton --- 25-akpm/drivers/char/random.c | 36 +++++++++++++++++++++++++++--------- 1 files changed, 27 insertions(+), 9 deletions(-) diff -puN drivers/char/random.c~dev-random-use-separate-entropy-store-for-dev-urandom drivers/char/random.c --- 25/drivers/char/random.c~dev-random-use-separate-entropy-store-for-dev-urandom 2004-08-19 23:36:20.239635000 -0700 +++ 25-akpm/drivers/char/random.c 2004-08-19 23:36:20.244634240 -0700 @@ -401,6 +401,7 @@ static struct poolinfo { */ static struct entropy_store *random_state; /* The default global store */ static struct entropy_store *sec_random_state; /* secondary store */ +static struct entropy_store *urandom_state; /* For urandom */ static DECLARE_WAIT_QUEUE_HEAD(random_read_wait); static DECLARE_WAIT_QUEUE_HEAD(random_write_wait); @@ -1467,14 +1468,21 @@ static ssize_t extract_entropy(struct en */ void get_random_bytes(void *buf, int nbytes) { - if (sec_random_state) - extract_entropy(sec_random_state, (char *) buf, nbytes, - EXTRACT_ENTROPY_SECONDARY); - else if (random_state) - extract_entropy(random_state, (char *) buf, nbytes, 0); - else + struct entropy_store *r = urandom_state; + int flags = EXTRACT_ENTROPY_SECONDARY; + + if (!r) + r = sec_random_state; + if (!r) { + r = random_state; + flags = 0; + } + if (!r) { printk(KERN_NOTICE "get_random_bytes called before " "random driver initialization\n"); + return; + } + extract_entropy(r, (char *) buf, nbytes, flags); } EXPORT_SYMBOL(get_random_bytes); @@ -1525,8 +1533,12 @@ static int __init rand_initialize(void) if (create_entropy_store(SECONDARY_POOL_SIZE, "secondary", &sec_random_state)) goto err; + if (create_entropy_store(SECONDARY_POOL_SIZE, "urandom", + &urandom_state)) + goto err; clear_entropy_store(random_state); clear_entropy_store(sec_random_state); + clear_entropy_store(urandom_state); init_std_data(random_state); init_std_data(sec_random_state); #ifdef CONFIG_SYSCTL @@ -1661,9 +1673,15 @@ static ssize_t urandom_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos) { - return extract_entropy(sec_random_state, buf, nbytes, - EXTRACT_ENTROPY_USER | - EXTRACT_ENTROPY_SECONDARY); + int flags = EXTRACT_ENTROPY_USER; + unsigned long cpuflags; + + spin_lock_irqsave(&random_state->lock, cpuflags); + if (random_state->entropy_count > random_state->poolinfo.POOLBITS) + flags |= EXTRACT_ENTROPY_SECONDARY; + spin_unlock_irqrestore(&random_state->lock, cpuflags); + + return extract_entropy(urandom_state, buf, nbytes, flags); } static unsigned int _