random: rate limit unseeded randomness warnings
[sfrench/cifs-2.6.git] / drivers / char / random.c
index e5b3d3ba46604f7c0bb5612f3da867ea16884d20..cd888d4ee605e0b9cf5f4970d34989d4b72f3b72 100644 (file)
 #include <linux/ptrace.h>
 #include <linux/workqueue.h>
 #include <linux/irq.h>
+#include <linux/ratelimit.h>
 #include <linux/syscalls.h>
 #include <linux/completion.h>
 #include <linux/uuid.h>
@@ -427,8 +428,9 @@ struct crng_state primary_crng = {
  * its value (from 0->1->2).
  */
 static int crng_init = 0;
-#define crng_ready() (likely(crng_init > 0))
+#define crng_ready() (likely(crng_init > 1))
 static int crng_init_cnt = 0;
+static unsigned long crng_global_init_time = 0;
 #define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE)
 static void _extract_crng(struct crng_state *crng,
                          __u32 out[CHACHA20_BLOCK_WORDS]);
@@ -437,6 +439,16 @@ static void _crng_backtrack_protect(struct crng_state *crng,
 static void process_random_ready_list(void);
 static void _get_random_bytes(void *buf, int nbytes);
 
+static struct ratelimit_state unseeded_warning =
+       RATELIMIT_STATE_INIT("warn_unseeded_randomness", HZ, 3);
+static struct ratelimit_state urandom_warning =
+       RATELIMIT_STATE_INIT("warn_urandom_randomness", HZ, 3);
+
+static int ratelimit_disable __read_mostly;
+
+module_param_named(ratelimit_disable, ratelimit_disable, int, 0644);
+MODULE_PARM_DESC(ratelimit_disable, "Disable random ratelimit suppression");
+
 /**********************************************************************
  *
  * OS independent entropy store.   Here are the functions which handle
@@ -709,7 +721,8 @@ retry:
                }
 
                /* should we wake readers? */
-               if (entropy_bits >= random_read_wakeup_bits) {
+               if (entropy_bits >= random_read_wakeup_bits &&
+                   wq_has_sleeper(&random_read_wait)) {
                        wake_up_interruptible(&random_read_wait);
                        kill_fasync(&fasync, SIGIO, POLL_IN);
                }
@@ -732,7 +745,7 @@ retry:
 
 static int credit_entropy_bits_safe(struct entropy_store *r, int nbits)
 {
-       const int nbits_max = (int)(~0U >> (ENTROPY_SHIFT + 1));
+       const int nbits_max = r->poolinfo->poolwords * 32;
 
        if (nbits < 0)
                return -EINVAL;
@@ -786,6 +799,43 @@ static void crng_initialize(struct crng_state *crng)
        crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1;
 }
 
+#ifdef CONFIG_NUMA
+static void do_numa_crng_init(struct work_struct *work)
+{
+       int i;
+       struct crng_state *crng;
+       struct crng_state **pool;
+
+       pool = kcalloc(nr_node_ids, sizeof(*pool), GFP_KERNEL|__GFP_NOFAIL);
+       for_each_online_node(i) {
+               crng = kmalloc_node(sizeof(struct crng_state),
+                                   GFP_KERNEL | __GFP_NOFAIL, i);
+               spin_lock_init(&crng->lock);
+               crng_initialize(crng);
+               pool[i] = crng;
+       }
+       mb();
+       if (cmpxchg(&crng_node_pool, NULL, pool)) {
+               for_each_node(i)
+                       kfree(pool[i]);
+               kfree(pool);
+       }
+}
+
+static DECLARE_WORK(numa_crng_init_work, do_numa_crng_init);
+
+static void numa_crng_init(void)
+{
+       schedule_work(&numa_crng_init_work);
+}
+#else
+static void numa_crng_init(void) {}
+#endif
+
+/*
+ * crng_fast_load() can be called by code in the interrupt service
+ * path.  So we can't afford to dilly-dally.
+ */
 static int crng_fast_load(const char *cp, size_t len)
 {
        unsigned long flags;
@@ -793,7 +843,7 @@ static int crng_fast_load(const char *cp, size_t len)
 
        if (!spin_trylock_irqsave(&primary_crng.lock, flags))
                return 0;
-       if (crng_ready()) {
+       if (crng_init != 0) {
                spin_unlock_irqrestore(&primary_crng.lock, flags);
                return 0;
        }
@@ -812,6 +862,51 @@ static int crng_fast_load(const char *cp, size_t len)
        return 1;
 }
 
+/*
+ * crng_slow_load() is called by add_device_randomness, which has two
+ * attributes.  (1) We can't trust the buffer passed to it is
+ * guaranteed to be unpredictable (so it might not have any entropy at
+ * all), and (2) it doesn't have the performance constraints of
+ * crng_fast_load().
+ *
+ * So we do something more comprehensive which is guaranteed to touch
+ * all of the primary_crng's state, and which uses a LFSR with a
+ * period of 255 as part of the mixing algorithm.  Finally, we do
+ * *not* advance crng_init_cnt since buffer we may get may be something
+ * like a fixed DMI table (for example), which might very well be
+ * unique to the machine, but is otherwise unvarying.
+ */
+static int crng_slow_load(const char *cp, size_t len)
+{
+       unsigned long           flags;
+       static unsigned char    lfsr = 1;
+       unsigned char           tmp;
+       unsigned                i, max = CHACHA20_KEY_SIZE;
+       const char *            src_buf = cp;
+       char *                  dest_buf = (char *) &primary_crng.state[4];
+
+       if (!spin_trylock_irqsave(&primary_crng.lock, flags))
+               return 0;
+       if (crng_init != 0) {
+               spin_unlock_irqrestore(&primary_crng.lock, flags);
+               return 0;
+       }
+       if (len > max)
+               max = len;
+
+       for (i = 0; i < max ; i++) {
+               tmp = lfsr;
+               lfsr >>= 1;
+               if (tmp & 1)
+                       lfsr ^= 0xE1;
+               tmp = dest_buf[i % CHACHA20_KEY_SIZE];
+               dest_buf[i % CHACHA20_KEY_SIZE] ^= src_buf[i % len] ^ lfsr;
+               lfsr += (tmp << 3) | (tmp >> 5);
+       }
+       spin_unlock_irqrestore(&primary_crng.lock, flags);
+       return 1;
+}
+
 static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
 {
        unsigned long   flags;
@@ -830,7 +925,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
                _crng_backtrack_protect(&primary_crng, buf.block,
                                        CHACHA20_KEY_SIZE);
        }
-       spin_lock_irqsave(&primary_crng.lock, flags);
+       spin_lock_irqsave(&crng->lock, flags);
        for (i = 0; i < 8; i++) {
                unsigned long   rv;
                if (!arch_get_random_seed_long(&rv) &&
@@ -840,13 +935,26 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
        }
        memzero_explicit(&buf, sizeof(buf));
        crng->init_time = jiffies;
-       spin_unlock_irqrestore(&primary_crng.lock, flags);
+       spin_unlock_irqrestore(&crng->lock, flags);
        if (crng == &primary_crng && crng_init < 2) {
                invalidate_batched_entropy();
+               numa_crng_init();
                crng_init = 2;
                process_random_ready_list();
                wake_up_interruptible(&crng_init_wait);
                pr_notice("random: crng init done\n");
+               if (unseeded_warning.missed) {
+                       pr_notice("random: %d get_random_xx warning(s) missed "
+                                 "due to ratelimiting\n",
+                                 unseeded_warning.missed);
+                       unseeded_warning.missed = 0;
+               }
+               if (urandom_warning.missed) {
+                       pr_notice("random: %d urandom warning(s) missed "
+                                 "due to ratelimiting\n",
+                                 urandom_warning.missed);
+                       urandom_warning.missed = 0;
+               }
        }
 }
 
@@ -855,8 +963,9 @@ static void _extract_crng(struct crng_state *crng,
 {
        unsigned long v, flags;
 
-       if (crng_init > 1 &&
-           time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL))
+       if (crng_ready() &&
+           (time_after(crng_global_init_time, crng->init_time) ||
+            time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL)))
                crng_reseed(crng, crng == &primary_crng ? &input_pool : NULL);
        spin_lock_irqsave(&crng->lock, flags);
        if (arch_get_random_long(&v))
@@ -963,7 +1072,6 @@ static ssize_t extract_crng_user(void __user *buf, size_t nbytes)
 struct timer_rand_state {
        cycles_t last_time;
        long last_delta, last_delta2;
-       unsigned dont_count_entropy:1;
 };
 
 #define INIT_TIMER_RAND_STATE { INITIAL_JIFFIES, };
@@ -981,10 +1089,8 @@ void add_device_randomness(const void *buf, unsigned int size)
        unsigned long time = random_get_entropy() ^ jiffies;
        unsigned long flags;
 
-       if (!crng_ready()) {
-               crng_fast_load(buf, size);
-               return;
-       }
+       if (!crng_ready() && size)
+               crng_slow_load(buf, size);
 
        trace_add_device_randomness(size, _RET_IP_);
        spin_lock_irqsave(&input_pool.lock, flags);
@@ -1029,35 +1135,33 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
         * We take into account the first, second and third-order deltas
         * in order to make our estimate.
         */
+       delta = sample.jiffies - state->last_time;
+       state->last_time = sample.jiffies;
+
+       delta2 = delta - state->last_delta;
+       state->last_delta = delta;
+
+       delta3 = delta2 - state->last_delta2;
+       state->last_delta2 = delta2;
+
+       if (delta < 0)
+               delta = -delta;
+       if (delta2 < 0)
+               delta2 = -delta2;
+       if (delta3 < 0)
+               delta3 = -delta3;
+       if (delta > delta2)
+               delta = delta2;
+       if (delta > delta3)
+               delta = delta3;
 
-       if (!state->dont_count_entropy) {
-               delta = sample.jiffies - state->last_time;
-               state->last_time = sample.jiffies;
-
-               delta2 = delta - state->last_delta;
-               state->last_delta = delta;
-
-               delta3 = delta2 - state->last_delta2;
-               state->last_delta2 = delta2;
-
-               if (delta < 0)
-                       delta = -delta;
-               if (delta2 < 0)
-                       delta2 = -delta2;
-               if (delta3 < 0)
-                       delta3 = -delta3;
-               if (delta > delta2)
-                       delta = delta2;
-               if (delta > delta3)
-                       delta = delta3;
+       /*
+        * delta is now minimum absolute delta.
+        * Round down by 1 bit on general principles,
+        * and limit entropy entimate to 12 bits.
+        */
+       credit_entropy_bits(r, min_t(int, fls(delta>>1), 11));
 
-               /*
-                * delta is now minimum absolute delta.
-                * Round down by 1 bit on general principles,
-                * and limit entropy entimate to 12 bits.
-                */
-               credit_entropy_bits(r, min_t(int, fls(delta>>1), 11));
-       }
        preempt_enable();
 }
 
@@ -1141,7 +1245,7 @@ void add_interrupt_randomness(int irq, int irq_flags)
        fast_mix(fast_pool);
        add_interrupt_bench(cycles);
 
-       if (!crng_ready()) {
+       if (unlikely(crng_init == 0)) {
                if ((fast_pool->count >= 64) &&
                    crng_fast_load((char *) fast_pool->pool,
                                   sizeof(fast_pool->pool))) {
@@ -1491,8 +1595,9 @@ static void _warn_unseeded_randomness(const char *func_name, void *caller,
 #ifndef CONFIG_WARN_ALL_UNSEEDED_RANDOM
        print_once = true;
 #endif
-       pr_notice("random: %s called from %pS with crng_init=%d\n",
-                 func_name, caller, crng_init);
+       if (__ratelimit(&unseeded_warning))
+               pr_notice("random: %s called from %pS with crng_init=%d\n",
+                         func_name, caller, crng_init);
 }
 
 /*
@@ -1682,28 +1787,14 @@ static void init_std_data(struct entropy_store *r)
  */
 static int rand_initialize(void)
 {
-#ifdef CONFIG_NUMA
-       int i;
-       struct crng_state *crng;
-       struct crng_state **pool;
-#endif
-
        init_std_data(&input_pool);
        init_std_data(&blocking_pool);
        crng_initialize(&primary_crng);
-
-#ifdef CONFIG_NUMA
-       pool = kcalloc(nr_node_ids, sizeof(*pool), GFP_KERNEL|__GFP_NOFAIL);
-       for_each_online_node(i) {
-               crng = kmalloc_node(sizeof(struct crng_state),
-                                   GFP_KERNEL | __GFP_NOFAIL, i);
-               spin_lock_init(&crng->lock);
-               crng_initialize(crng);
-               pool[i] = crng;
+       crng_global_init_time = jiffies;
+       if (ratelimit_disable) {
+               urandom_warning.interval = 0;
+               unseeded_warning.interval = 0;
        }
-       mb();
-       crng_node_pool = pool;
-#endif
        return 0;
 }
 early_initcall(rand_initialize);
@@ -1771,9 +1862,10 @@ urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
 
        if (!crng_ready() && maxwarn > 0) {
                maxwarn--;
-               printk(KERN_NOTICE "random: %s: uninitialized urandom read "
-                      "(%zd bytes read)\n",
-                      current->comm, nbytes);
+               if (__ratelimit(&urandom_warning))
+                       printk(KERN_NOTICE "random: %s: uninitialized "
+                              "urandom read (%zd bytes read)\n",
+                              current->comm, nbytes);
                spin_lock_irqsave(&primary_crng.lock, flags);
                crng_init_cnt = 0;
                spin_unlock_irqrestore(&primary_crng.lock, flags);
@@ -1877,6 +1969,14 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
                input_pool.entropy_count = 0;
                blocking_pool.entropy_count = 0;
                return 0;
+       case RNDRESEEDCRNG:
+               if (!capable(CAP_SYS_ADMIN))
+                       return -EPERM;
+               if (crng_init < 2)
+                       return -ENODATA;
+               crng_reseed(&primary_crng, NULL);
+               crng_global_init_time = jiffies - 1;
+               return 0;
        default:
                return -EINVAL;
        }
@@ -2214,7 +2314,7 @@ void add_hwgenerator_randomness(const char *buffer, size_t count,
 {
        struct entropy_store *poolp = &input_pool;
 
-       if (!crng_ready()) {
+       if (unlikely(crng_init == 0)) {
                crng_fast_load(buffer, count);
                return;
        }