diff options
| author | John Denker <jsd@av8n.com> | 2013-10-09 13:46:28 -0700 | 
|---|---|---|
| committer | John Denker <jsd@av8n.com> | 2013-10-18 05:33:22 -0700 | 
| commit | 67c471f7fd31c53073b5c04c9555a882a1c5a7e9 (patch) | |
| tree | cc70b898a8aaf3ec70e24321b55e6cbd97fb85ee | |
| parent | 9475e3f6f0216f22c5d04602e7194b8d86c73e51 (diff) | |
total entropy available;
extraload blocking pool
| -rw-r--r-- | drivers/char/random.c | 88 | 
1 files changed, 49 insertions, 39 deletions
| diff --git a/drivers/char/random.c b/drivers/char/random.c index d1a0acd..157a0b3 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -428,7 +428,7 @@ static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);  static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);  static struct fasync_struct *fasync; -static bool debug; +static bool debug = 0;  module_param(debug, bool, 0644);  #define DEBUG_ENT(fmt, arg...) do { \  	if (debug) \ @@ -471,11 +471,6 @@ struct entropy_store {  static __u32 input_pool_data[INPUT_POOL_WORDS];  static __u32 blocking_pool_data[OUTPUT_POOL_WORDS];  static __u32 nonblocking_pool_data[OUTPUT_POOL_WORDS]; -#ifdef NOTUSED -  static ulonglong uint64_zero = 0; -  static ulonglong uint64_max  = ~((ulonglong)0); -#endif -static ulonglong play = sizeof(ulonglong)*10000 + sizeof(ulong)*100 + sizeof(int);  static struct entropy_store input_pool = {  	.poolinfo = &poolinfo_table[0], @@ -856,24 +851,34 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,   * In principle, this would cascade, pulling from other pools   * even farther upstream, but as it stands there are only two   * pools, so no cascade. + * + * It is conceivable that the caller's want_level could exceed + * POOL_BYTES, and this would not be ridiculous. + * Mild fixme:  Handling of this case needs more thought.   */  static void fill_pool(          struct entropy_store *r, -        size_t want_level           /* measured in bytes */ +        size_t want_level               /* measured in BYTES */  ){  	__u32 tmp[OUTPUT_POOL_WORDS]; -        int rsvd = 0;                   /* measured in bits */ -        int mybatch = 0; +        int rsvd;                       /* measured in bits */ +        int txbits; +        int mybatch;          int actual;                     /* measured in BYTES */ -        int txbits = BYTE2BIT(want_level) - r->entropy_count; -        if (r->entropy_count >= r->poolinfo->POOLBITS) return; /* already full */ +        int headspace = r->poolinfo->POOLBITS - r->entropy_count;  	if (!r->pull) return;           /* no upstream pool to pull from */          if (r->limit) { -          /* -           * Use the values from the declarations, above. -           */ -           // FIXME:  Think about increasing the request -           // when entropy if pleniful. +/* Here if we are limited i.e. blocking i.e. /dev/random i.e. TRNG. */ +                int pullhead = r->pull->poolinfo->POOLBITS - r->pull->entropy_count; +/* Only the top 500 bits are free for extraloading: */ +                int extraload = 500 - pullhead; +/* Don't extraload more than needed to fill the headspace: */ +                extraload = min_t(int, extraload, headspace); +                txbits = BYTE2BIT(want_level) - r->entropy_count; +/* Load what is actually requested, or extraload whatever is freely available: */ +                txbits =  max_t(int, txbits, extraload); +                if (txbits <= 0) return;        /* already have all we want */ +                mybatch = rsvd = 0;          } else {  /*   * Here if we are non-limited i.e. non-blocking i.e. urandom i.e. PRNG. @@ -894,17 +899,18 @@ static void fill_pool(            rsvd = rsvd - appetite*rsvd/20;            if (rsvd < 0) rsvd = 0;  /* For the PRNG, make the request big enough to be "significant" to any attacker: */ -          mybatch = RESEED_BATCH; +          mybatch = txbits = RESEED_BATCH;          } -        txbits = max_t(int, txbits, mybatch); -        /* but never more than our buffer size */ +        /* Don't request more than fits in our buffer: */          txbits = min_t(int, txbits, 8*sizeof(tmp)); -        DEBUG_ENT("About to reseed %s adding %d bits; " -                  "caller want_level: %zu  prev level: %d\n", +        DEBUG_ENT("About to reseed %s adding %d bits;" +                  "  caller want_level: %zu  prev level: %d" +                  "  batch: %d  rsvd: %d\n",                    r->name, txbits, -                  want_level * 8, r->entropy_count); +                  want_level * 8, r->entropy_count, +                  BIT2BYTE(mybatch), BIT2BYTE(rsvd));          if (txbits < 0) return;         /* already full enough */          actual = extract_entropy(r->pull, tmp, BIT2BYTE(txbits), @@ -1405,7 +1411,9 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)  	switch (cmd) {  	case RNDGETENTCNT:  		/* inherently racy, no point locking */ -		if (put_user(input_pool.entropy_count, p)) +		if (put_user(input_pool.entropy_count +                        + blocking_pool.entropy_count +                     + nonblocking_pool.entropy_count, p))  			return -EFAULT;  		return 0;  	case RNDADDTOENTCNT: @@ -1536,6 +1544,15 @@ static int proc_do_uuid(struct ctl_table *table, int write,  	return proc_dostring(&fake_table, write, buffer, lenp, ppos);  } +static int total_entropy_count; +static int sum_entropy_count(struct ctl_table *table, int write, +			void __user *buffer, size_t *lenp, loff_t *ppos){ +        total_entropy_count = input_pool.entropy_count +                         + blocking_pool.entropy_count +                      + nonblocking_pool.entropy_count; +	return proc_dointvec(table, write, buffer, lenp, ppos); +} +  static int sysctl_poolsize = INPUT_POOL_WORDS * 32;  extern struct ctl_table random_table[];  struct ctl_table random_table[] = { @@ -1550,6 +1567,13 @@ struct ctl_table random_table[] = {  		.procname	= "entropy_avail",  		.maxlen		= sizeof(int),  		.mode		= 0444, +		.proc_handler	= sum_entropy_count, +		.data		= &total_entropy_count, +	}, +	{ +		.procname	= "entropy_avail_inp", +		.maxlen		= sizeof(int), +		.mode		= 0444,  		.proc_handler	= proc_dointvec,  		.data		= &input_pool.entropy_count,  	}, @@ -1568,21 +1592,7 @@ struct ctl_table random_table[] = {  		.data		= &nonblocking_pool.entropy_count,  	},  	{ -		.procname	= "play_int", -		.maxlen		= sizeof(ulonglong), -		.mode		= 0644, -		.proc_handler	= proc_dointvec, -		.data		= &play, -	}, -	{ -		.procname	= "play_long", -		.maxlen		= sizeof(ulonglong), -		.mode		= 0644, -		.proc_handler	= proc_doulonglongvec_minmax, -		.data		= &play, -	}, -	{ -		.procname	= "extracted_total", +		.procname	= "extracted_total_inp",  		.maxlen		= sizeof(ulonglong),  		.mode		= 0644,  		.proc_handler	= proc_doulonglongvec_minmax, @@ -1603,7 +1613,7 @@ struct ctl_table random_table[] = {  		.data		= &nonblocking_pool.extracted_total,  	},  	{ -		.procname	= "extracted_subttl", +		.procname	= "extracted_subttl_inp",  		.maxlen		= sizeof(ulonglong),  		.mode		= 0644,  		.proc_handler	= proc_doulonglongvec_minmax, | 
