Commit f5c2742c authored by Theodore Ts'o's avatar Theodore Ts'o
Browse files

random: cap the rate which the /dev/urandom pool gets reseeded



In order to avoid draining the input pool of its entropy at too high
of a rate, enforce a minimum time interval between reseedings of the
urandom pool.  This is set to 60 seconds by default.

Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
parent c59974ae
Loading
Loading
Loading
Loading
+24 −0
Original line number Original line Diff line number Diff line
@@ -306,6 +306,13 @@ static int random_read_wakeup_thresh = 64;
 */
 */
static int random_write_wakeup_thresh = 128;
static int random_write_wakeup_thresh = 128;


/*
 * The minimum number of seconds between urandom pool resending.  We
 * do this to limit the amount of entropy that can be drained from the
 * input pool even if there are heavy demands on /dev/urandom.
 */
static int random_min_urandom_seed = 60;

/*
/*
 * When the input pool goes over trickle_thresh, start dropping most
 * When the input pool goes over trickle_thresh, start dropping most
 * samples to avoid wasting CPU time and reduce lock contention.
 * samples to avoid wasting CPU time and reduce lock contention.
@@ -438,6 +445,7 @@ struct entropy_store {
	struct entropy_store *pull;
	struct entropy_store *pull;


	/* read-write data: */
	/* read-write data: */
	unsigned long last_pulled;
	spinlock_t lock;
	spinlock_t lock;
	unsigned short add_ptr;
	unsigned short add_ptr;
	unsigned short input_rotate;
	unsigned short input_rotate;
@@ -887,6 +895,14 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
{
{
	__u32	tmp[OUTPUT_POOL_WORDS];
	__u32	tmp[OUTPUT_POOL_WORDS];


	if (r->limit == 0 && random_min_urandom_seed) {
		unsigned long now = jiffies;

		if (time_before(now,
				r->last_pulled + random_min_urandom_seed * HZ))
			return;
		r->last_pulled = now;
	}
	if (r->pull &&
	if (r->pull &&
	    r->entropy_count < (nbytes << (ENTROPY_SHIFT + 3)) &&
	    r->entropy_count < (nbytes << (ENTROPY_SHIFT + 3)) &&
	    r->entropy_count < r->poolinfo->poolfracbits) {
	    r->entropy_count < r->poolinfo->poolfracbits) {
@@ -1190,6 +1206,7 @@ static void init_std_data(struct entropy_store *r)
	r->entropy_count = 0;
	r->entropy_count = 0;
	r->entropy_total = 0;
	r->entropy_total = 0;
	r->last_data_init = 0;
	r->last_data_init = 0;
	r->last_pulled = jiffies;
	mix_pool_bytes(r, &now, sizeof(now), NULL);
	mix_pool_bytes(r, &now, sizeof(now), NULL);
	for (i = r->poolinfo->poolbytes; i > 0; i -= sizeof(rv)) {
	for (i = r->poolinfo->poolbytes; i > 0; i -= sizeof(rv)) {
		if (!arch_get_random_long(&rv))
		if (!arch_get_random_long(&rv))
@@ -1540,6 +1557,13 @@ struct ctl_table random_table[] = {
		.extra1		= &min_write_thresh,
		.extra1		= &min_write_thresh,
		.extra2		= &max_write_thresh,
		.extra2		= &max_write_thresh,
	},
	},
	{
		.procname	= "urandom_min_reseed_secs",
		.data		= &random_min_urandom_seed,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec,
	},
	{
	{
		.procname	= "boot_id",
		.procname	= "boot_id",
		.data		= &sysctl_bootid,
		.data		= &sysctl_bootid,