[PATCH 2/2] ksmbd: validate compression Flags before kvmalloc
Anatolii Shumak <[email protected]> Sat, 1 Aug 2026 08:19:53 +0300
| Newsgroups | org.kernel.vger.linux-cifs |
|---|---|
| Message-ID | <[email protected]> |
ksmbd_decompress_request() allocated the decompressed request buffer before smb_compression_decompress() rejected unknown transform Flags or chained mode when it was not negotiated. A remote peer could force a transient multi-megabyte allocation that was immediately freed on -EINVAL. Validate CHAINED/NONE Flags and compress_chained before kvmalloc. Link: https://github.com/namjaejeon/ksmbd/issues/529 Signed-off-by: Anatolii Shumak <[email protected]> --- fs/smb/server/compress.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/fs/smb/server/compress.c b/fs/smb/server/compress.c index 821299888ad3..7e13cae705e2 100644 --- a/fs/smb/server/compress.c +++ b/fs/smb/server/compress.c @@ -46,13 +46,22 @@ int ksmbd_decompress_request(struct ksmbd_conn *conn) return -EINVAL; orig_size = le32_to_cpu(hdr->OriginalCompressedSegmentSize); + /* + * For chained transforms the top-level header is only eight bytes; the + * Flags field overlays the first payload header. Reject unknown Flags + * and unnegotiated chained mode before allocating the output buffer. + */ if (hdr->Flags == cpu_to_le16(SMB2_COMPRESSION_FLAG_CHAINED)) { + if (!conn->compress_chained) + return -EINVAL; out_size = orig_size; - } else { + } else if (hdr->Flags == cpu_to_le16(SMB2_COMPRESSION_FLAG_NONE)) { offset = le32_to_cpu(hdr->Offset); if (offset > pdu_size - sizeof(*hdr) || check_add_overflow(orig_size, offset, &out_size)) return -EINVAL; + } else { + return -EINVAL; } max_allowed_pdu_size = SMB3_MAX_MSGSIZE + conn->vals->max_write_size; -- 2.51.0.windows.2