|
@@ -1294,6 +1294,34 @@ void rand_initialize_disk(struct gendisk *disk)
|
|
}
|
|
}
|
|
#endif
|
|
#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];
|
|
|
|
+
|
|
|
|
+ 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
|
|
static ssize_t
|
|
random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
|
|
random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
|
|
{
|
|
{
|
|
@@ -1312,8 +1340,13 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
|
|
ENTROPY_BITS(&input_pool));
|
|
ENTROPY_BITS(&input_pool));
|
|
if (n > 0)
|
|
if (n > 0)
|
|
return n;
|
|
return n;
|
|
|
|
+
|
|
/* Pool is (near) empty. Maybe wait and retry. */
|
|
/* Pool is (near) empty. Maybe wait and retry. */
|
|
|
|
|
|
|
|
+ /* First try an emergency refill */
|
|
|
|
+ if (arch_random_refill())
|
|
|
|
+ continue;
|
|
|
|
+
|
|
if (file->f_flags & O_NONBLOCK)
|
|
if (file->f_flags & O_NONBLOCK)
|
|
return -EAGAIN;
|
|
return -EAGAIN;
|
|
|
|
|