[PATCH RFC v2] smb: client: fix double decrement of server->in_flight

"syzbot" <[email protected]>
Newsgroups dev.linux.lists.syzbot
Message-ID <[email protected]>
During a failed send or reconnect, the reconnect thread can process a
still-queued multiplex ID (MID) before the sender returns the same
reservation. This double completion corrupts request accounting, wraps the
unsigned server->in_flight counter to UINT_MAX, and can affect system
availability by blocking further requests.

Specifically, when smb_send_rqst() fails (e.g., with -ECONNRESET), it
signals the cifsd thread for a reconnect. If compound_send_recv() drops the
cifs_server_lock(server) before removing the MIDs from the pending queue,
the cifsd thread can wake up, acquire the lock, and execute
cifs_abort_connection().

cifs_abort_connection() iterates over server->pending_mid_q, finds the MIDs
that failed to send, and executes their callbacks (cifs_compound_callback).
Because no response was received, the callback calls add_credits() with 0
credits. smb2_add_credits() unconditionally decrements server->in_flight,
even if the number of credits being added is 0.

After the callback finishes, compound_send_recv() continues its execution,
sees that rc < 0, and explicitly calls add_credits() to return the credits
it originally reserved. This results in a second call to
smb2_add_credits(), which decrements server->in_flight again. Since
in_flight was already decremented to 0 by the callback, this second
decrement triggers a warning and wraps the unsigned counter to UINT_MAX.

CIFS: VFS: \\127.0.0.1 Error -32 sending data on socket to server
------------[ cut here ]------------
server->in_flight == 0
WARNING: fs/smb/client/smb2ops.c:104 at smb2_add_credits+0x1249/0x2b70
fs/smb/client/smb2ops.c:104
Call Trace:
 <TASK>
 add_credits fs/smb/client/cifsglob.h:894 [inline]
 compound_send_recv+0x13b4/0x2b90 fs/smb/client/transport.c:979
 cifs_send_recv+0x42/0x60 fs/smb/client/transport.c:1106
 SMB2_negotiate+0x164d/0x4030 fs/smb/client/smb2pdu.c:1188
 cifs_negotiate_protocol+0x45d/0x680 fs/smb/client/connect.c:4043
 cifs_get_smb_ses+0x1104/0x1ff0 fs/smb/client/connect.c:2492
 cifs_mount_get_session+0xf1/0x450 fs/smb/client/connect.c:3578
 get_session fs/smb/client/dfs.c:65 [inline]
 dfs_mount_share+0x22e/0x990 fs/smb/client/dfs.c:275
 cifs_mount+0xcc/0xbf0 fs/smb/client/connect.c:3860
 cifs_smb3_do_mount+0x2d0/0x8a0 fs/smb/client/cifsfs.c:1024
 smb3_get_tree_common fs/smb/client/fs_context.c:897 [inline]
 smb3_get_tree+0x2dd/0x400 fs/smb/client/fs_context.c:917
 vfs_get_tree+0x92/0x2a0 fs/super.c:1700
 fc_mount fs/namespace.c:1198 [inline]
 do_new_mount_fc fs/namespace.c:3765 [inline]
 do_new_mount+0x319/0xdc0 fs/namespace.c:3841
 do_mount fs/namespace.c:4174 [inline]
 __do_sys_mount fs/namespace.c:4390 [inline]
 __se_sys_mount+0x31d/0x420 fs/namespace.c:4367
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0x174/0x580 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
 </TASK>

To fix this, ensure that the cifsd thread cannot observe these MIDs if the
request failed to send (rc < 0) or if no response is expected (flags &
CIFS_NO_SRV_RSP). By calling delete_mid() before dropping
cifs_server_lock(server), we safely remove the MIDs from the pending queue
while still holding the mutex. This guarantees that cifs_abort_connection()
will not find them and will not execute their callbacks. We also set
cancelled_mid[i] = true so that the common cleanup code safely skips the
already-deleted MIDs, preventing any double-free issues.

Fixes: ee258d79159a ("CIFS: Move credit processing to mid callbacks for SMB3")
Assisted-by: Gemini:gemini-3.5-flash Gemini:gemini-3.1-pro-preview syzbot
Reported-by: [email protected]
Closes: https://syzkaller.appspot.com/bug?extid=eeb58d2197d88720a228
Link: https://syzkaller.appspot.com/ai_job?id=41f83e92-1b53-4701-b089-30a34a1b8cc8
To: <[email protected]>
To: <[email protected]>
To: "Steve French" <[email protected]>
To: "Pavel Shilovsky" <[email protected]>
Cc: "Bharath SM" <[email protected]>
Cc: <[email protected]>
Cc: "Paulo Alcantara" <[email protected]>
Cc: "Ronnie Sahlberg" <[email protected]>
Cc: "Shyam Prasad N" <[email protected]>
Cc: "Tom Talpey" <[email protected]>

---
v2:
- Updated the commit description to lead with the failed-send/reconnect trigger and its impact on request accounting and system availability.
- Corrected the description to state that the unsigned server->in_flight counter wraps to UINT_MAX instead of becoming -1.

v1:
https://lore.kernel.org/all/[email protected]/T/
---
diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c
index fdf4e50c2..8d14225e9 100644
--- a/fs/smb/client/transport.c
+++ b/fs/smb/client/transport.c
@@ -968,6 +968,13 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
 		server->sequence_number -= 2;
 	}
 
+	if (rc < 0 || (flags & CIFS_NO_SRV_RSP)) {
+		for (i = 0; i < num_rqst; i++) {
+			delete_mid(server, mid[i]);
+			cancelled_mid[i] = true;
+		}
+	}
+
 	cifs_server_unlock(server);
 
 	/*


base-commit: 075b74841bd0065a3bda3440873c747938e69b68
-- 
This is an AI-generated patch subject to moderation.
Reply with '#syz upstream' to Sign-off the patch as a human author
and send it to the upstream kernel mailing lists.
Reply with '#syz reject' to reject it ('#syz unreject' to undo).

See https://goo.gle/syzbot-ai-patches for information about AI-generated patches.
The person who has signed off on the patch is responsible for
addressing comments.
syzbot engineers can be reached at [email protected].
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.