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

Commit 35db2a07 authored by Jens Axboe's avatar Jens Axboe Committed by Greg Kroah-Hartman
Browse files

random: convert to using fops->write_iter()



commit 22b0a222af4df8ee9bb8e07013ab44da9511b047 upstream.

Now that the read side has been converted to fix a regression with
splice, convert the write side as well to have some symmetry in the
interface used (and help deprecate ->write()).

Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
[Jason: cleaned up random_ioctl a bit, require full writes in
 RNDADDENTROPY since it's crediting entropy, simplify control flow of
 write_pool(), and incorporate suggestions from Al.]
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarJason A. Donenfeld <Jason@zx2c4.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 43e62db8
Loading
Loading
Loading
Loading
+35 −32
Original line number Diff line number Diff line
@@ -1251,39 +1251,31 @@ static __poll_t random_poll(struct file *file, poll_table *wait)
	return crng_ready() ? EPOLLIN | EPOLLRDNORM : EPOLLOUT | EPOLLWRNORM;
}

static int write_pool(const char __user *ubuf, size_t len)
static ssize_t write_pool(struct iov_iter *iter)
{
	size_t block_len;
	int ret = 0;
	u8 block[BLAKE2S_BLOCK_SIZE];
	ssize_t ret = 0;
	size_t copied;

	while (len) {
		block_len = min(len, sizeof(block));
		if (copy_from_user(block, ubuf, block_len)) {
			ret = -EFAULT;
			goto out;
		}
		len -= block_len;
		ubuf += block_len;
		mix_pool_bytes(block, block_len);
	if (unlikely(!iov_iter_count(iter)))
		return 0;

	for (;;) {
		copied = copy_from_iter(block, sizeof(block), iter);
		ret += copied;
		mix_pool_bytes(block, copied);
		if (!iov_iter_count(iter) || copied != sizeof(block))
			break;
		cond_resched();
	}

out:
	memzero_explicit(block, sizeof(block));
	return ret;
	return ret ? ret : -EFAULT;
}

static ssize_t random_write(struct file *file, const char __user *ubuf,
			    size_t len, loff_t *ppos)
static ssize_t random_write_iter(struct kiocb *kiocb, struct iov_iter *iter)
{
	int ret;

	ret = write_pool(ubuf, len);
	if (ret)
		return ret;

	return (ssize_t)len;
	return write_pool(iter);
}

static ssize_t urandom_read_iter(struct kiocb *kiocb, struct iov_iter *iter)
@@ -1315,9 +1307,8 @@ static ssize_t random_read_iter(struct kiocb *kiocb, struct iov_iter *iter)

static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
{
	int size, ent_count;
	int __user *p = (int __user *)arg;
	int retval;
	int ent_count;

	switch (cmd) {
	case RNDGETENTCNT:
@@ -1334,20 +1325,32 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
			return -EINVAL;
		credit_init_bits(ent_count);
		return 0;
	case RNDADDENTROPY:
	case RNDADDENTROPY: {
		struct iov_iter iter;
		struct iovec iov;
		ssize_t ret;
		int len;

		if (!capable(CAP_SYS_ADMIN))
			return -EPERM;
		if (get_user(ent_count, p++))
			return -EFAULT;
		if (ent_count < 0)
			return -EINVAL;
		if (get_user(size, p++))
		if (get_user(len, p++))
			return -EFAULT;
		ret = import_single_range(WRITE, p, len, &iov, &iter);
		if (unlikely(ret))
			return ret;
		ret = write_pool(&iter);
		if (unlikely(ret < 0))
			return ret;
		/* Since we're crediting, enforce that it was all written into the pool. */
		if (unlikely(ret != len))
			return -EFAULT;
		retval = write_pool((const char __user *)p, size);
		if (retval < 0)
			return retval;
		credit_init_bits(ent_count);
		return 0;
	}
	case RNDZAPENTCNT:
	case RNDCLEARPOOL:
		/* No longer has any effect. */
@@ -1373,7 +1376,7 @@ static int random_fasync(int fd, struct file *filp, int on)

const struct file_operations random_fops = {
	.read_iter = random_read_iter,
	.write = random_write,
	.write_iter = random_write_iter,
	.poll = random_poll,
	.unlocked_ioctl = random_ioctl,
	.compat_ioctl = compat_ptr_ioctl,
@@ -1383,7 +1386,7 @@ const struct file_operations random_fops = {

const struct file_operations urandom_fops = {
	.read_iter = urandom_read_iter,
	.write = random_write,
	.write_iter = random_write_iter,
	.unlocked_ioctl = random_ioctl,
	.compat_ioctl = compat_ptr_ioctl,
	.fasync = random_fasync,