Skip to content

Commit 0d994cd

Browse files
Marios Makassikissmfrench
authored andcommitted
ksmbd: add buffer validation in session setup
Make sure the security buffer's length/offset are valid with regards to the packet length. Acked-by: Namjae Jeon <[email protected]> Signed-off-by: Marios Makassikis <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 621be84 commit 0d994cd

File tree

2 files changed

+40
-27
lines changed

2 files changed

+40
-27
lines changed

fs/ksmbd/auth.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -298,8 +298,8 @@ int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob,
298298
int blob_len, struct ksmbd_session *sess)
299299
{
300300
char *domain_name;
301-
unsigned int lm_off, nt_off;
302-
unsigned short nt_len;
301+
unsigned int nt_off, dn_off;
302+
unsigned short nt_len, dn_len;
303303
int ret;
304304

305305
if (blob_len < sizeof(struct authenticate_message)) {
@@ -314,15 +314,17 @@ int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob,
314314
return -EINVAL;
315315
}
316316

317-
lm_off = le32_to_cpu(authblob->LmChallengeResponse.BufferOffset);
318317
nt_off = le32_to_cpu(authblob->NtChallengeResponse.BufferOffset);
319318
nt_len = le16_to_cpu(authblob->NtChallengeResponse.Length);
319+
dn_off = le32_to_cpu(authblob->DomainName.BufferOffset);
320+
dn_len = le16_to_cpu(authblob->DomainName.Length);
321+
322+
if (blob_len < (u64)dn_off + dn_len || blob_len < (u64)nt_off + nt_len)
323+
return -EINVAL;
320324

321325
/* TODO : use domain name that imported from configuration file */
322-
domain_name = smb_strndup_from_utf16((const char *)authblob +
323-
le32_to_cpu(authblob->DomainName.BufferOffset),
324-
le16_to_cpu(authblob->DomainName.Length), true,
325-
sess->conn->local_nls);
326+
domain_name = smb_strndup_from_utf16((const char *)authblob + dn_off,
327+
dn_len, true, sess->conn->local_nls);
326328
if (IS_ERR(domain_name))
327329
return PTR_ERR(domain_name);
328330

fs/ksmbd/smb2pdu.c

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,19 +1257,13 @@ static int generate_preauth_hash(struct ksmbd_work *work)
12571257
return 0;
12581258
}
12591259

