summary refs log tree commit diff
path: root/drivers/char
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2018-04-11 16:32:17 -0400
committerTheodore Ts'o <tytso@mit.edu>2018-04-14 11:59:31 -0400
commitd848e5f8e1ebdb227d045db55fe4f825e82965fa (patch)
tree7661e5f63b463d3fb22da99aef52bf1e00d814f4 /drivers/char
parent0bb29a849a6433b72e249eea7695477b02056e94 (diff)
downloadlinux-d848e5f8e1ebdb227d045db55fe4f825e82965fa.tar.gz
random: add new ioctl RNDRESEEDCRNG
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
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/random.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 898233f594b4..3cd3aae24d6d 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -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,
 			  __u32 out[CHACHA20_BLOCK_WORDS]);
@@ -933,7 +934,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))
@@ -1757,6 +1759,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;
 	return 0;
 }
 early_initcall(rand_initialize);
@@ -1930,6 +1933,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;
 	}