FAILED: patch "[PATCH] smb: client: validate the data area in SMB2_read()" failed to apply to 5.15-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.15.y
git checkout FETCH_HEAD
git cherry-pick -x 2ec9cdf469dd32bcf33073aeb30c08e9356e0ca1
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026110422-kitty-unlocking-dd52@gregkh' --subject-prefix 'PATCH 5.15.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 2ec9cdf469dd32bcf33073aeb30c08e9356e0ca1 Mon Sep 17 00:00:00 2001
From: Abdifatah Suruur <[email protected]>
Date: Thu, 22 Oct 2026 06:53:29 +0300
Subject: [PATCH] smb: client: validate the data area in SMB2_read()
SMB2_read() copies le32_to_cpu(rsp->DataLength) bytes from (char *)rsp + rsp->DataOffset without checking that the range lies within the response actually received. A READ response with DataOffset == 0 makes smb2_get_data_area_len() zero the data length, so smb2_check_message() accepts a frame as short as the fixed response, while SMB2_read() still uses the server-supplied DataLength, capped only by CIFS_MAX_MSGSIZE and the caller's length.
A malicious server can answer the synchronous read used by the mfsymlinks (or SFU) symlink parser with an 81-byte READ response carrying DataOffset 0 and DataLength 1067, making the client copy 1067 bytes from a 448-byte receive object (KASAN slab-out-of-bounds; up to 16 KiB in the general case).
Clamp a zero (or header-overlapping) DataOffset to read_rsp_size, as handle_read_data() does for the asynchronous path, and reject the response unless DataOffset + DataLength fits within rsp_iov.iov_len. The SMB1 helper was fixed the same way in 5be5bdda5863.
fs/smb/client/smb2pdu.c +23 -1
@@ -4948,6 +4948,7 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,struct kvec iov[1 ];struct kvec rsp_iov;unsigned int total_len; +u16 data_offset;int flags =CIFS_LOG_ERROR ;struct cifs_ses *ses = io_parms->tcon->ses;
@@ -5007,8 +5008,29 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, *nbytes =0 ; } + data_offset = rsp->DataOffset; +if (data_offset < io_parms->server->vals->read_rsp_size) { +/* +* win2k8 sometimes sends an offset of 0 when the read is beyond +* the EOF. Treat it as if the data starts just after the header, +* as handle_read_data() does. +*/ +cifs_dbg (FYI ,"data offset %u inside read response header\n" , + data_offset); + data_offset = io_parms->server->vals->read_rsp_size; + } + +/* The data area must lie within the response actually received */ +if (*nbytes && (size_t )data_offset + *nbytes > rsp_iov.iov_len) { +cifs_dbg (FYI ,"bad data offset %u length %u for response of %zu\n" , + data_offset, *nbytes, rsp_iov.iov_len); + rc =smb_EIO2 (smb_eio_trace_read_bad_offset, + data_offset, *nbytes); + *nbytes =0 ; + } +if (*buf) { -memcpy (*buf, (char *)rsp + rsp->DataOffset, *nbytes); +memcpy (*buf, (char *)rsp + data_offset, *nbytes);free_rsp_buf (resp_buftype, rsp_iov.iov_base); }else if (resp_buftype !=CIFS_NO_BUFFER ) { *buf = rsp_iov.iov_base;
Sasha Levin
maintainerPATCH 1/1 smb: client: validate the data area in SMB2_read()
From: Abdifatah Suruur <[email protected]>
[ Upstream commit 2ec9cdf469dd32bcf33073aeb30c08e9356e0ca1 ]
SMB2_read() copies le32_to_cpu(rsp->DataLength) bytes from (char *)rsp + rsp->DataOffset without checking that the range lies within the response actually received. A READ response with DataOffset == 0 makes smb2_get_data_area_len() zero the data length, so smb2_check_message() accepts a frame as short as the fixed response, while SMB2_read() still uses the server-supplied DataLength, capped only by CIFS_MAX_MSGSIZE and the caller's length.
A malicious server can answer the synchronous read used by the mfsymlinks (or SFU) symlink parser with an 81-byte READ response carrying DataOffset 0 and DataLength 1067, making the client copy 1067 bytes from a 448-byte receive object (KASAN slab-out-of-bounds; up to 16 KiB in the general case).
Clamp a zero (or header-overlapping) DataOffset to read_rsp_size, as handle_read_data() does for the asynchronous path, and reject the response unless DataOffset + DataLength fits within rsp_iov.iov_len. The SMB1 helper was fixed the same way in 5be5bdda5863.
--- fs/cifs/smb2pdu.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-)
fs/cifs/smb2pdu.c +22 -1
@@ -4236,6 +4236,7 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,struct kvec iov[1 ];struct kvec rsp_iov;unsigned int total_len; +u16 data_offset;int flags =CIFS_LOG_ERROR ;struct cifs_ses *ses = io_parms->tcon->ses;
@@ -4292,8 +4293,28 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, *nbytes =0 ; } + data_offset = rsp->DataOffset; +if (data_offset < io_parms->server->vals->read_rsp_size) { +/* +* win2k8 sometimes sends an offset of 0 when the read is beyond +* the EOF. Treat it as if the data starts just after the header, +* as handle_read_data() does. +*/ +cifs_dbg (FYI ,"data offset %u inside read response header\n" , + data_offset); + data_offset = io_parms->server->vals->read_rsp_size; + } + +/* The data area must lie within the response actually received */ +if (*nbytes && (size_t )data_offset + *nbytes > rsp_iov.iov_len) { +cifs_dbg (FYI ,"bad data offset %u length %u for response of %zu\n" , + data_offset, *nbytes, rsp_iov.iov_len); + rc = -EIO ; + *nbytes =0 ; + } +if (*buf) { -memcpy (*buf, (char *)rsp + rsp->DataOffset, *nbytes); +memcpy (*buf, (char *)rsp + data_offset, *nbytes);free_rsp_buf (resp_buftype, rsp_iov.iov_base); }else if (resp_buftype !=CIFS_NO_BUFFER ) { *buf = rsp_iov.iov_base;
Signature · 1 line
2.53.0