Skip to content

Commit

Permalink
ksmbd: fix multiple out-of-bounds read during context decoding
Browse files Browse the repository at this point in the history
commit 0512a5f upstream.

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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
HexRabbit authored and gregkh committed Jun 9, 2023
1 parent 522a941 commit 4f303c0
Showing 1 changed file with 34 additions and 19 deletions.
53 changes: 34 additions & 19 deletions fs/ksmbd/smb2pdu.c
Original file line number Diff line number Diff line change
Expand Up @@ -861,13 +861,14 @@ static void assemble_neg_contexts(struct ksmbd_conn *conn,

static __le32 decode_preauth_ctxt(struct ksmbd_conn *conn,
struct smb2_preauth_neg_context *pneg_ctxt,
int len_of_ctxts)
int ctxt_len)
{
/*
* sizeof(smb2_preauth_neg_context) assumes SMB311_SALT_SIZE Salt,
* which may not be present. Only check for used HashAlgorithms[1].
*/
if (len_of_ctxts < MIN_PREAUTH_CTXT_DATA_LEN)
if (ctxt_len <
sizeof(struct smb2_neg_context) + MIN_PREAUTH_CTXT_DATA_LEN)
return STATUS_INVALID_PARAMETER;

if (pneg_ctxt->HashAlgorithms != SMB2_PREAUTH_INTEGRITY_SHA512)
Expand All @@ -879,15 +880,23 @@ static __le32 decode_preauth_ctxt(struct ksmbd_conn *conn,

static void decode_encrypt_ctxt(struct ksmbd_conn *conn,
struct smb2_encryption_neg_context *pneg_ctxt,
int len_of_ctxts)
int ctxt_len)
{
int cph_cnt = le16_to_cpu(pneg_ctxt->CipherCount);
int i, cphs_size = cph_cnt * sizeof(__le16);
int cph_cnt;
int i, cphs_size;

if (sizeof(struct smb2_encryption_neg_context) > ctxt_len) {
pr_err("Invalid SMB2_ENCRYPTION_CAPABILITIES context size\n");
return;
}

conn->cipher_type = 0;

cph_cnt = le16_to_cpu(pneg_ctxt->CipherCount);
cphs_size = cph_cnt * sizeof(__le16);

if (sizeof(struct smb2_encryption_neg_context) + cphs_size >
len_of_ctxts) {
ctxt_len) {
pr_err("Invalid cipher count(%d)\n", cph_cnt);
return;
}
Expand Down Expand Up @@ -935,15 +944,22 @@ static void decode_compress_ctxt(struct ksmbd_conn *conn,

static void decode_sign_cap_ctxt(struct ksmbd_conn *conn,
struct smb2_signing_capabilities *pneg_ctxt,
int len_of_ctxts)
int ctxt_len)
{
int sign_algo_cnt = le16_to_cpu(pneg_ctxt->SigningAlgorithmCount);
int i, sign_alos_size = sign_algo_cnt * sizeof(__le16);
int sign_algo_cnt;
int i, sign_alos_size;

if (sizeof(struct smb2_signing_capabilities) > ctxt_len) {
pr_err("Invalid SMB2_SIGNING_CAPABILITIES context length\n");
return;
}

conn->signing_negotiated = false;
sign_algo_cnt = le16_to_cpu(pneg_ctxt->SigningAlgorithmCount);
sign_alos_size = sign_algo_cnt * sizeof(__le16);

if (sizeof(struct smb2_signing_capabilities) + sign_alos_size >
len_of_ctxts) {
ctxt_len) {
pr_err("Invalid signing algorithm count(%d)\n", sign_algo_cnt);
return;
}
Expand Down Expand Up @@ -981,18 +997,16 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
len_of_ctxts = len_of_smb - offset;

while (i++ < neg_ctxt_cnt) {
int clen;

/* check that offset is not beyond end of SMB */
if (len_of_ctxts == 0)
break;
int clen, ctxt_len;

if (len_of_ctxts < sizeof(struct smb2_neg_context))
break;

pctx = (struct smb2_neg_context *)((char *)pctx + offset);
clen = le16_to_cpu(pctx->DataLength);
if (clen + sizeof(struct smb2_neg_context) > len_of_ctxts)
ctxt_len = clen + sizeof(struct smb2_neg_context);

if (ctxt_len > len_of_ctxts)
break;

if (pctx->ContextType == SMB2_PREAUTH_INTEGRITY_CAPABILITIES) {
Expand All @@ -1003,7 +1017,7 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,

status = decode_preauth_ctxt(conn,
(struct smb2_preauth_neg_context *)pctx,
len_of_ctxts);
ctxt_len);
if (status != STATUS_SUCCESS)
break;
} else if (pctx->ContextType == SMB2_ENCRYPTION_CAPABILITIES) {
Expand All @@ -1014,7 +1028,7 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,

decode_encrypt_ctxt(conn,
(struct smb2_encryption_neg_context *)pctx,
len_of_ctxts);
ctxt_len);
} else if (pctx->ContextType == SMB2_COMPRESSION_CAPABILITIES) {
ksmbd_debug(SMB,
"deassemble SMB2_COMPRESSION_CAPABILITIES context\n");
Expand All @@ -1033,9 +1047,10 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
} else if (pctx->ContextType == SMB2_SIGNING_CAPABILITIES) {
ksmbd_debug(SMB,
"deassemble SMB2_SIGNING_CAPABILITIES context\n");

decode_sign_cap_ctxt(conn,
(struct smb2_signing_capabilities *)pctx,
len_of_ctxts);
ctxt_len);
}

/* offsets must be 8 byte aligned */
Expand Down

0 comments on commit 4f303c0

Please sign in to comment.