aboutsummaryrefslogtreecommitdiffstats
path: root/fs/compat.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-10-29 13:36:49 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-29 13:36:49 -0400
commit435f49a518c78eec8e2edbbadd912737246cbe20 (patch)
tree106df2617d42ace231e2fa9fcf1e0fd1075874ea /fs/compat.c
parentf56f44001cb5b40089deac094dbb74e5c9f64d81 (diff)
readv/writev: do the same MAX_RW_COUNT truncation that read/write does
We used to protect against overflow, but rather than return an error, do what read/write does, namely to limit the total size to MAX_RW_COUNT. This is not only more consistent, but it also means that any broken low-level read/write routine that still keeps counts in 'int' can't break. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/compat.c')
-rw-r--r--fs/compat.c12
1 files changed, 6 insertions, 6 deletions
diff --git a/fs/compat.c b/fs/compat.c
index 52cfeb61da77..ff66c0d7583d 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -606,14 +606,14 @@ ssize_t compat_rw_copy_check_uvector(int type,
606 /* 606 /*
607 * Single unix specification: 607 * Single unix specification:
608 * We should -EINVAL if an element length is not >= 0 and fitting an 608 * We should -EINVAL if an element length is not >= 0 and fitting an
609 * ssize_t. The total length is fitting an ssize_t 609 * ssize_t.
610 * 610 *
611 * Be careful here because iov_len is a size_t not an ssize_t 611 * In Linux, the total length is limited to MAX_RW_COUNT, there is
612 * no overflow possibility.
612 */ 613 */
613 tot_len = 0; 614 tot_len = 0;
614 ret = -EINVAL; 615 ret = -EINVAL;
615 for (seg = 0; seg < nr_segs; seg++) { 616 for (seg = 0; seg < nr_segs; seg++) {
616 compat_ssize_t tmp = tot_len;
617 compat_uptr_t buf; 617 compat_uptr_t buf;
618 compat_ssize_t len; 618 compat_ssize_t len;
619 619
@@ -624,13 +624,13 @@ ssize_t compat_rw_copy_check_uvector(int type,
624 } 624 }
625 if (len < 0) /* size_t not fitting in compat_ssize_t .. */ 625 if (len < 0) /* size_t not fitting in compat_ssize_t .. */
626 goto out; 626 goto out;
627 tot_len += len;
628 if (tot_len < tmp) /* maths overflow on the compat_ssize_t */
629 goto out;
630 if (!access_ok(vrfy_dir(type), compat_ptr(buf), len)) { 627 if (!access_ok(vrfy_dir(type), compat_ptr(buf), len)) {
631 ret = -EFAULT; 628 ret = -EFAULT;
632 goto out; 629 goto out;
633 } 630 }
631 if (len > MAX_RW_COUNT - tot_len)
632 len = MAX_RW_COUNT - tot_len;
633 tot_len += len;
634 iov->iov_base = compat_ptr(buf); 634 iov->iov_base = compat_ptr(buf);
635 iov->iov_len = (compat_size_t) len; 635 iov->iov_len = (compat_size_t) len;
636 uvector++; 636 uvector++;