]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ksmbd: use the session dialect for rejected binding signatures
authorNamjae Jeon <linkinjeon@kernel.org>
Thu, 2 Jul 2026 12:16:50 +0000 (21:16 +0900)
committerSteve French <stfrench@microsoft.com>
Mon, 6 Jul 2026 12:55:41 +0000 (07:55 -0500)
When an SMB3 session is referenced by a binding request on an SMB2.1
connection, the request is signed with the existing session's SMB3 signing
algorithm. ksmbd instead verifies it with the new connection's SMB2.1 HMAC
algorithm, so verification fails and the client receives
STATUS_ACCESS_DENIED instead of STATUS_REQUEST_NOT_ACCEPTED.

Select the signing verifier from the referenced session dialect. Permit a
signed SESSION_SETUP without an established channel to use the SMB3 session
signing key for verification. This is limited to SESSION_SETUP so other
unbound requests remain rejected.

The rejected response must use the same existing session algorithm. When an
SMB3 session is referenced on an SMB2.1 connection, sign the SESSION_SETUP
response with the SMB3 signing path rather than the connection's SMB2.1
path.

This fixes smb2.session.bind_negative_smb3to2s.

Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/server/server.c
fs/smb/server/smb2pdu.c

index bc861ca4f0ccdf4fc7b142ba8029d0232c5eb159..f5baba9348405823cafa48fd8f430c15108cdb9e 100644 (file)
@@ -243,8 +243,14 @@ static void __handle_ksmbd_work(struct ksmbd_work *work,
 
                if (work->sess &&
                    (work->sess->sign || smb3_11_final_sess_setup_resp(work) ||
-                    conn->ops->is_sign_req(work, command)))
-                       conn->ops->set_sign_rsp(work);
+                    conn->ops->is_sign_req(work, command))) {
+                       if (command == SMB2_SESSION_SETUP_HE &&
+                           work->sess->dialect >= SMB30_PROT_ID &&
+                           conn->dialect < SMB30_PROT_ID)
+                               smb3_set_sign_rsp(work);
+                       else
+                               conn->ops->set_sign_rsp(work);
+               }
        } while (is_chained == true);
 
 send:
index 123ba63b24101f260a1d5a71836e53fc932a5822..b73167785e87557d8944da69d4abd2136fb5388f 100644 (file)
@@ -2015,10 +2015,16 @@ int smb2_sess_setup(struct ksmbd_work *work)
                   (req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
                sess = ksmbd_session_lookup_slowpath(le64_to_cpu(req->hdr.SessionId));
                if (sess) {
+                       int sign_ret;
+
                        work->sess = sess;
+                       if (sess->dialect >= SMB30_PROT_ID)
+                               sign_ret = smb3_check_sign_req(work);
+                       else
+                               sign_ret = smb2_check_sign_req(work);
                        if (sess->state != SMB2_SESSION_VALID ||
                            !(req->hdr.Flags & SMB2_FLAGS_SIGNED) ||
-                           !conn->ops->check_sign_req(work)) {
+                           !sign_ret) {
                                ksmbd_user_session_put(sess);
                                work->sess = NULL;
                                sess = NULL;
@@ -9681,9 +9687,13 @@ int smb3_check_sign_req(struct ksmbd_work *work)
        } else {
                chann = lookup_chann_list(work->sess, conn);
                if (!chann) {
-                       return 0;
+                       if (le16_to_cpu(hdr->Command) != SMB2_SESSION_SETUP_HE ||
+                           !(hdr->Flags & SMB2_FLAGS_SIGNED))
+                               return 0;
+                       signing_key = work->sess->smb3signingkey;
+               } else {
+                       signing_key = chann->smb3signingkey;
                }
-               signing_key = chann->smb3signingkey;
        }
 
        if (!signing_key) {