ksmbd: fix UBSAN array-index-out-of-bounds in decode_compress_ctxt()

decode_compress_ctxt() walks CompressionAlgorithms[] using the client
supplied CompressionAlgorithmCount. That field is declared in
struct smb2_compression_capabilities_context as a fixed 4-element array,
but the number of algorithms is actually variable and clients such as
Windows advertise more than four (e.g. LZ77, LZ77+Huffman, LZNT1,
Pattern_V1 and LZ4).

The on-wire context length is already validated, so the access is within
the received buffer, but indexing the statically sized [4] array makes
UBSAN report an out-of-bounds access:

  UBSAN: array-index-out-of-bounds in smb2pdu.c:1122:48
  index 4 is out of range for type '__le16 [4]'
  Call Trace:
   smb2_handle_negotiate+0xda7/0xde0 [ksmbd]
   ksmbd_smb_negotiate_common+0x27b/0x3e0 [ksmbd]
   smb2_negotiate_request+0x14/0x20 [ksmbd]
   handle_ksmbd_work+0x181/0x500 [ksmbd]

Walk the algorithms through a pointer so the fixed-array bounds check is
not applied, while keeping the existing length validation that bounds the
loop to the data actually received.

Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
Namjae Jeon 2026-06-21 21:21:01 +09:00 committed by Steve French
parent 5a7f4d6d8e
commit 474fd91f38

View File

@ -1094,6 +1094,7 @@ static __le32 decode_compress_ctxt(struct ksmbd_conn *conn,
int ctxt_len)
{
int alg_cnt, algs_size, i;
__le16 *algs;
if (sizeof(struct smb2_neg_context) + 10 > ctxt_len) {
pr_err("Invalid SMB2_COMPRESSION_CAPABILITIES context length\n");
@ -1118,8 +1119,15 @@ static __le32 decode_compress_ctxt(struct ksmbd_conn *conn,
return STATUS_INVALID_PARAMETER;
}
/*
* CompressionAlgorithms[] is declared as a fixed 4-element array, but
* the actual element count is variable (clients such as Windows may
* advertise more). The on-wire length was validated above, so walk the
* algorithms through a pointer to avoid a fixed-array bounds check.
*/
algs = pneg_ctxt->CompressionAlgorithms;
for (i = 0; i < alg_cnt; i++) {
__le16 alg = pneg_ctxt->CompressionAlgorithms[i];
__le16 alg = algs[i];
/*
* LZ77 is the required general-purpose codec. Pattern_V1 is an