Commit 69370471 authored by Linus Torvalds's avatar Linus Torvalds

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
parents e34df334 dd254f5a
...@@ -1447,8 +1447,6 @@ static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode, ...@@ -1447,8 +1447,6 @@ static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode,
return ret; return ret;
} }
len = ret;
if (rw == WRITE) if (rw == WRITE)
file_start_write(file); file_start_write(file);
......
...@@ -398,11 +398,6 @@ ssize_t vfs_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos) ...@@ -398,11 +398,6 @@ ssize_t vfs_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos)
} }
EXPORT_SYMBOL(vfs_iter_write); EXPORT_SYMBOL(vfs_iter_write);
/*
* rw_verify_area doesn't like huge counts. We limit
* them to something that fits in "int" so that others
* won't have to do range checks all the time.
*/
int rw_verify_area(int read_write, struct file *file, const loff_t *ppos, size_t count) int rw_verify_area(int read_write, struct file *file, const loff_t *ppos, size_t count)
{ {
struct inode *inode; struct inode *inode;
...@@ -429,11 +424,8 @@ int rw_verify_area(int read_write, struct file *file, const loff_t *ppos, size_t ...@@ -429,11 +424,8 @@ int rw_verify_area(int read_write, struct file *file, const loff_t *ppos, size_t
if (retval < 0) if (retval < 0)
return retval; return retval;
} }
retval = security_file_permission(file, return security_file_permission(file,
read_write == READ ? MAY_READ : MAY_WRITE); read_write == READ ? MAY_READ : MAY_WRITE);
if (retval)
return retval;
return count > MAX_RW_COUNT ? MAX_RW_COUNT : count;
} }
static ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos) 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,8 +469,9 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
return -EFAULT; return -EFAULT;
ret = rw_verify_area(READ, file, pos, count); ret = rw_verify_area(READ, file, pos, count);
if (ret >= 0) { if (!ret) {
count = ret; if (count > MAX_RW_COUNT)
count = MAX_RW_COUNT;
ret = __vfs_read(file, buf, count, pos); ret = __vfs_read(file, buf, count, pos);
if (ret > 0) { if (ret > 0) {
fsnotify_access(file); fsnotify_access(file);
...@@ -560,8 +553,9 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_ ...@@ -560,8 +553,9 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_
return -EFAULT; return -EFAULT;
ret = rw_verify_area(WRITE, file, pos, count); ret = rw_verify_area(WRITE, file, pos, count);
if (ret >= 0) { if (!ret) {
count = ret; if (count > MAX_RW_COUNT)
count = MAX_RW_COUNT;
file_start_write(file); file_start_write(file);
ret = __vfs_write(file, buf, count, pos); ret = __vfs_write(file, buf, count, pos);
if (ret > 0) { if (ret > 0) {
...@@ -1315,7 +1309,8 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, ...@@ -1315,7 +1309,8 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
retval = rw_verify_area(READ, in.file, &pos, count); retval = rw_verify_area(READ, in.file, &pos, count);
if (retval < 0) if (retval < 0)
goto fput_in; goto fput_in;
count = retval; if (count > MAX_RW_COUNT)
count = MAX_RW_COUNT;
/* /*
* Get output file, and verify that it is ok.. * 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,7 +1328,6 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
retval = rw_verify_area(WRITE, out.file, &out_pos, count); retval = rw_verify_area(WRITE, out.file, &out_pos, count);
if (retval < 0) if (retval < 0)
goto fput_out; goto fput_out;
count = retval;
if (!max) if (!max)
max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes); 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,11 +1471,12 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in,
if (flags != 0) if (flags != 0)
return -EINVAL; return -EINVAL;
/* copy_file_range allows full ssize_t len, ignoring MAX_RW_COUNT */
ret = rw_verify_area(READ, file_in, &pos_in, len); ret = rw_verify_area(READ, file_in, &pos_in, len);
if (ret >= 0) if (unlikely(ret))
ret = rw_verify_area(WRITE, file_out, &pos_out, len); return ret;
if (ret < 0)
ret = rw_verify_area(WRITE, file_out, &pos_out, len);
if (unlikely(ret))
return ret; return ret;
if (!(file_in->f_mode & FMODE_READ) || if (!(file_in->f_mode & FMODE_READ) ||
......
...@@ -99,40 +99,44 @@ ...@@ -99,40 +99,44 @@
} }
#define iterate_and_advance(i, n, v, I, B, K) { \ #define iterate_and_advance(i, n, v, I, B, K) { \
size_t skip = i->iov_offset; \ if (unlikely(i->count < n)) \
if (unlikely(i->type & ITER_BVEC)) { \ n = i->count; \
const struct bio_vec *bvec; \ if (n) { \
struct bio_vec v; \ size_t skip = i->iov_offset; \
iterate_bvec(i, n, v, bvec, skip, (B)) \ if (unlikely(i->type & ITER_BVEC)) { \
if (skip == bvec->bv_len) { \ const struct bio_vec *bvec; \
bvec++; \ struct bio_vec v; \
skip = 0; \ iterate_bvec(i, n, v, bvec, skip, (B)) \
} \ if (skip == bvec->bv_len) { \
i->nr_segs -= bvec - i->bvec; \ bvec++; \
i->bvec = bvec; \ skip = 0; \
} else if (unlikely(i->type & ITER_KVEC)) { \ } \
const struct kvec *kvec; \ i->nr_segs -= bvec - i->bvec; \
struct kvec v; \ i->bvec = bvec; \
iterate_kvec(i, n, v, kvec, skip, (K)) \ } else if (unlikely(i->type & ITER_KVEC)) { \
if (skip == kvec->iov_len) { \ const struct kvec *kvec; \
kvec++; \ struct kvec v; \
skip = 0; \ iterate_kvec(i, n, v, kvec, skip, (K)) \
} \ if (skip == kvec->iov_len) { \
i->nr_segs -= kvec - i->kvec; \ kvec++; \
i->kvec = kvec; \ skip = 0; \
} else { \ } \
const struct iovec *iov; \ i->nr_segs -= kvec - i->kvec; \
struct iovec v; \ i->kvec = kvec; \
iterate_iovec(i, n, v, iov, skip, (I)) \ } else { \
if (skip == iov->iov_len) { \ const struct iovec *iov; \
iov++; \ struct iovec v; \
skip = 0; \ iterate_iovec(i, n, v, iov, skip, (I)) \
if (skip == iov->iov_len) { \
iov++; \
skip = 0; \
} \
i->nr_segs -= iov - i->iov; \
i->iov = iov; \
} \ } \
i->nr_segs -= iov - i->iov; \ i->count -= n; \
i->iov = iov; \ i->iov_offset = skip; \
} \ } \
i->count -= n; \
i->iov_offset = skip; \
} }
static size_t copy_page_to_iter_iovec(struct page *page, size_t offset, size_t bytes, 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,12 +390,6 @@ static void memzero_page(struct page *page, size_t offset, size_t len)
size_t copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i) size_t copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i)
{ {
const char *from = addr; const char *from = addr;
if (unlikely(bytes > i->count))
bytes = i->count;
if (unlikely(!bytes))
return 0;
iterate_and_advance(i, bytes, v, iterate_and_advance(i, bytes, v,
__copy_to_user(v.iov_base, (from += v.iov_len) - v.iov_len, __copy_to_user(v.iov_base, (from += v.iov_len) - v.iov_len,
v.iov_len), v.iov_len),
...@@ -407,12 +405,6 @@ EXPORT_SYMBOL(copy_to_iter); ...@@ -407,12 +405,6 @@ EXPORT_SYMBOL(copy_to_iter);
size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i) size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i)
{ {
char *to = addr; char *to = addr;
if (unlikely(bytes > i->count))
bytes = i->count;
if (unlikely(!bytes))
return 0;
iterate_and_advance(i, bytes, v, iterate_and_advance(i, bytes, v,
__copy_from_user((to += v.iov_len) - v.iov_len, v.iov_base, __copy_from_user((to += v.iov_len) - v.iov_len, v.iov_base,
v.iov_len), v.iov_len),
...@@ -428,12 +420,6 @@ EXPORT_SYMBOL(copy_from_iter); ...@@ -428,12 +420,6 @@ EXPORT_SYMBOL(copy_from_iter);
size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i) size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i)
{ {
char *to = addr; char *to = addr;
if (unlikely(bytes > i->count))
bytes = i->count;
if (unlikely(!bytes))
return 0;
iterate_and_advance(i, bytes, v, iterate_and_advance(i, bytes, v,
__copy_from_user_nocache((to += v.iov_len) - v.iov_len, __copy_from_user_nocache((to += v.iov_len) - v.iov_len,
v.iov_base, v.iov_len), v.iov_base, v.iov_len),
...@@ -474,12 +460,6 @@ EXPORT_SYMBOL(copy_page_from_iter); ...@@ -474,12 +460,6 @@ EXPORT_SYMBOL(copy_page_from_iter);
size_t iov_iter_zero(size_t bytes, struct iov_iter *i) size_t iov_iter_zero(size_t bytes, struct iov_iter *i)
{ {
if (unlikely(bytes > i->count))
bytes = i->count;
if (unlikely(!bytes))
return 0;
iterate_and_advance(i, bytes, v, iterate_and_advance(i, bytes, v,
__clear_user(v.iov_base, v.iov_len), __clear_user(v.iov_base, v.iov_len),
memzero_page(v.bv_page, v.bv_offset, v.bv_len), 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,12 +665,6 @@ size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum,
char *to = addr; char *to = addr;
__wsum sum, next; __wsum sum, next;
size_t off = 0; size_t off = 0;
if (unlikely(bytes > i->count))
bytes = i->count;
if (unlikely(!bytes))
return 0;
sum = *csum; sum = *csum;
iterate_and_advance(i, bytes, v, ({ iterate_and_advance(i, bytes, v, ({
int err = 0; int err = 0;
...@@ -729,12 +703,6 @@ size_t csum_and_copy_to_iter(const void *addr, size_t bytes, __wsum *csum, ...@@ -729,12 +703,6 @@ size_t csum_and_copy_to_iter(const void *addr, size_t bytes, __wsum *csum,
const char *from = addr; const char *from = addr;
__wsum sum, next; __wsum sum, next;
size_t off = 0; size_t off = 0;
if (unlikely(bytes > i->count))
bytes = i->count;
if (unlikely(!bytes))
return 0;
sum = *csum; sum = *csum;
iterate_and_advance(i, bytes, v, ({ iterate_and_advance(i, bytes, v, ({
int err = 0; int err = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment