Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 331c6490 authored by H. Peter Anvin's avatar H. Peter Anvin Committed by Theodore Ts'o
Browse files

random: If we have arch_get_random_seed*(), try it before blocking



If we have arch_get_random_seed*(), try to use it for emergency refill
of the entropy pool before giving up and blocking on /dev/random.  It
may or may not work in the moment, but if it does work, it will give
the user better service than blocking will.

Reviewed-by: default avatarIngo Molnar <mingo@kernel.org>
Signed-off-by: default avatarH. Peter Anvin <hpa@linux.intel.com>
Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent 83664a69
Loading
Loading
Loading
Loading
+33 −0
Original line number Original line Diff line number Diff line
@@ -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;