]> Git Repo - linux.git/commitdiff
smb3: fix temporary data corruption in insert range
authorDavid Howells <[email protected]>
Tue, 23 Aug 2022 13:07:55 +0000 (14:07 +0100)
committerSteve French <[email protected]>
Mon, 29 Aug 2022 03:34:08 +0000 (22:34 -0500)
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: [email protected]
Fixes: 7fe6fe95b936 ("cifs: add FALLOC_FL_INSERT_RANGE support")
Signed-off-by: David Howells <[email protected]>
cc: Ronnie Sahlberg <[email protected]>
Signed-off-by: Steve French <[email protected]>
fs/cifs/smb2ops.c

index 5b5ddc1b4638f2cead43c2a3cb6d83db3d32ae18..7c941ce1e7a9f3d3e3b2925e6943d236b91afaf4 100644 (file)
@@ -3722,35 +3722,43 @@ static long smb3_insert_range(struct file *file, struct cifs_tcon *tcon,
        struct cifsFileInfo *cfile = file->private_data;
        struct inode *inode = file_inode(file);
        __le64 eof;
-       __u64  count;
+       __u64  count, old_eof;
 
        xid = get_xid();
 
-       if (off >= i_size_read(inode)) {
+       inode_lock(inode);
+
+       old_eof = i_size_read(inode);
+       if (off >= old_eof) {
                rc = -EINVAL;
                goto out;
        }
 
-       count = i_size_read(inode) - off;
-       eof = cpu_to_le64(i_size_read(inode) + len);
+       count = old_eof - off;
+       eof = cpu_to_le64(old_eof + len);
 
+       filemap_invalidate_lock(inode->i_mapping);
        filemap_write_and_wait(inode->i_mapping);
+       truncate_pagecache_range(inode, off, old_eof);
 
        rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
                          cfile->fid.volatile_fid, cfile->pid, &eof);
        if (rc < 0)
-               goto out;
+               goto out_2;
 
        rc = smb2_copychunk_range(xid, cfile, cfile, off, count, off + len);
        if (rc < 0)
-               goto out;
+               goto out_2;
 
-       rc = smb3_zero_range(file, tcon, off, len, 1);
+       rc = smb3_zero_data(file, tcon, off, len, xid);
        if (rc < 0)
-               goto out;
+               goto out_2;
 
        rc = 0;
+out_2:
+       filemap_invalidate_unlock(inode->i_mapping);
  out:
+       inode_unlock(inode);
        free_xid(xid);
        return rc;
 }
This page took 0.054062 seconds and 4 git commands to generate.