提交 22b0a222 编写于 作者: J Jens Axboe 提交者: Jason A. Donenfeld

random: convert to using fops->write_iter()

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: NJens 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: NJason A. Donenfeld <Jason@zx2c4.com>
上级 1b388e77
...@@ -1274,39 +1274,31 @@ static __poll_t random_poll(struct file *file, poll_table *wait) ...@@ -1274,39 +1274,31 @@ static __poll_t random_poll(struct file *file, poll_table *wait)
return crng_ready() ? EPOLLIN | EPOLLRDNORM : EPOLLOUT | EPOLLWRNORM; 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]; u8 block[BLAKE2S_BLOCK_SIZE];
ssize_t ret = 0;
size_t copied;
while (len) { if (unlikely(!iov_iter_count(iter)))
block_len = min(len, sizeof(block)); return 0;
if (copy_from_user(block, ubuf, block_len)) {
ret = -EFAULT; for (;;) {
goto out; copied = copy_from_iter(block, sizeof(block), iter);
} ret += copied;
len -= block_len; mix_pool_bytes(block, copied);
ubuf += block_len; if (!iov_iter_count(iter) || copied != sizeof(block))
mix_pool_bytes(block, block_len); break;
cond_resched(); cond_resched();
} }
out:
memzero_explicit(block, sizeof(block)); memzero_explicit(block, sizeof(block));
return ret; return ret ? ret : -EFAULT;
} }
static ssize_t random_write(struct file *file, const char __user *ubuf, static ssize_t random_write_iter(struct kiocb *kiocb, struct iov_iter *iter)
size_t len, loff_t *ppos)
{ {
int ret; return write_pool(iter);
ret = write_pool(ubuf, len);
if (ret)
return ret;
return (ssize_t)len;
} }
static ssize_t urandom_read_iter(struct kiocb *kiocb, struct iov_iter *iter) static ssize_t urandom_read_iter(struct kiocb *kiocb, struct iov_iter *iter)
...@@ -1345,9 +1337,8 @@ static ssize_t random_read_iter(struct kiocb *kiocb, struct iov_iter *iter) ...@@ -1345,9 +1337,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) static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
{ {
int size, ent_count;
int __user *p = (int __user *)arg; int __user *p = (int __user *)arg;
int retval; int ent_count;
switch (cmd) { switch (cmd) {
case RNDGETENTCNT: case RNDGETENTCNT:
...@@ -1364,20 +1355,32 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg) ...@@ -1364,20 +1355,32 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
return -EINVAL; return -EINVAL;
credit_init_bits(ent_count); credit_init_bits(ent_count);
return 0; return 0;
case RNDADDENTROPY: case RNDADDENTROPY: {
struct iov_iter iter;
struct iovec iov;
ssize_t ret;
int len;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
if (get_user(ent_count, p++)) if (get_user(ent_count, p++))
return -EFAULT; return -EFAULT;
if (ent_count < 0) if (ent_count < 0)
return -EINVAL; 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; return -EFAULT;
retval = write_pool((const char __user *)p, size);
if (retval < 0)
return retval;
credit_init_bits(ent_count); credit_init_bits(ent_count);
return 0; return 0;
}
case RNDZAPENTCNT: case RNDZAPENTCNT:
case RNDCLEARPOOL: case RNDCLEARPOOL:
/* No longer has any effect. */ /* No longer has any effect. */
...@@ -1403,7 +1406,7 @@ static int random_fasync(int fd, struct file *filp, int on) ...@@ -1403,7 +1406,7 @@ static int random_fasync(int fd, struct file *filp, int on)
const struct file_operations random_fops = { const struct file_operations random_fops = {
.read_iter = random_read_iter, .read_iter = random_read_iter,
.write = random_write, .write_iter = random_write_iter,
.poll = random_poll, .poll = random_poll,
.unlocked_ioctl = random_ioctl, .unlocked_ioctl = random_ioctl,
.compat_ioctl = compat_ptr_ioctl, .compat_ioctl = compat_ptr_ioctl,
...@@ -1413,7 +1416,7 @@ const struct file_operations random_fops = { ...@@ -1413,7 +1416,7 @@ const struct file_operations random_fops = {
const struct file_operations urandom_fops = { const struct file_operations urandom_fops = {
.read_iter = urandom_read_iter, .read_iter = urandom_read_iter,
.write = random_write, .write_iter = random_write_iter,
.unlocked_ioctl = random_ioctl, .unlocked_ioctl = random_ioctl,
.compat_ioctl = compat_ptr_ioctl, .compat_ioctl = compat_ptr_ioctl,
.fasync = random_fasync, .fasync = random_fasync,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册