[PATCH] ksmbd: fix multiple out-of-bounds read during context decoding

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Kuan-Ting Chen <h3xrabbit@xxxxxxxxx>

Ensure the context's length is valid (excluding VLAs) before casting the
pointer to the corresponding structure pointer type, also removed
redundant check on `len_of_ctxts`.

Signed-off-by: Kuan-Ting Chen <h3xrabbit@xxxxxxxxx>
---
 fs/ksmbd/smb2pdu.c | 23 +++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 972176bff..83b877254 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -969,18 +969,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) {
@@ -989,6 +987,9 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
 			if (conn->preauth_info->Preauth_HashId)
 				break;
 
+			if (ctxt_len < sizeof(struct smb2_preauth_neg_context))
+				break;
+
 			status = decode_preauth_ctxt(conn,
 						     (struct smb2_preauth_neg_context *)pctx,
 						     len_of_ctxts);
@@ -1000,6 +1001,9 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
 			if (conn->cipher_type)
 				break;
 
+			if (ctxt_len < sizeof(struct smb2_encryption_neg_context))
+				break;
+
 			decode_encrypt_ctxt(conn,
 					    (struct smb2_encryption_neg_context *)pctx,
 					    len_of_ctxts);
@@ -1009,6 +1013,9 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
 			if (conn->compress_algorithm)
 				break;
 
+			if (ctxt_len < sizeof(struct smb2_compression_capabilities_context))
+				break;
+
 			decode_compress_ctxt(conn,
 					     (struct smb2_compression_capabilities_context *)pctx);
 		} else if (pctx->ContextType == SMB2_NETNAME_NEGOTIATE_CONTEXT_ID) {
@@ -1021,6 +1028,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");
+
+			if (ctxt_len < sizeof(struct smb2_signing_capabilities))
+				break;
+
 			decode_sign_cap_ctxt(conn,
 					     (struct smb2_signing_capabilities *)pctx,
 					     len_of_ctxts);
-- 
2.25.1




[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux