diff options
author | Miklos Szeredi <mszeredi@suse.cz> | 2014-05-27 16:41:16 +0200 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2014-05-28 01:54:52 -0400 |
commit | b6dd6f4738837439c520e73995ec93fe1de2ec72 (patch) | |
tree | 625ca1eb1d708ea7ceccba35362ee6ffa1daf9da /fs/splice.c | |
parent | c7208164e66f63e3ec1759b98087849286410741 (diff) | |
download | lwn-b6dd6f4738837439c520e73995ec93fe1de2ec72.tar.gz lwn-b6dd6f4738837439c520e73995ec93fe1de2ec72.zip |
vfs: fix vmplice_to_user()
Commit 6130f5315ee8 "switch vmsplice_to_user() to copy_page_to_iter()" in
v3.15-rc1 broke vmsplice(2).
This patch fixes two bugs:
- count is not initialized to a proper value, which resulted in no data
being copied
- if rw_copy_check_uvector() returns negative then the iov might be leaked.
Tested OK.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/splice.c')
-rw-r--r-- | fs/splice.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/fs/splice.c b/fs/splice.c index 9bc07d2b53cf..e246954ea48c 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -1537,7 +1537,7 @@ static long vmsplice_to_user(struct file *file, const struct iovec __user *uiov, struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov = iovstack; struct iov_iter iter; - ssize_t count = 0; + ssize_t count; pipe = get_pipe_info(file); if (!pipe) @@ -1546,8 +1546,9 @@ static long vmsplice_to_user(struct file *file, const struct iovec __user *uiov, ret = rw_copy_check_uvector(READ, uiov, nr_segs, ARRAY_SIZE(iovstack), iovstack, &iov); if (ret <= 0) - return ret; + goto out; + count = ret; iov_iter_init(&iter, iov, nr_segs, count, 0); sd.len = 0; @@ -1560,6 +1561,7 @@ static long vmsplice_to_user(struct file *file, const struct iovec __user *uiov, ret = __splice_from_pipe(pipe, &sd, pipe_to_user); pipe_unlock(pipe); +out: if (iov != iovstack) kfree(iov); |