|
In SMB 3.1.1, clients such as Windows 11 send chained compressed
write requests containing multiple payload segments (for example,
None + Pattern_V1) when transferring zero-heavy or compressible
files.
According to MS-SMB2 section 2.2.42.2.1, the first payload header in
a chained compression transform MUST have SMB2_COMPRESSION_FLAG_CHAINED
(0x0001) set. Trailing payload headers in the chain correspond to
subsequent payloads, where the specification defines
SMB2_COMPRESSION_FLAG_NONE (0x0000).
However, Windows clients do not always explicitly zero the 16-bit
Flags field on subsequent payload headers during chunk construction
(as described in MS-SMB2 section 3.1.4.4 step 2), leaving residual
bits in the Flags field.
smb_decompress_chained() currently enforces:
(!first && flags != cpu_to_le16(SMB2_COMPRESSION_FLAG_NONE))
returning -EINVAL if any trailing payload has non-zero flags. When
this occurs during large file writes (such as copying VHDX files),
ksmbd breaks the connection receive loop and abruptly terminates
the TCP connection with ECONNRESET (-104), causing Windows clients to
fail with error 0x8007003B (ERROR_UNEXP_NET_ERR).
Fix this by relaxing the flags requirement on trailing payloads in
smb_decompress_chained(). Conforming chains still strictly require
SMB2_COMPRESSION_FLAG_CHAINED on the first payload header, but for
subsequent payloads, only reject headers that attempt to initiate an
invalid nested chain (SMB2_COMPRESSION_FLAG_CHAINED). All payload
lengths, decompression algorithms, and total uncompressed output sizes
continue to be strictly validated against the transform's
OriginalCompressedSegmentSize.
Assisted-by: OpenCode:gpt-6-astra
Signed-off-by: Omkar Chandorkar <gotenksIN@aospa.co>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
|