random: add new ioctl RNDRESEEDCRNG
authorTheodore Ts'o <tytso@mit.edu>
Wed, 11 Apr 2018 20:32:17 +0000 (16:32 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 24 Apr 2018 07:36:37 +0000 (09:36 +0200)
commit d848e5f8e1ebdb227d045db55fe4f825e82965fa upstream.

Add a new ioctl which forces the the crng to be reseeded.

Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Cc: stable@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/char/random.c
include/uapi/linux/random.h

index c621f8443281a9f3ce9616404270035eedd3e650..58a2ff7df392e27f21ad5a9595ae41c59b5a127b 100644 (file)
@@ -429,6 +429,7 @@ struct crng_state primary_crng = {
 static int 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,
                          __u8 out[CHACHA20_BLOCK_SIZE]);
@@ -905,7 +906,8 @@ static void _extract_crng(struct crng_state *crng,
        unsigned long v, flags;
 
        if (crng_ready() &&
-           time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL))
+           (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))
@@ -1738,6 +1740,7 @@ static int rand_initialize(void)
        init_std_data(&input_pool);
        init_std_data(&blocking_pool);
        crng_initialize(&primary_crng);
+       crng_global_init_time = jiffies;
 
 #ifdef CONFIG_NUMA
        pool = kcalloc(nr_node_ids, sizeof(*pool), GFP_KERNEL|__GFP_NOFAIL);
@@ -1924,6 +1927,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;
        }
index c34f4490d025ff6802aca2ef6bd2237906f889b2..26ee91300e3ecbb2d5f8c18db6231343c09944bd 100644 (file)
@@ -35,6 +35,9 @@
 /* Clear the entropy pool and associated counters.  (Superuser only.) */
 #define RNDCLEARPOOL   _IO( 'R', 0x06 )
 
+/* Reseed CRNG.  (Superuser only.) */
+#define RNDRESEEDCRNG  _IO( 'R', 0x07 )
+
 struct rand_pool_info {
        int     entropy_count;
        int     buf_size;