aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-05-18 14:46:23 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-05-18 14:46:23 -0400
commit69370471d0b2fc3020c60f5473b1eef5977d165a (patch)
treee0ba8b51204779afb17b5749657e9709e8a1ea3e
parente34df3344d7b6f284e958147d7225faa340a1f39 (diff)
parentdd254f5a382cc7879db7a07ed266b12d38fe3ab6 (diff)
Merge branch 'work.iov_iter' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull iov_iter cleanups from Al Viro. * 'work.iov_iter' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: fold checks into iterate_and_advance() rw_verify_area(): saner calling conventions aio: remove a pointless assignment
-rw-r--r--fs/aio.c2
-rw-r--r--fs/read_write.c33
-rw-r--r--lib/iov_iter.c104
3 files changed, 50 insertions, 89 deletions
diff --git a/fs/aio.c b/fs/aio.c
index 155f84253f33..a6deaa78326d 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1447,8 +1447,6 @@ rw_common:
1447 return ret; 1447 return ret;
1448 } 1448 }
1449 1449
1450 len = ret;
1451
1452 if (rw == WRITE) 1450 if (rw == WRITE)
1453 file_start_write(file); 1451 file_start_write(file);
1454 1452
diff --git a/fs/read_write.c b/fs/read_write.c
index 56425cd5c9e7..933b53a375b4 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -398,11 +398,6 @@ ssize_t vfs_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos)
398} 398}
399EXPORT_SYMBOL(vfs_iter_write); 399EXPORT_SYMBOL(vfs_iter_write);
400 400
401/*
402 * rw_verify_area doesn't like huge counts. We limit
403 * them to something that fits in "int" so that others
404 * won't have to do range checks all the time.
405 */
406int rw_verify_area(int read_write, struct file *file, const loff_t *ppos, size_t count) 401int rw_verify_area(int read_write, struct file *file, const loff_t *ppos, size_t count)
407{ 402{
408 struct inode *inode; 403 struct inode *inode;
@@ -429,11 +424,8 @@ int rw_verify_area(int read_write, struct file *file, const loff_t *ppos, size_t
429 if (retval < 0) 424 if (retval < 0)
430 return retval; 425 return retval;
431 } 426 }
432 retval = security_file_permission(file, 427 return security_file_permission(file,
433 read_write == READ ? MAY_READ : MAY_WRITE); 428 read_write == READ ? MAY_READ : MAY_WRITE);
434 if (retval)
435 return retval;
436 return count > MAX_RW_COUNT ? MAX_RW_COUNT : count;
437} 429}
438 430
439static ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos) 431static ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
@@ -477,8 +469,9 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
477 return -EFAULT; 469 return -EFAULT;
478 470
479 ret = rw_verify_area(READ, file, pos, count); 471 ret = rw_verify_area(READ, file, pos, count);
480 if (ret >= 0) { 472 if (!ret) {
481 count = ret; 473 if (count > MAX_RW_COUNT)
474 count = MAX_RW_COUNT;
482 ret = __vfs_read(file, buf, count, pos); 475 ret = __vfs_read(file, buf, count, pos);
483 if (ret > 0) { 476 if (ret > 0) {
484 fsnotify_access(file); 477 fsnotify_access(file);
@@ -560,8 +553,9 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_
560 return -EFAULT; 553 return -EFAULT;
561 554
562 ret = rw_verify_area(WRITE, file, pos, count); 555 ret = rw_verify_area(WRITE, file, pos, count);
563 if (ret >= 0) { 556 if (!ret) {
564 count = ret; 557 if (count > MAX_RW_COUNT)
558 count = MAX_RW_COUNT;
565 file_start_write(file); 559 file_start_write(file);
566 ret = __vfs_write(file, buf, count, pos); 560 ret = __vfs_write(file, buf, count, pos);
567 if (ret > 0) { 561 if (ret > 0) {
@@ -1315,7 +1309,8 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
1315 retval = rw_verify_area(READ, in.file, &pos, count); 1309 retval = rw_verify_area(READ, in.file, &pos, count);
1316 if (retval < 0) 1310 if (retval < 0)
1317 goto fput_in; 1311 goto fput_in;
1318 count = retval; 1312 if (count > MAX_RW_COUNT)
1313 count = MAX_RW_COUNT;
1319 1314
1320 /* 1315 /*
1321 * Get output file, and verify that it is ok.. 1316 * Get output file, and verify that it is ok..
@@ -1333,7 +1328,6 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
1333 retval = rw_verify_area(WRITE, out.file, &out_pos, count); 1328 retval = rw_verify_area(WRITE, out.file, &out_pos, count);
1334 if (retval < 0) 1329 if (retval < 0)
1335 goto fput_out; 1330 goto fput_out;
1336 count = retval;
1337 1331
1338 if (!max) 1332 if (!max)
1339 max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes); 1333 max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes);
@@ -1477,11 +1471,12 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in,
1477 if (flags != 0) 1471 if (flags != 0)
1478 return -EINVAL; 1472 return -EINVAL;
1479 1473
1480 /* copy_file_range allows full ssize_t len, ignoring MAX_RW_COUNT */
1481 ret = rw_verify_area(READ, file_in, &pos_in, len); 1474 ret = rw_verify_area(READ, file_in, &pos_in, len);
1482 if (ret >= 0) 1475 if (unlikely(ret))
1483 ret = rw_verify_area(WRITE, file_out, &pos_out, len); 1476 return ret;
1484 if (ret < 0) 1477
1478 ret = rw_verify_area(WRITE, file_out, &pos_out, len);
1479 if (unlikely(ret))
1485 return ret; 1480 return ret;
1486 1481
1487 if (!(file_in->f_mode & FMODE_READ) || 1482 if (!(file_in->f_mode & FMODE_READ) ||
diff --git a/lib/iov_iter.c b/lib/iov_iter.c
index ca5316e0087b..28cb4315fe57 100644
--- a/lib/iov_iter.c
+++ b/lib/iov_iter.c
@@ -99,40 +99,44 @@
99} 99}
100 100
101#define iterate_and_advance(i, n, v, I, B, K) { \ 101#define iterate_and_advance(i, n, v, I, B, K) { \
102 size_t skip = i->iov_offset; \ 102 if (unlikely(i->count < n)) \
103 if (unlikely(i->type & ITER_BVEC)) { \ 103 n = i->count; \
104 const struct bio_vec *bvec; \ 104 if (n) { \
105 struct bio_vec v; \ 105 size_t skip = i->iov_offset; \
106 iterate_bvec(i, n, v, bvec, skip, (B)) \ 106 if (unlikely(i->type & ITER_BVEC)) { \
107 if (skip == bvec->bv_len) { \ 107 const struct bio_vec *bvec; \
108 bvec++; \ 108 struct bio_vec v; \
109 skip = 0; \ 109 iterate_bvec(i, n, v, bvec, skip, (B)) \
110 } \ 110 if (skip == bvec->bv_len) { \
111 i->nr_segs -= bvec - i->bvec; \ 111 bvec++; \
112 i->bvec = bvec; \ 112 skip = 0; \
113 } else if (unlikely(i->type & ITER_KVEC)) { \ 113 } \
114 const struct kvec *kvec; \ 114 i->nr_segs -= bvec - i->bvec; \
115 struct kvec v; \ 115 i->bvec = bvec; \
116 iterate_kvec(i, n, v, kvec, skip, (K)) \ 116 } else if (unlikely(i->type & ITER_KVEC)) { \
117 if (skip == kvec->iov_len) { \ 117 const struct kvec *kvec; \
118 kvec++; \ 118 struct kvec v; \
119 skip = 0; \ 119 iterate_kvec(i, n, v, kvec, skip, (K)) \
120 } \ 120 if (skip == kvec->iov_len) { \
121 i->nr_segs -= kvec - i->kvec; \ 121 kvec++; \
122 i->kvec = kvec; \ 122 skip = 0; \
123 } else { \ 123 } \
124 const struct iovec *iov; \ 124 i->nr_segs -= kvec - i->kvec; \
125 struct iovec v; \ 125 i->kvec = kvec; \
126 iterate_iovec(i, n, v, iov, skip, (I)) \ 126 } else { \
127 if (skip == iov->iov_len) { \ 127 const struct iovec *iov; \
128 iov++; \ 128 struct iovec v; \
129 skip = 0; \ 129 iterate_iovec(i, n, v, iov, skip, (I)) \
130 if (skip == iov->iov_len) { \
131 iov++; \
132 skip = 0; \
133 } \
134 i->nr_segs -= iov - i->iov; \
135 i->iov = iov; \
130 } \ 136 } \
131 i->nr_segs -= iov - i->iov; \ 137 i->count -= n; \
132 i->iov = iov; \ 138 i->iov_offset = skip; \
133 } \ 139 } \
134 i->count -= n; \
135 i->iov_offset = skip; \
136} 140}
137 141
138static size_t copy_page_to_iter_iovec(struct page *page, size_t offset, size_t bytes, 142static size_t copy_page_to_iter_iovec(struct page *page, size_t offset, size_t bytes,
@@ -386,12 +390,6 @@ static void memzero_page(struct page *page, size_t offset, size_t len)
386size_t copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i) 390size_t copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i)
387{ 391{
388 const char *from = addr; 392 const char *from = addr;
389 if (unlikely(bytes > i->count))
390 bytes = i->count;
391
392 if (unlikely(!bytes))
393 return 0;
394
395 iterate_and_advance(i, bytes, v, 393 iterate_and_advance(i, bytes, v,
396 __copy_to_user(v.iov_base, (from += v.iov_len) - v.iov_len, 394 __copy_to_user(v.iov_base, (from += v.iov_len) - v.iov_len,
397 v.iov_len), 395 v.iov_len),
@@ -407,12 +405,6 @@ EXPORT_SYMBOL(copy_to_iter);
407size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i) 405size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i)
408{ 406{
409 char *to = addr; 407 char *to = addr;
410 if (unlikely(bytes > i->count))
411 bytes = i->count;
412
413 if (unlikely(!bytes))
414 return 0;
415
416 iterate_and_advance(i, bytes, v, 408 iterate_and_advance(i, bytes, v,
417 __copy_from_user((to += v.iov_len) - v.iov_len, v.iov_base, 409 __copy_from_user((to += v.iov_len) - v.iov_len, v.iov_base,
418 v.iov_len), 410 v.iov_len),
@@ -428,12 +420,6 @@ EXPORT_SYMBOL(copy_from_iter);
428size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i) 420size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i)
429{ 421{
430 char *to = addr; 422 char *to = addr;
431 if (unlikely(bytes > i->count))
432 bytes = i->count;
433
434 if (unlikely(!bytes))
435 return 0;
436
437 iterate_and_advance(i, bytes, v, 423 iterate_and_advance(i, bytes, v,
438 __copy_from_user_nocache((to += v.iov_len) - v.iov_len, 424 __copy_from_user_nocache((to += v.iov_len) - v.iov_len,
439 v.iov_base, v.iov_len), 425 v.iov_base, v.iov_len),
@@ -474,12 +460,6 @@ EXPORT_SYMBOL(copy_page_from_iter);
474 460
475size_t iov_iter_zero(size_t bytes, struct iov_iter *i) 461size_t iov_iter_zero(size_t bytes, struct iov_iter *i)
476{ 462{
477 if (unlikely(bytes > i->count))
478 bytes = i->count;
479
480 if (unlikely(!bytes))
481 return 0;
482
483 iterate_and_advance(i, bytes, v, 463 iterate_and_advance(i, bytes, v,
484 __clear_user(v.iov_base, v.iov_len), 464 __clear_user(v.iov_base, v.iov_len),
485 memzero_page(v.bv_page, v.bv_offset, v.bv_len), 465 memzero_page(v.bv_page, v.bv_offset, v.bv_len),
@@ -685,12 +665,6 @@ size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum,
685 char *to = addr; 665 char *to = addr;
686 __wsum sum, next; 666 __wsum sum, next;
687 size_t off = 0; 667 size_t off = 0;
688 if (unlikely(bytes > i->count))
689 bytes = i->count;
690
691 if (unlikely(!bytes))
692 return 0;
693
694 sum = *csum; 668 sum = *csum;
695 iterate_and_advance(i, bytes, v, ({ 669 iterate_and_advance(i, bytes, v, ({
696 int err = 0; 670 int err = 0;
@@ -729,12 +703,6 @@ size_t csum_and_copy_to_iter(const void *addr, size_t bytes, __wsum *csum,
729 const char *from = addr; 703 const char *from = addr;
730 __wsum sum, next; 704 __wsum sum, next;
731 size_t off = 0; 705 size_t off = 0;
732 if (unlikely(bytes > i->count))
733 bytes = i->count;
734
735 if (unlikely(!bytes))
736 return 0;
737
738 sum = *csum; 706 sum = *csum;
739 iterate_and_advance(i, bytes, v, ({ 707 iterate_and_advance(i, bytes, v, ({
740 int err = 0; 708 int err = 0;