Skip to content

Commit 22b0a22

Browse files
axboezx2c4
authored andcommitted
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: Jens Axboe <[email protected]> [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 <[email protected]> Signed-off-by: Jason A. Donenfeld <[email protected]>
1 parent 1b388e7 commit 22b0a22

File tree

1 file changed

+35
-32
lines changed

1 file changed

+35
-32
lines changed

Diff for: drivers/char/random.c

+35-32
Original file line numberDiff line numberDiff line change
@@ -1274,39 +1274,31 @@ static __poll_t random_poll(struct file *file, poll_table *wait)
12741274
return crng_ready() ? EPOLLIN | EPOLLRDNORM : EPOLLOUT | EPOLLWRNORM;
12751275
}
12761276

1277-
static int write_pool(const char __user *ubuf, size_t len)
1277+
static ssize_t write_pool(struct iov_iter *iter)
12781278
{
1279-
size_t block_len;
1280-
int ret = 0;
12811279
u8 block[BLAKE2S_BLOCK_SIZE];
1280+
ssize_t ret = 0;
1281+
size_t copied;
12821282

1283-
while (len) {
1284-
block_len = min(len, sizeof(block));
1285-
if (copy_from_user(block, ubuf, block_len)) {
1286-
ret = -EFAULT;
1287-
goto out;
1288-
}
1289-
len -= block_len;
1290-
ubuf += block_len;
1291-
mix_pool_bytes(block, block_len);
1283+
if (unlikely(!iov_iter_count(iter)))
1284+
return 0;
1285+
1286+
for (;;) {
1287+
copied = copy_from_iter(block, sizeof(block), iter);
1288+
ret += copied;
1289+
mix_pool_bytes(block, copied);
1290+
if (!iov_iter_count(iter) || copied != sizeof(block))
1291+
break;
12921292
cond_resched();
12931293
}
12941294

1295-
out:
12961295
memzero_explicit(block, sizeof(block));
1297-
return ret;
1296+
return ret ? ret : -EFAULT;
12981297
}
12991298

1300-
static ssize_t random_write(struct file *file, const char __user *ubuf,
1301-
size_t len, loff_t *ppos)
1299+
static ssize_t random_write_iter(struct kiocb *kiocb, struct iov_iter *iter)
13021300
{
1303-
int ret;
1304-
1305-
ret = write_pool(ubuf, len);
1306-
if (ret)
1307-
return ret;
1308-
1309-
return (ssize_t)len;
1301+
return write_pool(iter);
13101302
}
13111303

13121304
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)
13451337

13461338
static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
13471339
{
1348-
int size, ent_count;
13491340
int __user *p = (int __user *)arg;
1350-
int retval;
1341+
int ent_count;
13511342

13521343
switch (cmd) {
13531344
case RNDGETENTCNT:
@@ -1364,20 +1355,32 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
13641355
return -EINVAL;
13651356
credit_init_bits(ent_count);
13661357
return 0;
1367-
case RNDADDENTROPY:
1358+
case RNDADDENTROPY: {
1359+
struct iov_iter iter;
1360+
struct iovec iov;
1361+
ssize_t ret;
1362+
int len;
1363+
13681364
if (!capable(CAP_SYS_ADMIN))
13691365
return -EPERM;
13701366
if (get_user(ent_count, p++))
13711367
return -EFAULT;
13721368
if (ent_count < 0)
13731369
return -EINVAL;
1374-
if (get_user(size, p++))
1370+
if (get_user(len, p++))
1371+
return -EFAULT;
1372+
ret = import_single_range(WRITE, p, len, &iov, &iter);
1373+
if (unlikely(ret))
1374+
return ret;
1375+
ret = write_pool(&iter);
1376+
if (unlikely(ret < 0))
1377+
return ret;
1378+
/* Since we're crediting, enforce that it was all written into the pool. */
1379+
if (unlikely(ret != len))
13751380
return -EFAULT;
1376-
retval = write_pool((const char __user *)p, size);
1377-
if (retval < 0)
1378-
return retval;
13791381
credit_init_bits(ent_count);
13801382
return 0;
1383+
}
13811384
case RNDZAPENTCNT:
13821385
case RNDCLEARPOOL:
13831386
/* No longer has any effect. */
@@ -1403,7 +1406,7 @@ static int random_fasync(int fd, struct file *filp, int on)
14031406

14041407
const struct file_operations random_fops = {
14051408
.read_iter = random_read_iter,
1406-
.write = random_write,
1409+
.write_iter = random_write_iter,
14071410
.poll = random_poll,
14081411
.unlocked_ioctl = random_ioctl,
14091412
.compat_ioctl = compat_ptr_ioctl,
@@ -1413,7 +1416,7 @@ const struct file_operations random_fops = {
14131416

14141417
const struct file_operations urandom_fops = {
14151418
.read_iter = urandom_read_iter,
1416-
.write = random_write,
1419+
.write_iter = random_write_iter,
14171420
.unlocked_ioctl = random_ioctl,
14181421
.compat_ioctl = compat_ptr_ioctl,
14191422
.fasync = random_fasync,

0 commit comments

Comments
 (0)