Merge tag 'stable/for-linus-3.15-rc5-tag' of git://git.kernel.org/pub/scm/linux/kerne...
[firefly-linux-kernel-4.4.55.git] / drivers / char / random.c
index 2c532a6b0a219f53244ee0ef2c0fdb08195027e8..102c50d38902ca43fed85641618ba202a7251679 100644 (file)
  * The minimum number of bits of entropy before we wake up a read on
  * /dev/random.  Should be enough to do a significant reseed.
  */
-static int random_read_wakeup_thresh = 64;
+static int random_read_wakeup_bits = 64;
 
 /*
  * If the entropy count falls under this number of bits, then we
  * should wake up processes which are selecting or polling on write
  * access to /dev/random.
  */
-static int random_write_wakeup_thresh = 28 * OUTPUT_POOL_WORDS;
+static int random_write_wakeup_bits = 28 * OUTPUT_POOL_WORDS;
 
 /*
  * The minimum number of seconds between urandom pool reseeding.  We
@@ -666,10 +666,10 @@ retry:
                                  r->entropy_total, _RET_IP_);
 
        if (r == &input_pool) {
-               int entropy_bytes = entropy_count >> ENTROPY_SHIFT;
+               int entropy_bits = entropy_count >> ENTROPY_SHIFT;
 
                /* should we wake readers? */
-               if (entropy_bytes >= random_read_wakeup_thresh) {
+               if (entropy_bits >= random_read_wakeup_bits) {
                        wake_up_interruptible(&random_read_wait);
                        kill_fasync(&fasync, SIGIO, POLL_IN);
                }
@@ -678,9 +678,9 @@ retry:
                 * forth between them, until the output pools are 75%
                 * full.
                 */
-               if (entropy_bytes > random_write_wakeup_thresh &&
+               if (entropy_bits > random_write_wakeup_bits &&
                    r->initialized &&
-                   r->entropy_total >= 2*random_read_wakeup_thresh) {
+                   r->entropy_total >= 2*random_read_wakeup_bits) {
                        static struct entropy_store *last = &blocking_pool;
                        struct entropy_store *other = &blocking_pool;
 
@@ -844,6 +844,8 @@ void add_interrupt_randomness(int irq, int irq_flags)
        cycles_t                cycles = random_get_entropy();
        __u32                   input[4], c_high, j_high;
        __u64                   ip;
+       unsigned long           seed;
+       int                     credit;
 
        c_high = (sizeof(cycles) > 4) ? cycles >> 32 : 0;
        j_high = (sizeof(now) > 4) ? now >> 32 : 0;
@@ -862,20 +864,33 @@ void add_interrupt_randomness(int irq, int irq_flags)
 
        r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
        __mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool), NULL);
+
        /*
         * If we don't have a valid cycle counter, and we see
         * back-to-back timer interrupts, then skip giving credit for
-        * any entropy.
+        * any entropy, otherwise credit 1 bit.
         */
+       credit = 1;
        if (cycles == 0) {
                if (irq_flags & __IRQF_TIMER) {
                        if (fast_pool->last_timer_intr)
-                               return;
+                               credit = 0;
                        fast_pool->last_timer_intr = 1;
                } else
                        fast_pool->last_timer_intr = 0;
        }
-       credit_entropy_bits(r, 1);
+
+       /*
+        * If we have architectural seed generator, produce a seed and
+        * add it to the pool.  For the sake of paranoia count it as
+        * 50% entropic.
+        */
+       if (arch_get_random_seed_long(&seed)) {
+               __mix_pool_bytes(r, &seed, sizeof(seed), NULL);
+               credit += sizeof(seed) * 4;
+       }
+
+       credit_entropy_bits(r, credit);
 }
 
 #ifdef CONFIG_BLOCK
