Skip to content

Commit 6103461

Browse files
dhkts1smfrench
authored andcommitted
ksmbd: fix stack buffer overflow in multichannel session-key copy
Commit 4b70636 ("ksmbd: fix multichannel binding and enforce channel limit") moved the binding-path session key out of the session-wide sess->sess_key (CIFS_KEY_SIZE = 40) into a new per-channel buffer, and sized both that buffer and the on-stack copy used during binding with SMB2_NTLMV2_SESSKEY_SIZE (16): struct channel { char sess_key[SMB2_NTLMV2_SESSKEY_SIZE]; /* 16 */ ... }; ntlm_authenticate() / krb5_authenticate(): char channel_key[SMB2_NTLMV2_SESSKEY_SIZE] = {}; /* 16 */ char *auth_key = conn->binding ? channel_key : sess->sess_key; The two writers that fill this destination still bound the copy length against CIFS_KEY_SIZE (40), not against the 16-byte buffer: ksmbd_decode_ntlmssp_auth_blob() (NTLM key exchange): if (sess_key_len > CIFS_KEY_SIZE) /* 40 */ return -EINVAL; arc4_crypt(ctx_arc4, sess_key, (char *)authblob + sess_key_off, sess_key_len); ksmbd_krb5_authenticate(): if (resp->session_key_len > sizeof(sess->sess_key)) /* 40 */ ... memcpy(sess_key, resp->payload, resp->session_key_len); On a binding SESSION_SETUP, auth_key points at the 16-byte channel_key, so a client that supplies an NTLM EncryptedRandomSessionKey of up to 40 bytes (with NTLMSSP_NEGOTIATE_KEY_EXCH), or a Kerberos ticket whose session key is longer than 16 bytes (a normal AES256 key is 32), writes past the 16-byte stack buffer -- up to a 24-byte kernel stack overflow. KASAN reports it as a stack-out-of-bounds write in arc4_crypt() called from ksmbd_decode_ntlmssp_auth_blob(). The destinations must be able to hold the full session key the length checks already permit. Size the per-channel key buffer and the two on-stack channel_key buffers with CIFS_KEY_SIZE, matching sess->sess_key. Fixes: 4b70636 ("ksmbd: fix multichannel binding and enforce channel limit") Signed-off-by: Gil Portnoy <dddhkts1@gmail.com> Acked-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent 08b9452 commit 6103461

2 files changed

Lines changed: 3 additions & 3 deletions

File tree

fs/smb/server/mgmt/user_session.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
struct ksmbd_file_table;
2020

2121
struct channel {
22-
char sess_key[SMB2_NTLMV2_SESSKEY_SIZE];
22+
char sess_key[CIFS_KEY_SIZE];
2323
__u8 smb3signingkey[SMB3_SIGN_KEY_SIZE];
2424
struct ksmbd_conn *conn;
2525
};

fs/smb/server/smb2pdu.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1689,7 +1689,7 @@ static int ntlm_authenticate(struct ksmbd_work *work,
16891689
struct ksmbd_conn *conn = work->conn;
16901690
struct ksmbd_session *sess = work->sess;
16911691
struct ksmbd_user *user;
1692-
char channel_key[SMB2_NTLMV2_SESSKEY_SIZE] = {};
1692+
char channel_key[CIFS_KEY_SIZE] = {};
16931693
char *auth_key = conn->binding ? channel_key : sess->sess_key;
16941694
u64 prev_id;
16951695
bool binding = conn->binding;
@@ -1826,7 +1826,7 @@ static int krb5_authenticate(struct ksmbd_work *work,
18261826
struct ksmbd_conn *conn = work->conn;
18271827
struct ksmbd_session *sess = work->sess;
18281828
char *in_blob, *out_blob;
1829-
char channel_key[SMB2_NTLMV2_SESSKEY_SIZE] = {};
1829+
char channel_key[CIFS_KEY_SIZE] = {};
18301830
char *auth_key = conn->binding ? channel_key : sess->sess_key;
18311831
u64 prev_sess_id;
18321832
bool binding = conn->binding;

0 commit comments

Comments
 (0)