From: Dudu Lu Date: Wed, 15 Apr 2026 10:24:24 +0000 (+0800) Subject: smb: client: fix integer underflow in receive_encrypted_read() X-Git-Url: http://git.ipfire.org/index.cgi?a=commitdiff_plain;h=6b83b03c07fbe0b57bb729bee91ae44c623c82ff;p=thirdparty%2Fkernel%2Flinux.git smb: client: fix integer underflow in receive_encrypted_read() In receive_encrypted_read(), the length of data to read from the socket is computed as: len = le32_to_cpu(tr_hdr->OriginalMessageSize) - server->vals->read_rsp_size; OriginalMessageSize comes from the server's transform header and is untrusted. If a malicious server sends a value smaller than read_rsp_size, the unsigned subtraction wraps to a very large value (~4GB). This value is then passed to netfs_alloc_folioq_buffer() and cifs_read_iter_from_socket(), causing either a massive allocation attempt that fails with -ENOMEM (DoS), or under extreme memory pressure, potential heap corruption. Fix by adding a check that OriginalMessageSize is at least read_rsp_size before the subtraction. On failure, jump to discard_data to drain the remaining PDU from the socket, preventing desync of subsequent reads on the connection. Signed-off-by: Dudu Lu Reviewed-by: Enzo Matsumiya Signed-off-by: Steve French --- diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index 509fcea28a429..a2105f4b54db7 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -4943,6 +4943,14 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid, goto free_dw; server->total_read += rc; + if (le32_to_cpu(tr_hdr->OriginalMessageSize) < + server->vals->read_rsp_size) { + cifs_server_dbg(VFS, "OriginalMessageSize %u too small for read response (%zu)\n", + le32_to_cpu(tr_hdr->OriginalMessageSize), + server->vals->read_rsp_size); + rc = -EINVAL; + goto discard_data; + } len = le32_to_cpu(tr_hdr->OriginalMessageSize) - server->vals->read_rsp_size; dw->len = len;