diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-18 14:46:23 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-18 14:46:23 -0400 |
| commit | 69370471d0b2fc3020c60f5473b1eef5977d165a (patch) | |
| tree | e0ba8b51204779afb17b5749657e9709e8a1ea3e | |
| parent | e34df3344d7b6f284e958147d7225faa340a1f39 (diff) | |
| parent | dd254f5a382cc7879db7a07ed266b12d38fe3ab6 (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.c | 2 | ||||
| -rw-r--r-- | fs/read_write.c | 33 | ||||
| -rw-r--r-- | lib/iov_iter.c | 104 |
3 files changed, 50 insertions, 89 deletions
| @@ -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 | } |
| 399 | EXPORT_SYMBOL(vfs_iter_write); | 399 | EXPORT_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 | */ | ||
| 406 | int rw_verify_area(int read_write, struct file *file, const loff_t *ppos, size_t count) | 401 | int 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 | ||
| 439 | static ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos) | 431 | static 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 | ||
| 138 | static size_t copy_page_to_iter_iovec(struct page *page, size_t offset, size_t bytes, | 142 | static 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) | |||
| 386 | size_t copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i) | 390 | size_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); | |||
| 407 | size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i) | 405 | size_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); | |||
| 428 | size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i) | 420 | size_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 | ||
| 475 | size_t iov_iter_zero(size_t bytes, struct iov_iter *i) | 461 | size_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; |
