Skip to content

Commit 836bb32

Browse files
author
Steve French
committed
smb3: fix lock breakage for cached writes
Mandatory locking is enforced for cached writes, which violates default posix semantics, and also it is enforced inconsistently. This apparently breaks recent versions of libreoffice, but can also be demonstrated by opening a file twice from the same client, locking it from handle one and writing to it from handle two (which fails, returning EACCES). Since there was already a mount option "forcemandatorylock" (which defaults to off), with this change only when the user intentionally specifies "forcemandatorylock" on mount will we break posix semantics on write to a locked range (ie we will only fail the write in this case, if the user mounts with "forcemandatorylock"). Fixes: 85160e0 ("CIFS: Implement caching mechanism for mandatory brlocks") Cc: stable@vger.kernel.org Cc: Pavel Shilovsky <piastryyy@gmail.com> Reported-by: abartlet@samba.org Reported-by: Kevin Ottens <kevin.ottens@enioka.com> Reviewed-by: David Howells <dhowells@redhat.com> Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent 74c2ab6 commit 836bb32

File tree

1 file changed

+9
-4
lines changed

1 file changed

+9
-4
lines changed

fs/smb/client/file.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2753,6 +2753,7 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from)
27532753
struct inode *inode = file->f_mapping->host;
27542754
struct cifsInodeInfo *cinode = CIFS_I(inode);
27552755
struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
2756+
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
27562757
ssize_t rc;
27572758

27582759
rc = netfs_start_io_write(inode);
@@ -2769,12 +2770,16 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from)
27692770
if (rc <= 0)
27702771
goto out;
27712772

2772-
if (!cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(from),
2773+
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) &&
2774+
(cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(from),
27732775
server->vals->exclusive_lock_type, 0,
2774-
NULL, CIFS_WRITE_OP))
2775-
rc = netfs_buffered_write_iter_locked(iocb, from, NULL);
2776-
else
2776+
NULL, CIFS_WRITE_OP))) {
27772777
rc = -EACCES;
2778+
goto out;
2779+
}
2780+
2781+
rc = netfs_buffered_write_iter_locked(iocb, from, NULL);
2782+
27782783
out:
27792784
up_read(&cinode->lock_sem);
27802785
netfs_end_io_write(inode);

0 commit comments

Comments
 (0)