This is a note to let you know that I've just added the patch titled smb3: fix temporary data corruption in insert range to the 5.19-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: smb3-fix-temporary-data-corruption-in-insert-range.patch and it can be found in the queue-5.19 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. commit 8b64323e4828fd9b330d892005051e1d4f36dd0f Author: David Howells <dhowells@xxxxxxxxxx> Date: Tue Aug 23 14:07:55 2022 +0100 smb3: fix temporary data corruption in insert range [ Upstream commit 9c8b7a293f50253e694f19161c045817a938e551 ] 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@xxxxxxxxxxxxxxx Fixes: 7fe6fe95b936 ("cifs: add FALLOC_FL_INSERT_RANGE support") Signed-off-by: David Howells <dhowells@xxxxxxxxxx> cc: Ronnie Sahlberg <lsahlber@xxxxxxxxxx> Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx> Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 8e55495c4f7e..774c6e5f6584 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -4005,35 +4005,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; }