@@ -924,19 +939,19 @@ static void _xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
 {
        __u32   tmp[OUTPUT_POOL_WORDS];
 
-       /* For /dev/random's pool, always leave two wakeup worth's BITS */
-       int rsvd = r->limit ? 0 : random_read_wakeup_thresh/4;
+       /* For /dev/random's pool, always leave two wakeups' worth */
+       int rsvd_bytes = r->limit ? 0 : random_read_wakeup_bits / 4;
        int bytes = nbytes;
 
-       /* pull at least as many as BYTES as wakeup BITS */
-       bytes = max_t(int, bytes, random_read_wakeup_thresh / 8);
+       /* pull at least as much as a wakeup */
+       bytes = max_t(int, bytes, random_read_wakeup_bits / 8);
        /* but never more than the buffer size */
        bytes = min_t(int, bytes, sizeof(tmp));
 
        trace_xfer_secondary_pool(r->name, bytes * 8, nbytes * 8,
                                  ENTROPY_BITS(r), ENTROPY_BITS(r->pull));
        bytes = extract_entropy(r->pull, tmp, bytes,
-                               random_read_wakeup_thresh / 8, rsvd);
+                               random_read_wakeup_bits / 8, rsvd_bytes);
        mix_pool_bytes(r, tmp, bytes, NULL);
        credit_entropy_bits(r, bytes*8);
 }
@@ -952,7 +967,7 @@ static void push_to_pool(struct work_struct *work)
        struct entropy_store *r = container_of(work, struct entropy_store,
                                              push_work);
        BUG_ON(!r);
-       _xfer_secondary_pool(r, random_read_wakeup_thresh/8);
+       _xfer_secondary_pool(r, random_read_wakeup_bits/8);
        trace_push_to_pool(r->name, r->entropy_count >> ENTROPY_SHIFT,
                           r->pull->entropy_count >> ENTROPY_SHIFT);
 }
@@ -964,15 +979,10 @@ static void push_to_pool(struct work_struct *work)
 static size_t account(struct entropy_store *r, size_t nbytes, int min,
                      int reserved)
 {
-       unsigned long flags;
-       int wakeup_write = 0;
        int have_bytes;
        int entropy_count, orig;
        size_t ibytes;
 
-       /* Hold lock while accounting */
-       spin_lock_irqsave(&r->lock, flags);
-
        BUG_ON(r->entropy_count > r->poolinfo->poolfracbits);
 
        /* Can we pull enough? */
@@ -980,29 +990,22 @@ retry:
        entropy_count = orig = ACCESS_ONCE(r->entropy_count);
        have_bytes = entropy_count >> (ENTROPY_SHIFT + 3);
        ibytes = nbytes;
-       if (have_bytes < min + reserved) {
+       /* If limited, never pull more than available */
+       if (r->limit)
+               ibytes = min_t(size_t, ibytes, have_bytes - reserved);
+       if (ibytes < min)
                ibytes = 0;
-       } else {
-               /* If limited, never pull more than available */
-               if (r->limit && ibytes + reserved >= have_bytes)
-                       ibytes = have_bytes - reserved;
-
-               if (have_bytes >= ibytes + reserved)
-                       entropy_count -= ibytes << (ENTROPY_SHIFT + 3);
-               else
-                       entropy_count = reserved << (ENTROPY_SHIFT + 3);
+       if (have_bytes >= ibytes + reserved)
+               entropy_count -= ibytes << (ENTROPY_SHIFT + 3);
+       else
+               entropy_count = reserved << (ENTROPY_SHIFT + 3);
 
-               if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
-                       goto retry;
-
-               if ((r->entropy_count >> ENTROPY_SHIFT)
-                   < random_write_wakeup_thresh)
-                       wakeup_write = 1;
-       }
-       spin_unlock_irqrestore(&r->lock, flags);
+       if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
+               goto retry;
 
        trace_debit_entropy(r->name, 8 * ibytes);
-       if (wakeup_write) {
+       if (ibytes &&
+           (r->entropy_count >> ENTROPY_SHIFT) < random_write_wakeup_bits) {
                wake_up_interruptible(&random_write_wait);
                kill_fasync(&fasync, SIGIO, POLL_OUT);
        }
@@ -1027,23 +1030,23 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
        __u8 extract[64];
        unsigned long flags;
 
-       /* Generate a hash across the pool, 16 words (512 bits) at a time */
-       sha_init(hash.w);
-       spin_lock_irqsave(&r->lock, flags);
-       for (i = 0; i < r->poolinfo->poolwords; i += 16)
-               sha_transform(hash.w, (__u8 *)(r->pool + i), workspace);
-
        /*
         * If we have an architectural hardware random number
-        * generator, mix that in, too.
+        * generator, use it for SHA's initial vector
         */
+       sha_init(hash.w);
        for (i = 0; i < LONGS(20); i++) {
                unsigned long v;
                if (!arch_get_random_long(&v))
                        break;
-               hash.l[i] ^= v;
+               hash.l[i] = v;
        }
 
+       /* Generate a hash across the pool, 16 words (512 bits) at a time */
+       spin_lock_irqsave(&r->lock, flags);
+       for (i = 0; i < r->poolinfo->poolwords; i += 16)
+               sha_transform(hash.w, (__u8 *)(r->pool + i), workspace);
+
        /*
         * We mix the hash back into the pool to prevent backtracking
         * attacks (where the attacker knows the state of the pool
@@ -1250,7 +1253,8 @@ static void init_std_data(struct entropy_store *r)
        r->last_pulled = jiffies;
        mix_pool_bytes(r, &now, sizeof(now), NULL);
        for (i = r->poolinfo->poolbytes; i > 0; i -= sizeof(rv)) {
-               if (!arch_get_random_long(&rv))
+               if (!arch_get_random_seed_long(&rv) &&
+                   !arch_get_random_long(&rv))
                        rv = random_get_entropy();
                mix_pool_bytes(r, &rv, sizeof(rv), NULL);
        }
@@ -1293,6 +1297,37 @@ void rand_initialize_disk(struct gendisk *disk)
 }
 #endif
 
+/*
+ * Attempt an emergency refill using arch_get_random_seed_long().
+ *
+ * As with add_interrupt_randomness() be paranoid and only
+ * credit the output as 50% entropic.
+ */
+static int arch_random_refill(void)
+{
+       const unsigned int nlongs = 64; /* Arbitrary number */
+       unsigned int n = 0;
+       unsigned int i;
+       unsigned long buf[nlongs];
+
+       if (!arch_has_random_seed())
+               return 0;
+
+       for (i = 0; i < nlongs; i++) {
+               if (arch_get_random_seed_long(&buf[n]))
+                       n++;
+       }
+
+       if (n) {
+               unsigned int rand_bytes = n * sizeof(unsigned long);
+
+               mix_pool_bytes(&input_pool, buf, rand_bytes, NULL);
+               credit_entropy_bits(&input_pool, rand_bytes*4);
+       }
+
+       return n;
+}
+
 static ssize_t
 random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
 {
@@ -1311,14 +1346,19 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
                                  ENTROPY_BITS(&input_pool));
                if (n > 0)
                        return n;
+
                /* Pool is (near) empty.  Maybe wait and retry. */
 
+               /* First try an emergency refill */
+               if (arch_random_refill())
+                       continue;
+
                if (file->f_flags & O_NONBLOCK)
                        return -EAGAIN;
 
                wait_event_interruptible(random_read_wait,
                        ENTROPY_BITS(&input_pool) >=
-                       random_read_wakeup_thresh);
+                       random_read_wakeup_bits);
                if (signal_pending(current))
                        return -ERESTARTSYS;
        }
