]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ksmbd: do not expire session on binding failure
authorHyunwoo Kim <imv4bel@gmail.com>
Mon, 16 Mar 2026 23:52:01 +0000 (08:52 +0900)
committerSteve French <stfrench@microsoft.com>
Sun, 22 Mar 2026 22:15:00 +0000 (17:15 -0500)
When a multichannel session binding request fails (e.g. wrong password),
the error path unconditionally sets sess->state = SMB2_SESSION_EXPIRED.
However, during binding, sess points to the target session looked up via
ksmbd_session_lookup_slowpath() -- which belongs to another connection's
user. This allows a remote attacker to invalidate any active session by
simply sending a binding request with a wrong password (DoS).

Fix this by skipping session expiration when the failed request was
a binding attempt, since the session does not belong to the current
connection. The reference taken by ksmbd_session_lookup_slowpath() is
still correctly released via ksmbd_user_session_put().

Cc: stable@vger.kernel.org
Signed-off-by: Hyunwoo Kim <imv4bel@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/server/smb2pdu.c

index 9c44e71e3c3baccfdd2c01766a806298fb63e8c7..8fa780e8efd002b224d180ab653709dc86d2e80d 100644 (file)
@@ -1939,8 +1939,14 @@ out_err:
                        if (sess->user && sess->user->flags & KSMBD_USER_FLAG_DELAY_SESSION)
                                try_delay = true;
 
-                       sess->last_active = jiffies;
-                       sess->state = SMB2_SESSION_EXPIRED;
+                       /*
+                        * For binding requests, session belongs to another
+                        * connection. Do not expire it.
+                        */
+                       if (!(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
+                               sess->last_active = jiffies;
+                               sess->state = SMB2_SESSION_EXPIRED;
+                       }
                        ksmbd_user_session_put(sess);
                        work->sess = NULL;
                        if (try_delay) {