1260-
static int decode_negotiation_token(struct ksmbd_work *work,
1261-
struct negotiate_message *negblob)
1260+
static int decode_negotiation_token(struct ksmbd_conn *conn,
1261+
struct negotiate_message *negblob,
1262+
size_t sz)
12621263
{
1263-
struct ksmbd_conn *conn = work->conn;
1264-
struct smb2_sess_setup_req *req;
1265-
int sz;
1266-
12671264
if (!conn->use_spnego)
12681265
return -EINVAL;
12691266

1270-
req = work->request_buf;
1271-
sz = le16_to_cpu(req->SecurityBufferLength);
1272-
12731267
if (ksmbd_decode_negTokenInit((char *)negblob, sz, conn)) {
12741268
if (ksmbd_decode_negTokenTarg((char *)negblob, sz, conn)) {
12751269
conn->auth_mechs |= KSMBD_AUTH_NTLMSSP;
@@ -1281,9 +1275,9 @@ static int decode_negotiation_token(struct ksmbd_work *work,
12811275
}
12821276

12831277
static int ntlm_negotiate(struct ksmbd_work *work,
1284-
struct negotiate_message *negblob)
1278+
struct negotiate_message *negblob,
1279+
size_t negblob_len)
12851280
{
1286-
struct smb2_sess_setup_req *req = work->request_buf;
12871281
struct smb2_sess_setup_rsp *rsp = work->response_buf;
12881282
struct challenge_message *chgblob;
12891283
unsigned char *spnego_blob = NULL;
@@ -1292,8 +1286,7 @@ static int ntlm_negotiate(struct ksmbd_work *work,
12921286
int sz, rc;
12931287

12941288
ksmbd_debug(SMB, "negotiate phase\n");
1295-
sz = le16_to_cpu(req->SecurityBufferLength);
1296-
rc = ksmbd_decode_ntlmssp_neg_blob(negblob, sz, work->sess);
1289+
rc = ksmbd_decode_ntlmssp_neg_blob(negblob, negblob_len, work->sess);
12971290
if (rc)
12981291
return rc;
12991292

@@ -1361,12 +1354,23 @@ static struct ksmbd_user *session_user(struct ksmbd_conn *conn,
13611354
struct authenticate_message *authblob;
13621355
struct ksmbd_user *user;
13631356
char *name;
1364-
int sz;
1357+
unsigned int auth_msg_len, name_off, name_len, secbuf_len;
13651358

1359+
secbuf_len = le16_to_cpu(req->SecurityBufferLength);
1360+
if (secbuf_len < sizeof(struct authenticate_message)) {
1361+
ksmbd_debug(SMB, "blob len %d too small\n", secbuf_len);
1362+
return NULL;
1363+
}
13661364
authblob = user_authblob(conn, req);
1367-
sz = le32_to_cpu(authblob->UserName.BufferOffset);
1368-
name = smb_strndup_from_utf16((const char *)authblob + sz,
1369-
le16_to_cpu(authblob->UserName.Length),
1365+
name_off = le32_to_cpu(authblob->UserName.BufferOffset);
1366+
name_len = le16_to_cpu(authblob->UserName.Length);
1367+
auth_msg_len = le16_to_cpu(req->SecurityBufferOffset) + secbuf_len;
1368+
1369+
if (auth_msg_len < (u64)name_off + name_len)
1370+
return NULL;
1371+
1372+
name = smb_strndup_from_utf16((const char *)authblob + name_off,
1373+
name_len,
13701374
true,
13711375
conn->local_nls);
13721376
if (IS_ERR(name)) {
@@ -1612,6 +1616,7 @@ int smb2_sess_setup(struct ksmbd_work *work)
16121616
struct smb2_sess_setup_rsp *rsp = work->response_buf;
16131617
struct ksmbd_session *sess;
16141618
struct negotiate_message *negblob;
1619+
unsigned int negblob_len, negblob_off;
16151620
int rc = 0;
16161621

16171622
ksmbd_debug(SMB, "Received request for session setup\n");
@@ -1692,10 +1697,16 @@ int smb2_sess_setup(struct ksmbd_work *work)
16921697
if (sess->state == SMB2_SESSION_EXPIRED)
16931698
sess->state = SMB2_SESSION_IN_PROGRESS;
16941699

1700+
negblob_off = le16_to_cpu(req->SecurityBufferOffset);
1701+
negblob_len = le16_to_cpu(req->SecurityBufferLength);
1702+
if (negblob_off < (offsetof(struct smb2_sess_setup_req, Buffer) - 4) ||
1703+
negblob_len < offsetof(struct negotiate_message, NegotiateFlags))
1704+
return -EINVAL;
1705+
16951706
negblob = (struct negotiate_message *)((char *)&req->hdr.ProtocolId +
1696-
le16_to_cpu(req->SecurityBufferOffset));
1707+
negblob_off);
16971708

1698-
if (decode_negotiation_token(work, negblob) == 0) {
1709+
if (decode_negotiation_token(conn, negblob, negblob_len) == 0) {
16991710
if (conn->mechToken)
17001711
negblob = (struct negotiate_message *)conn->mechToken;
17011712
}
@@ -1719,7 +1730,7 @@ int smb2_sess_setup(struct ksmbd_work *work)
17191730
sess->Preauth_HashValue = NULL;
17201731
} else if (conn->preferred_auth_mech == KSMBD_AUTH_NTLMSSP) {
17211732
if (negblob->MessageType == NtLmNegotiate) {
1722-
rc = ntlm_negotiate(work, negblob);
1733+
rc = ntlm_negotiate(work, negblob, negblob_len);
17231734
if (rc)
17241735
goto out_err;
17251736
rsp->hdr.Status =

0 commit comments

Comments
 (0)