diff options
| -rw-r--r-- | fs/btrfs/ioctl.c | 12 | 
1 files changed, 10 insertions, 2 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index ed3ba55f65ac..95f9625dccc4 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -4279,9 +4279,17 @@ static noinline int btrfs_clone_files(struct file *file, struct file *file_src,  		goto out_unlock;  	if (len == 0)  		olen = len = src->i_size - off; -	/* if we extend to eof, continue to block boundary */ -	if (off + len == src->i_size) +	/* +	 * If we extend to eof, continue to block boundary if and only if the +	 * destination end offset matches the destination file's size, otherwise +	 * we would be corrupting data by placing the eof block into the middle +	 * of a file. +	 */ +	if (off + len == src->i_size) { +		if (!IS_ALIGNED(len, bs) && destoff + len < inode->i_size) +			goto out_unlock;  		len = ALIGN(src->i_size, bs) - off; +	}  	if (len == 0) {  		ret = 0;  | 
