Skip to content

Commit c09abe8

Browse files
committed
cifs: fix potential oops in cifs_oplock_break
jira VULN-131073 cve-pre CVE-2025-38527 commit-author Steve French <[email protected]> commit e8f5f84 With deferred close we can have closes that race with lease breaks, and so with the current checks for whether to send the lease response, oplock_response(), this can mean that an unmount (kill_sb) can occur just before we were checking if the tcon->ses is valid. See below: [Fri Aug 4 04:12:50 2023] RIP: 0010:cifs_oplock_break+0x1f7/0x5b0 [cifs] [Fri Aug 4 04:12:50 2023] Code: 7d a8 48 8b 7d c0 c0 e9 02 48 89 45 b8 41 89 cf e8 3e f5 ff ff 4c 89 f7 41 83 e7 01 e8 82 b3 03 f2 49 8b 45 50 48 85 c0 74 5e <48> 83 78 60 00 74 57 45 84 ff 75 52 48 8b 43 98 48 83 eb 68 48 39 [Fri Aug 4 04:12:50 2023] RSP: 0018:ffffb30607ddbdf8 EFLAGS: 00010206 [Fri Aug 4 04:12:50 2023] RAX: 632d223d32612022 RBX: ffff97136944b1e0 RCX: 0000000080100009 [Fri Aug 4 04:12:50 2023] RDX: 0000000000000001 RSI: 0000000080100009 RDI: ffff97136944b188 [Fri Aug 4 04:12:50 2023] RBP: ffffb30607ddbe58 R08: 0000000000000001 R09: ffffffffc08e0900 [Fri Aug 4 04:12:50 2023] R10: 0000000000000001 R11: 000000000000000f R12: ffff97136944b138 [Fri Aug 4 04:12:50 2023] R13: ffff97149147c000 R14: ffff97136944b188 R15: 0000000000000000 [Fri Aug 4 04:12:50 2023] FS: 0000000000000000(0000) GS:ffff9714f7c00000(0000) knlGS:0000000000000000 [Fri Aug 4 04:12:50 2023] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [Fri Aug 4 04:12:50 2023] CR2: 00007fd8de9c7590 CR3: 000000011228e000 CR4: 0000000000350ef0 [Fri Aug 4 04:12:50 2023] Call Trace: [Fri Aug 4 04:12:50 2023] <TASK> [Fri Aug 4 04:12:50 2023] process_one_work+0x225/0x3d0 [Fri Aug 4 04:12:50 2023] worker_thread+0x4d/0x3e0 [Fri Aug 4 04:12:50 2023] ? process_one_work+0x3d0/0x3d0 [Fri Aug 4 04:12:50 2023] kthread+0x12a/0x150 [Fri Aug 4 04:12:50 2023] ? set_kthread_struct+0x50/0x50 [Fri Aug 4 04:12:50 2023] ret_from_fork+0x22/0x30 [Fri Aug 4 04:12:50 2023] </TASK> To fix this change the ordering of the checks before sending the oplock_response to first check if the openFileList is empty. Fixes: da787d5 ("SMB3: Do not send lease break acknowledgment if all file handles have been closed") Suggested-by: Bharath SM <[email protected]> Reviewed-by: Bharath SM <[email protected]> Reviewed-by: Shyam Prasad N <[email protected]> Signed-off-by: Paulo Alcantara (SUSE) <[email protected]> Signed-off-by: Steve French <[email protected]> (cherry picked from commit e8f5f84) Signed-off-by: Brett Mastbergen <[email protected]>
1 parent d8eb12b commit c09abe8

File tree

1 file changed

+16
-7
lines changed

1 file changed

+16
-7
lines changed

fs/cifs/file.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5048,9 +5048,11 @@ void cifs_oplock_break(struct work_struct *work)
50485048
struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
50495049
oplock_break);
50505050
struct inode *inode = d_inode(cfile->dentry);
5051+
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
50515052
struct cifsInodeInfo *cinode = CIFS_I(inode);
5052-
struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
5053-
struct TCP_Server_Info *server = tcon->ses->server;
5053+
struct cifs_tcon *tcon;
5054+
struct TCP_Server_Info *server;
5055+
struct tcon_link *tlink;
50545056
int rc = 0;
50555057
bool purge_cache = false, oplock_break_cancelled;
50565058
__u64 persistent_fid, volatile_fid;
@@ -5059,6 +5061,12 @@ void cifs_oplock_break(struct work_struct *work)
50595061
wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS,
50605062
TASK_UNINTERRUPTIBLE);
50615063

5064+
tlink = cifs_sb_tlink(cifs_sb);
5065+
if (IS_ERR(tlink))
5066+
goto out;
5067+
tcon = tlink_tcon(tlink);
5068+
server = tcon->ses->server;
5069+
50625070
server->ops->downgrade_oplock(server, cinode, cfile->oplock_level,
50635071
cfile->oplock_epoch, &purge_cache);
50645072

@@ -5108,18 +5116,19 @@ void cifs_oplock_break(struct work_struct *work)
51085116
/*
51095117
* MS-SMB2 3.2.5.19.1 and 3.2.5.19.2 (and MS-CIFS 3.2.5.42) do not require
51105118
* an acknowledgment to be sent when the file has already been closed.
5111-
* check for server null, since can race with kill_sb calling tree disconnect.
51125119
*/
51135120
spin_lock(&cinode->open_file_lock);
5114-
if (tcon->ses && tcon->ses->server && !oplock_break_cancelled &&
5115-
!list_empty(&cinode->openFileList)) {
5121+
/* check list empty since can race with kill_sb calling tree disconnect */
5122+
if (!oplock_break_cancelled && !list_empty(&cinode->openFileList)) {
51165123
spin_unlock(&cinode->open_file_lock);
5117-
rc = tcon->ses->server->ops->oplock_response(tcon, persistent_fid,
5118-
volatile_fid, net_fid, cinode);
5124+
rc = server->ops->oplock_response(tcon, persistent_fid,
5125+
volatile_fid, net_fid, cinode);
51195126
cifs_dbg(FYI, "Oplock release rc = %d\n", rc);
51205127
} else
51215128
spin_unlock(&cinode->open_file_lock);
51225129

5130+
cifs_put_tlink(tlink);
5131+
out:
51235132
cifs_done_oplock_break(cinode);
51245133
}
51255134

0 commit comments

Comments
 (0)