Skip to content

Commit 9c8b7a2

Browse files
dhowellssmfrench
authored andcommitted
smb3: fix temporary data corruption in insert range
insert range doesn't discard the affected cached region so can risk temporarily corrupting file data. Also includes some minor cleanup (avoiding rereading inode size repeatedly unnecessarily) to make it clearer. Cc: stable@vger.kernel.org Fixes: 7fe6fe9 ("cifs: add FALLOC_FL_INSERT_RANGE support") Signed-off-by: David Howells <dhowells@redhat.com> cc: Ronnie Sahlberg <lsahlber@redhat.com> Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent fa30a81 commit 9c8b7a2

1 file changed

Lines changed: 16 additions & 8 deletions

File tree

fs/cifs/smb2ops.c

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3722,35 +3722,43 @@ static long smb3_insert_range(struct file *file, struct cifs_tcon *tcon,
37223722
struct cifsFileInfo *cfile = file->private_data;
37233723
struct inode *inode = file_inode(file);
37243724
__le64 eof;
3725-
__u64 count;
3725+
__u64 count, old_eof;
37263726

37273727
xid = get_xid();
37283728

3729-
if (off >= i_size_read(inode)) {
3729+
inode_lock(inode);
3730+
3731+
old_eof = i_size_read(inode);
3732+
if (off >= old_eof) {
37303733
rc = -EINVAL;
37313734
goto out;
37323735
}
37333736

3734-
count = i_size_read(inode) - off;
3735-
eof = cpu_to_le64(i_size_read(inode) + len);
3737+
count = old_eof - off;
3738+
eof = cpu_to_le64(old_eof + len);
37363739

3740+
filemap_invalidate_lock(inode->i_mapping);
37373741
filemap_write_and_wait(inode->i_mapping);
3742+
truncate_pagecache_range(inode, off, old_eof);
37383743

37393744
rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
37403745
cfile->fid.volatile_fid, cfile->pid, &eof);
37413746
if (rc < 0)
3742-
goto out;
3747+
goto out_2;
37433748

37443749
rc = smb2_copychunk_range(xid, cfile, cfile, off, count, off + len);
37453750
if (rc < 0)
3746-
goto out;
3751+
goto out_2;
37473752

3748-
rc = smb3_zero_range(file, tcon, off, len, 1);
3753+
rc = smb3_zero_data(file, tcon, off, len, xid);
37493754
if (rc < 0)
3750-
goto out;
3755+
goto out_2;
37513756

37523757
rc = 0;
3758+
out_2:
3759+
filemap_invalidate_unlock(inode->i_mapping);
37533760
out:
3761+
inode_unlock(inode);
37543762
free_xid(xid);
37553763
return rc;
37563764
}

0 commit comments

Comments
 (0)