aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/random.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/random.c')
-rw-r--r--drivers/char/random.c30
1 files changed, 21 insertions, 9 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 4ad71ef2cd59..71529e196b84 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -641,7 +641,7 @@ retry:
641 } while (unlikely(entropy_count < pool_size-2 && pnfrac)); 641 } while (unlikely(entropy_count < pool_size-2 && pnfrac));
642 } 642 }
643 643
644 if (entropy_count < 0) { 644 if (unlikely(entropy_count < 0)) {
645 pr_warn("random: negative entropy/overflow: pool %s count %d\n", 645 pr_warn("random: negative entropy/overflow: pool %s count %d\n",
646 r->name, entropy_count); 646 r->name, entropy_count);
647 WARN_ON(1); 647 WARN_ON(1);
@@ -980,26 +980,37 @@ static void push_to_pool(struct work_struct *work)
980static size_t account(struct entropy_store *r, size_t nbytes, int min, 980static size_t account(struct entropy_store *r, size_t nbytes, int min,
981 int reserved) 981 int reserved)
982{ 982{
983 int have_bytes;
984 int entropy_count, orig; 983 int entropy_count, orig;
985 size_t ibytes; 984 size_t ibytes, nfrac;
986 985
987 BUG_ON(r->entropy_count > r->poolinfo->poolfracbits); 986 BUG_ON(r->entropy_count > r->poolinfo->poolfracbits);
988 987
989 /* Can we pull enough? */ 988 /* Can we pull enough? */
990retry: 989retry:
991 entropy_count = orig = ACCESS_ONCE(r->entropy_count); 990 entropy_count = orig = ACCESS_ONCE(r->entropy_count);
992 have_bytes = entropy_count >> (ENTROPY_SHIFT + 3);
993 ibytes = nbytes; 991 ibytes = nbytes;
994 /* If limited, never pull more than available */ 992 /* If limited, never pull more than available */
995 if (r->limit) 993 if (r->limit) {
996 ibytes = min_t(size_t, ibytes, have_bytes - reserved); 994 int have_bytes = entropy_count >> (ENTROPY_SHIFT + 3);
995
996 if ((have_bytes -= reserved) < 0)
997 have_bytes = 0;
998 ibytes = min_t(size_t, ibytes, have_bytes);
999 }
997 if (ibytes < min) 1000 if (ibytes < min)
998 ibytes = 0; 1001 ibytes = 0;
999 if (have_bytes >= ibytes + reserved) 1002
1000 entropy_count -= ibytes << (ENTROPY_SHIFT + 3); 1003 if (unlikely(entropy_count < 0)) {
1004 pr_warn("random: negative entropy count: pool %s count %d\n",
1005 r->name, entropy_count);
1006 WARN_ON(1);
1007 entropy_count = 0;
1008 }
1009 nfrac = ibytes << (ENTROPY_SHIFT + 3);
1010 if ((size_t) entropy_count > nfrac)
1011 entropy_count -= nfrac;
1001 else 1012 else
1002 entropy_count = reserved << (ENTROPY_SHIFT + 3); 1013 entropy_count = 0;
1003 1014
1004 if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig) 1015 if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
1005 goto retry; 1016 goto retry;
@@ -1375,6 +1386,7 @@ urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
1375 "with %d bits of entropy available\n", 1386 "with %d bits of entropy available\n",
1376 current->comm, nonblocking_pool.entropy_total); 1387 current->comm, nonblocking_pool.entropy_total);
1377 1388
1389 nbytes = min_t(size_t, nbytes, INT_MAX >> (ENTROPY_SHIFT + 3));
1378 ret = extract_entropy_user(&nonblocking_pool, buf, nbytes); 1390 ret = extract_entropy_user(&nonblocking_pool, buf, nbytes);
1379 1391
1380 trace_urandom_read(8 * nbytes, ENTROPY_BITS(&nonblocking_pool), 1392 trace_urandom_read(8 * nbytes, ENTROPY_BITS(&nonblocking_pool),