Skip to content

Commit 1fd7ced

Browse files
committed
SMB3: drop reference to cfile before sending oplock break
jira VULN-131073 cve-pre CVE-2025-38527 commit-author Bharath SM <bharathsm@microsoft.com> commit 59a556a In cifs_oplock_break function we drop reference to a cfile at the end of function, due to which close command goes on wire after lease break acknowledgment even if file is already closed by application but we had deferred the handle close. If other client with limited file shareaccess waiting on lease break ack proceeds operation on that file as soon as first client sends ack, then we may encounter status sharing violation error because of open handle. Solution is to put reference to cfile(send close on wire if last ref) and then send oplock acknowledgment to server. Fixes: 9e31678 ("SMB3: fix lease break timeout when multiple deferred close handles for the same file.") Cc: stable@kernel.org Signed-off-by: Bharath SM <bharathsm@microsoft.com> Reviewed-by: Shyam Prasad N <sprasad@microsoft.com> Signed-off-by: Steve French <stfrench@microsoft.com> (cherry picked from commit 59a556a) Signed-off-by: Brett Mastbergen <bmastbergen@ciq.com>
1 parent dce8477 commit 1fd7ced

File tree

4 files changed

+21
-16
lines changed

4 files changed

+21
-16
lines changed

fs/cifs/cifsglob.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -420,8 +420,8 @@ struct smb_version_operations {
420420
/* check for STATUS_NETWORK_SESSION_EXPIRED */
421421
bool (*is_session_expired)(char *);
422422
/* send oplock break response */
423-
int (*oplock_response)(struct cifs_tcon *, struct cifs_fid *,
424-
struct cifsInodeInfo *);
423+
int (*oplock_response)(struct cifs_tcon *tcon, __u64 persistent_fid, __u64 volatile_fid,
424+
__u16 net_fid, struct cifsInodeInfo *cifs_inode);
425425
/* query remote filesystem */
426426
int (*queryfs)(const unsigned int, struct cifs_tcon *,
427427
struct cifs_sb_info *, struct kstatfs *);

fs/cifs/file.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5052,7 +5052,9 @@ void cifs_oplock_break(struct work_struct *work)
50525052
struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
50535053
struct TCP_Server_Info *server = tcon->ses->server;
50545054
int rc = 0;
5055-
bool purge_cache = false;
5055+
bool purge_cache = false, oplock_break_cancelled;
5056+
__u64 persistent_fid, volatile_fid;
5057+
__u16 net_fid;
50565058

50575059
wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS,
50585060
TASK_UNINTERRUPTIBLE);
@@ -5097,19 +5099,24 @@ void cifs_oplock_break(struct work_struct *work)
50975099
if (!CIFS_CACHE_HANDLE(cinode) && !list_empty(&cinode->deferred_closes))
50985100
cifs_close_deferred_file(cinode);
50995101

5102+
persistent_fid = cfile->fid.persistent_fid;
5103+
volatile_fid = cfile->fid.volatile_fid;
5104+
net_fid = cfile->fid.netfid;
5105+
oplock_break_cancelled = cfile->oplock_break_cancelled;
5106+
5107+
_cifsFileInfo_put(cfile, false /* do not wait for ourself */, false);
51005108
/*
51015109
* releasing stale oplock after recent reconnect of smb session using
51025110
* a now incorrect file handle is not a data integrity issue but do
51035111
* not bother sending an oplock release if session to server still is
51045112
* disconnected since oplock already released by the server
51055113
*/
5106-
if (!cfile->oplock_break_cancelled) {
5107-
rc = tcon->ses->server->ops->oplock_response(tcon, &cfile->fid,
5108-
cinode);
5114+
if (!oplock_break_cancelled) {
5115+
rc = tcon->ses->server->ops->oplock_response(tcon, persistent_fid,
5116+
volatile_fid, net_fid, cinode);
51095117
cifs_dbg(FYI, "Oplock release rc = %d\n", rc);
51105118
}
51115119

5112-
_cifsFileInfo_put(cfile, false /* do not wait for ourself */, false);
51135120
cifs_done_oplock_break(cinode);
51145121
}
51155122

fs/cifs/smb1ops.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -872,12 +872,11 @@ cifs_close_dir(const unsigned int xid, struct cifs_tcon *tcon,
872872
}
873873

874874
static int
875-
cifs_oplock_response(struct cifs_tcon *tcon, struct cifs_fid *fid,
876-
struct cifsInodeInfo *cinode)
875+
cifs_oplock_response(struct cifs_tcon *tcon, __u64 persistent_fid,
876+
__u64 volatile_fid, __u16 net_fid, struct cifsInodeInfo *cinode)
877877
{
878-
return CIFSSMBLock(0, tcon, fid->netfid, current->tgid, 0, 0, 0, 0,
879-
LOCKING_ANDX_OPLOCK_RELEASE, false,
880-
CIFS_CACHE_READ(cinode) ? 1 : 0);
878+
return CIFSSMBLock(0, tcon, net_fid, current->tgid, 0, 0, 0, 0,
879+
LOCKING_ANDX_OPLOCK_RELEASE, false, CIFS_CACHE_READ(cinode) ? 1 : 0);
881880
}
882881

883882
static int

fs/cifs/smb2ops.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2309,15 +2309,14 @@ smb2_is_network_name_deleted(char *buf, struct TCP_Server_Info *server)
23092309
}
23102310

23112311
static int
2312-
smb2_oplock_response(struct cifs_tcon *tcon, struct cifs_fid *fid,
2313-
struct cifsInodeInfo *cinode)
2312+
smb2_oplock_response(struct cifs_tcon *tcon, __u64 persistent_fid,
2313+
__u64 volatile_fid, __u16 net_fid, struct cifsInodeInfo *cinode)
23142314
{
23152315
if (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING)
23162316
return SMB2_lease_break(0, tcon, cinode->lease_key,
23172317
smb2_get_lease_state(cinode));
23182318

2319-
return SMB2_oplock_break(0, tcon, fid->persistent_fid,
2320-
fid->volatile_fid,
2319+
return SMB2_oplock_break(0, tcon, persistent_fid, volatile_fid,
23212320
CIFS_CACHE_READ(cinode) ? 1 : 0);
23222321
}
23232322

0 commit comments

Comments
 (0)