@@ -1349,9 +1389,9 @@ random_poll(struct file *file, poll_table * wait)
        poll_wait(file, &random_read_wait, wait);
        poll_wait(file, &random_write_wait, wait);
        mask = 0;
-       if (ENTROPY_BITS(&input_pool) >= random_read_wakeup_thresh)
+       if (ENTROPY_BITS(&input_pool) >= random_read_wakeup_bits)
                mask |= POLLIN | POLLRDNORM;
-       if (ENTROPY_BITS(&input_pool) < random_write_wakeup_thresh)
+       if (ENTROPY_BITS(&input_pool) < random_write_wakeup_bits)
                mask |= POLLOUT | POLLWRNORM;
        return mask;
 }
@@ -1498,7 +1538,7 @@ EXPORT_SYMBOL(generate_random_uuid);
 #include <linux/sysctl.h>
 
 static int min_read_thresh = 8, min_write_thresh;
-static int max_read_thresh = INPUT_POOL_WORDS * 32;
+static int max_read_thresh = OUTPUT_POOL_WORDS * 32;
 static int max_write_thresh = INPUT_POOL_WORDS * 32;
 static char sysctl_bootid[16];
 
@@ -1574,7 +1614,7 @@ struct ctl_table random_table[] = {
        },
        {
                .procname       = "read_wakeup_threshold",
-               .data           = &random_read_wakeup_thresh,
+               .data           = &random_read_wakeup_bits,
                .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = proc_dointvec_minmax,
@@ -1583,7 +1623,7 @@ struct ctl_table random_table[] = {
        },
        {
                .procname       = "write_wakeup_threshold",
-               .data           = &random_write_wakeup_thresh,
+               .data           = &random_write_wakeup_bits,
                .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = proc_dointvec_minmax,