Skip to content

Commit 0512a5f

Browse files
HexRabbitSteve French
authored andcommitted
ksmbd: fix multiple out-of-bounds read during context decoding
Check the remaining data length before accessing the context structure to ensure that the entire structure is contained within the packet. Additionally, since the context data length `ctxt_len` has already been checked against the total packet length `len_of_ctxts`, update the comparison to use `ctxt_len`. Cc: stable@vger.kernel.org Signed-off-by: Kuan-Ting Chen <h3xrabbit@gmail.com> Acked-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent d738950 commit 0512a5f

File tree

1 file changed

+34
-19
lines changed

1 file changed

+34
-19
lines changed

fs/smb/server/smb2pdu.c

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -845,13 +845,14 @@ static void assemble_neg_contexts(struct ksmbd_conn *conn,
845845

846846
static __le32 decode_preauth_ctxt(struct ksmbd_conn *conn,
847847
struct smb2_preauth_neg_context *pneg_ctxt,
848-
int len_of_ctxts)
848+
int ctxt_len)
849849
{
850850
/*
851851
* sizeof(smb2_preauth_neg_context) assumes SMB311_SALT_SIZE Salt,
852852
* which may not be present. Only check for used HashAlgorithms[1].
853853
*/
854-
if (len_of_ctxts < MIN_PREAUTH_CTXT_DATA_LEN)
854+
if (ctxt_len <
855+
sizeof(struct smb2_neg_context) + MIN_PREAUTH_CTXT_DATA_LEN)
855856
return STATUS_INVALID_PARAMETER;
856857

857858
if (pneg_ctxt->HashAlgorithms != SMB2_PREAUTH_INTEGRITY_SHA512)
@@ -863,15 +864,23 @@ static __le32 decode_preauth_ctxt(struct ksmbd_conn *conn,
863864

864865
static void decode_encrypt_ctxt(struct ksmbd_conn *conn,
865866
struct smb2_encryption_neg_context *pneg_ctxt,
866-
int len_of_ctxts)
867+
int ctxt_len)
867868
{
868-
int cph_cnt = le16_to_cpu(pneg_ctxt->CipherCount);
869-
int i, cphs_size = cph_cnt * sizeof(__le16);
869+
int cph_cnt;
870+
int i, cphs_size;
871+
872+
if (sizeof(struct smb2_encryption_neg_context) > ctxt_len) {
873+
pr_err("Invalid SMB2_ENCRYPTION_CAPABILITIES context size\n");
874+
return;
875+
}
870876

871877
conn->cipher_type = 0;
872878

879+
cph_cnt = le16_to_cpu(pneg_ctxt->CipherCount);
880+
cphs_size = cph_cnt * sizeof(__le16);
881+
873882
if (sizeof(struct smb2_encryption_neg_context) + cphs_size >
874-
len_of_ctxts) {
883+
ctxt_len) {
875884
pr_err("Invalid cipher count(%d)\n", cph_cnt);
876885
return;
877886
}
@@ -919,15 +928,22 @@ static void decode_compress_ctxt(struct ksmbd_conn *conn,
919928

920929
static void decode_sign_cap_ctxt(struct ksmbd_conn *conn,
921930
struct smb2_signing_capabilities *pneg_ctxt,
922-
int len_of_ctxts)
931+
int ctxt_len)
923932
{
924-
int sign_algo_cnt = le16_to_cpu(pneg_ctxt->SigningAlgorithmCount);
925-
int i, sign_alos_size = sign_algo_cnt * sizeof(__le16);
933+
int sign_algo_cnt;
934+
int i, sign_alos_size;
935+
936+
if (sizeof(struct smb2_signing_capabilities) > ctxt_len) {
937+
pr_err("Invalid SMB2_SIGNING_CAPABILITIES context length\n");
938+
return;
939+
}
926940

927941
conn->signing_negotiated = false;
942+
sign_algo_cnt = le16_to_cpu(pneg_ctxt->SigningAlgorithmCount);
943+
sign_alos_size = sign_algo_cnt * sizeof(__le16);
928944

929945
if (sizeof(struct smb2_signing_capabilities) + sign_alos_size >
930-
len_of_ctxts) {
946+
ctxt_len) {
931947
pr_err("Invalid signing algorithm count(%d)\n", sign_algo_cnt);
932948
return;
933949
}
@@ -965,18 +981,16 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
965981
len_of_ctxts = len_of_smb - offset;
966982

967983
while (i++ < neg_ctxt_cnt) {
968-
int clen;
969-
970-
/* check that offset is not beyond end of SMB */
971-
if (len_of_ctxts == 0)
972-
break;
984+
int clen, ctxt_len;
973985

974986
if (len_of_ctxts < sizeof(struct smb2_neg_context))
975987
break;
976988

977989
pctx = (struct smb2_neg_context *)((char *)pctx + offset);
978990
clen = le16_to_cpu(pctx->DataLength);
979-
if (clen + sizeof(struct smb2_neg_context) > len_of_ctxts)
991+
ctxt_len = clen + sizeof(struct smb2_neg_context);
992+
993+
if (ctxt_len > len_of_ctxts)
980994
break;
981995

982996
if (pctx->ContextType == SMB2_PREAUTH_INTEGRITY_CAPABILITIES) {
@@ -987,7 +1001,7 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
9871001

9881002
status = decode_preauth_ctxt(conn,
9891003
(struct smb2_preauth_neg_context *)pctx,
990-
len_of_ctxts);
1004+
ctxt_len);
9911005
if (status != STATUS_SUCCESS)
9921006
break;
9931007
} else if (pctx->ContextType == SMB2_ENCRYPTION_CAPABILITIES) {
@@ -998,7 +1012,7 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
9981012

9991013
decode_encrypt_ctxt(conn,
10001014
(struct smb2_encryption_neg_context *)pctx,
1001-
len_of_ctxts);
1015+
ctxt_len);
10021016
} else if (pctx->ContextType == SMB2_COMPRESSION_CAPABILITIES) {
10031017
ksmbd_debug(SMB,
10041018
"deassemble SMB2_COMPRESSION_CAPABILITIES context\n");
@@ -1017,9 +1031,10 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
10171031
} else if (pctx->ContextType == SMB2_SIGNING_CAPABILITIES) {
10181032
ksmbd_debug(SMB,
10191033
"deassemble SMB2_SIGNING_CAPABILITIES context\n");
1034+
10201035
decode_sign_cap_ctxt(conn,
10211036
(struct smb2_signing_capabilities *)pctx,
1022-
len_of_ctxts);
1037+
ctxt_len);
10231038
}
10241039

10251040
/* offsets must be 8 byte aligned */

0 commit comments

Comments
 (0)