Commit 22725ce4 authored by Darrick J. Wong's avatar Darrick J. Wong Committed by Al Viro

vfs: fix isize/pos/len checks for reflink & dedupe

Strengthen the checking of pos/len vs. i_size, clarify the return values
for the clone prep function, and remove pointless code.
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 33844e66
...@@ -4834,7 +4834,7 @@ int ocfs2_reflink_remap_range(struct file *file_in, ...@@ -4834,7 +4834,7 @@ int ocfs2_reflink_remap_range(struct file *file_in,
ret = vfs_clone_file_prep_inodes(inode_in, pos_in, inode_out, pos_out, ret = vfs_clone_file_prep_inodes(inode_in, pos_in, inode_out, pos_out,
&len, is_dedupe); &len, is_dedupe);
if (ret || len == 0) if (ret <= 0)
goto out_unlock; goto out_unlock;
/* Lock out changes to the allocation maps and remap. */ /* Lock out changes to the allocation maps and remap. */
......
...@@ -1669,6 +1669,9 @@ static int clone_verify_area(struct file *file, loff_t pos, u64 len, bool write) ...@@ -1669,6 +1669,9 @@ static int clone_verify_area(struct file *file, loff_t pos, u64 len, bool write)
* Check that the two inodes are eligible for cloning, the ranges make * Check that the two inodes are eligible for cloning, the ranges make
* sense, and then flush all dirty data. Caller must ensure that the * sense, and then flush all dirty data. Caller must ensure that the
* inodes have been locked against any other modifications. * inodes have been locked against any other modifications.
*
* Returns: 0 for "nothing to clone", 1 for "something to clone", or
* the usual negative error code.
*/ */
int vfs_clone_file_prep_inodes(struct inode *inode_in, loff_t pos_in, int vfs_clone_file_prep_inodes(struct inode *inode_in, loff_t pos_in,
struct inode *inode_out, loff_t pos_out, struct inode *inode_out, loff_t pos_out,
...@@ -1695,17 +1698,15 @@ int vfs_clone_file_prep_inodes(struct inode *inode_in, loff_t pos_in, ...@@ -1695,17 +1698,15 @@ int vfs_clone_file_prep_inodes(struct inode *inode_in, loff_t pos_in,
/* Are we going all the way to the end? */ /* Are we going all the way to the end? */
isize = i_size_read(inode_in); isize = i_size_read(inode_in);
if (isize == 0) { if (isize == 0)
*len = 0;
return 0; return 0;
}
/* Zero length dedupe exits immediately; reflink goes to EOF. */ /* Zero length dedupe exits immediately; reflink goes to EOF. */
if (*len == 0) { if (*len == 0) {
if (is_dedupe) { if (is_dedupe || pos_in == isize)
*len = 0;
return 0; return 0;
} if (pos_in > isize)
return -EINVAL;
*len = isize - pos_in; *len = isize - pos_in;
} }
...@@ -1769,7 +1770,7 @@ int vfs_clone_file_prep_inodes(struct inode *inode_in, loff_t pos_in, ...@@ -1769,7 +1770,7 @@ int vfs_clone_file_prep_inodes(struct inode *inode_in, loff_t pos_in,
return -EBADE; return -EBADE;
} }
return 0; return 1;
} }
EXPORT_SYMBOL(vfs_clone_file_prep_inodes); EXPORT_SYMBOL(vfs_clone_file_prep_inodes);
...@@ -1955,6 +1956,9 @@ int vfs_dedupe_file_range(struct file *file, struct file_dedupe_range *same) ...@@ -1955,6 +1956,9 @@ int vfs_dedupe_file_range(struct file *file, struct file_dedupe_range *same)
goto out; goto out;
ret = 0; ret = 0;
if (off + len > i_size_read(src))
return -EINVAL;
/* pre-format output fields to sane values */ /* pre-format output fields to sane values */
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
same->info[i].bytes_deduped = 0ULL; same->info[i].bytes_deduped = 0ULL;
......
...@@ -1161,7 +1161,7 @@ xfs_reflink_remap_range( ...@@ -1161,7 +1161,7 @@ xfs_reflink_remap_range(
ret = vfs_clone_file_prep_inodes(inode_in, pos_in, inode_out, pos_out, ret = vfs_clone_file_prep_inodes(inode_in, pos_in, inode_out, pos_out,
&len, is_dedupe); &len, is_dedupe);
if (ret || len == 0) if (ret <= 0)
goto out_unlock; goto out_unlock;
trace_xfs_reflink_remap_range(src, pos_in, len, dest, pos_out); trace_xfs_reflink_remap_range(src, pos_in, len, dest, pos_out);
......
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