Skip to content

Commit

Permalink
random: group userspace read/write functions
Browse files Browse the repository at this point in the history
commit a6adf8e upstream.

This pulls all of the userspace read/write-focused functions into the
fifth labeled section.

No functional changes.

Cc: Theodore Ts'o <tytso@mit.edu>
Reviewed-by: Eric Biggers <ebiggers@google.com>
Reviewed-by: Dominik Brodowski <linux@dominikbrodowski.net>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
zx2c4 authored and gregkh committed May 30, 2022
1 parent f045808 commit 21ae543
Showing 1 changed file with 77 additions and 48 deletions.
125 changes: 77 additions & 48 deletions drivers/char/random.c
Original file line number Diff line number Diff line change
Expand Up @@ -1477,30 +1477,61 @@ static void try_to_generate_entropy(void)
mix_pool_bytes(&stack.now, sizeof(stack.now));
}

static ssize_t urandom_read(struct file *file, char __user *buf, size_t nbytes,
loff_t *ppos)

/**********************************************************************
*
* Userspace reader/writer interfaces.
*
* getrandom(2) is the primary modern interface into the RNG and should
* be used in preference to anything else.
*
* Reading from /dev/random has the same functionality as calling
* getrandom(2) with flags=0. In earlier versions, however, it had
* vastly different semantics and should therefore be avoided, to
* prevent backwards compatibility issues.
*
* Reading from /dev/urandom has the same functionality as calling
* getrandom(2) with flags=GRND_INSECURE. Because it does not block
* waiting for the RNG to be ready, it should not be used.
*
* Writing to either /dev/random or /dev/urandom adds entropy to
* the input pool but does not credit it.
*
* Polling on /dev/random indicates when the RNG is initialized, on
* the read side, and when it wants new entropy, on the write side.
*
* Both /dev/random and /dev/urandom have the same set of ioctls for
* adding entropy, getting the entropy count, zeroing the count, and
* reseeding the crng.
*
**********************************************************************/

SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count, unsigned int,
flags)
{
static int maxwarn = 10;
if (flags & ~(GRND_NONBLOCK | GRND_RANDOM | GRND_INSECURE))
return -EINVAL;

if (!crng_ready() && maxwarn > 0) {
maxwarn--;
if (__ratelimit(&urandom_warning))
pr_notice("%s: uninitialized urandom read (%zd bytes read)\n",
current->comm, nbytes);
}
/*
* Requesting insecure and blocking randomness at the same time makes
* no sense.
*/
if ((flags & (GRND_INSECURE | GRND_RANDOM)) == (GRND_INSECURE | GRND_RANDOM))
return -EINVAL;

return get_random_bytes_user(buf, nbytes);
}
if (count > INT_MAX)
count = INT_MAX;

static ssize_t random_read(struct file *file, char __user *buf, size_t nbytes,
loff_t *ppos)
{
int ret;
if (!(flags & GRND_INSECURE) && !crng_ready()) {
int ret;

ret = wait_for_random_bytes();
if (ret != 0)
return ret;
return get_random_bytes_user(buf, nbytes);
if (flags & GRND_NONBLOCK)
return -EAGAIN;
ret = wait_for_random_bytes();
if (unlikely(ret))
return ret;
}
return get_random_bytes_user(buf, count);
}

static __poll_t random_poll(struct file *file, poll_table *wait)
Expand Down Expand Up @@ -1552,6 +1583,32 @@ static ssize_t random_write(struct file *file, const char __user *buffer,
return (ssize_t)count;
}

static ssize_t urandom_read(struct file *file, char __user *buf, size_t nbytes,
loff_t *ppos)
{
static int maxwarn = 10;

if (!crng_ready() && maxwarn > 0) {
maxwarn--;
if (__ratelimit(&urandom_warning))
pr_notice("%s: uninitialized urandom read (%zd bytes read)\n",
current->comm, nbytes);
}

return get_random_bytes_user(buf, nbytes);
}

static ssize_t random_read(struct file *file, char __user *buf, size_t nbytes,
loff_t *ppos)
{
int ret;

ret = wait_for_random_bytes();
if (ret != 0)
return ret;
return get_random_bytes_user(buf, nbytes);
}

static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
{
int size, ent_count;
Expand All @@ -1560,7 +1617,7 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)

switch (cmd) {
case RNDGETENTCNT:
/* inherently racy, no point locking */
/* Inherently racy, no point locking. */
if (put_user(input_pool.entropy_count, p))
return -EFAULT;
return 0;
Expand Down Expand Up @@ -1636,34 +1693,6 @@ const struct file_operations urandom_fops = {
.llseek = noop_llseek,
};

SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count, unsigned int,
flags)
{
if (flags & ~(GRND_NONBLOCK | GRND_RANDOM | GRND_INSECURE))
return -EINVAL;

/*
* Requesting insecure and blocking randomness at the same time makes
* no sense.
*/
if ((flags & (GRND_INSECURE | GRND_RANDOM)) == (GRND_INSECURE | GRND_RANDOM))
return -EINVAL;

if (count > INT_MAX)
count = INT_MAX;

if (!(flags & GRND_INSECURE) && !crng_ready()) {
int ret;

if (flags & GRND_NONBLOCK)
return -EAGAIN;
ret = wait_for_random_bytes();
if (unlikely(ret))
return ret;
}
return get_random_bytes_user(buf, count);
}

/********************************************************************
*
* Sysctl interface
Expand Down

0 comments on commit 21ae543

Please sign in to comment.