FAILED: patch "[PATCH] smb: client: reject a tree connect response whose byte count" failed to apply to 5.15-stable tree
Subsystems (4)
[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 65deb18359341141d37dc86fc7853511be3c87a7
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026090337-dismiss-carload-0d51@gregkh' --subject-prefix 'PATCH 5.15.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 65deb18359341141d37dc86fc7853511be3c87a7 Mon Sep 17 00:00:00 2001
From: Bryam Vargas <[email protected]>
Date: Fri, 21 Aug 2026 07:36:16 -0500
Subject: [PATCH] smb: client: reject a tree connect response whose byte count
is too small
CIFSTCon() bounds its strnlen() over the byte area with the server's ByteCount minus two, which for ByteCount 0 or 1 goes negative as an int and converts to a huge size_t. The later subtraction wraps the __u16 bytes_left, and that is what bounds cifs_strndup_from_utf16(): a bound of up to 65535 against a ~16 KB cifs_req_poolp object runs off the end of the slab object, and the bytes reach userspace through tcon->nativeFileSystem in /proc/fs/cifs/DebugData.
Reject a byte area too small for what the parser consumes. Two bytes is the least it can consume, and no conformant response carries fewer. The new trace point is the 129th smb_eio_trace entry, which __mode(byte) cannot represent, so the attribute goes with it.
fs/smb/client/cifssmb.c +6 -0
@@ -615,6 +615,11 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses, tcon->tid = smb_buffer_response->Tid; bcc_ptr =pByteArea (smb_buffer_response); bytes_left =get_bcc (smb_buffer_response); +if (bytes_left <2 ) { + rc =smb_EIO2 (smb_eio_trace_tcon_bcc_too_small, + bytes_left,2 ); + goto out; + } length =strnlen (bcc_ptr, bytes_left -2 );if (smb_buffer->Flags2 &SMBFLG2_UNICODE ) is_unicode = true;
@@ -670,6 +675,7 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses,reset_cifs_unix_caps (xid, tcon,NULL ,NULL ); } } +out:cifs_buf_release (smb_buffer);return rc; }
fs/smb/client/trace.h +2 -1
@@ -133,6 +133,7 @@ EM(smb_eio_trace_sym_slash, "sym_slash") \ EM(smb_eio_trace_sym_target_len, "sym_target_len") \ EM(smb_eio_trace_symlink_file_size, "symlink_file_size") \ + EM(smb_eio_trace_tcon_bcc_too_small, "tcon_bcc_too_small") \ EM(smb_eio_trace_tdis_in_reconnect, "tdis_in_reconnect") \ EM(smb_eio_trace_tx_chained_async, "tx_chained_async") \EM (smb_eio_trace_tx_compress_failed,"tx_compress_failed" ) \
@@ -213,7 +214,7 @@#define EM (a, b) a,#define E_ (a, b) a -enum smb_eio_trace { smb_eio_traces }__mode (byte ); +enum smb_eio_trace { smb_eio_traces };enum smb3_rw_credits_trace { smb3_rw_credits_traces }__mode (byte );enum smb3_tcon_ref_trace { smb3_tcon_ref_traces }__mode (byte );
Sasha Levin
maintainerPATCH 1/2 cifs: SMB1 split: connect.c
From: David Howells <[email protected]>
[ Upstream commit 88f7d7e32d9e086ba87c6b04a9ba57f3f41268bd ]
Split SMB1-specific connection management stuff to smb1ops.c and move CIFSTCon() to cifssmb.c.
[ sashal: Reduced backport -- upstream 88f7d7e32d9e0 touches 5 file(s), this
backport carries 2. Not backported here:
fs/smb/client/cifsproto.h
fs/smb/client/cifssmb.c
fs/smb/client/connect.c
fs/smb/client/smb1ops.c
fs/smb/client/smb1proto.h
This note is generated from the file lists only; see the resolution record for the reasoning. ]
Stable-dep-of: 65deb1835934 ("smb: client: reject a tree connect response whose byte count is too small")
--- fs/cifs/cifssmb.c | 128 +++++++++++++++++++++++++++++++++++++++++++++ fs/cifs/connect.c | 129 ---------------------------------------------- 2 files changed, 128 insertions(+), 129 deletions(-)
fs/cifs/cifssmb.c +128 -0
@@ -582,6 +582,134 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)return rc; } +/* +* Issue a TREE_CONNECT request. +*/ +int +CIFSTCon (const unsigned int xid,struct cifs_ses *ses, +const char *tree,struct cifs_tcon *tcon, +const struct nls_table *nls_codepage) +{ +struct smb_hdr *smb_buffer; +struct smb_hdr *smb_buffer_response; +TCONX_REQ *pSMB; +TCONX_RSP *pSMBr; +unsigned char *bcc_ptr; +int rc =0 ; +int length; +__u16 bytes_left, count; + +if (ses ==NULL ) +return -EIO ; + + smb_buffer =cifs_buf_get (); +if (smb_buffer ==NULL ) +return -ENOMEM ; + + smb_buffer_response = smb_buffer; + +header_assemble (smb_buffer,SMB_COM_TREE_CONNECT_ANDX , +NULL /*no tid */ ,4 /*wct */ ); + + smb_buffer->Mid =get_next_mid (ses->server); + smb_buffer->Uid = ses->Suid; + pSMB = (TCONX_REQ *) smb_buffer; + pSMBr = (TCONX_RSP *) smb_buffer_response; + + pSMB->AndXCommand =0xFF ; + pSMB->Flags =cpu_to_le16 (TCON_EXTENDED_SECINFO ); + bcc_ptr = &pSMB->Password[0 ]; + + pSMB->PasswordLength =cpu_to_le16 (1 );/* minimum */ + *bcc_ptr =0 ;/* password is null byte */ + bcc_ptr++;/* skip password */ +/* already aligned so no need to do it below */ + +if (ses->server->sign) + smb_buffer->Flags2 |=SMBFLG2_SECURITY_SIGNATURE ; + +if (ses->capabilities &CAP_STATUS32 ) { + smb_buffer->Flags2 |=SMBFLG2_ERR_STATUS ; + } +if (ses->capabilities &CAP_DFS ) { + smb_buffer->Flags2 |=SMBFLG2_DFS ; + } +if (ses->capabilities &CAP_UNICODE ) { + smb_buffer->Flags2 |=SMBFLG2_UNICODE ; + length = +cifs_strtoUTF16 ((__le16 *) bcc_ptr, tree, +6 /* max utf8 char length in bytes */ * + (/* server len*/ +256 /* share len */ ), nls_codepage); + bcc_ptr +=2 * length;/* convert num 16 bit words to bytes */ + bcc_ptr +=2 ;/* skip trailing null */ + }else {/* ASCII */ +strcpy (bcc_ptr, tree); + bcc_ptr +=strlen (tree) +1 ; + } +strcpy (bcc_ptr,"?????" ); + bcc_ptr +=strlen ("?????" ); + bcc_ptr +=1 ; + count = bcc_ptr - &pSMB->Password[0 ]; +be32_add_cpu (&pSMB->hdr.smb_buf_length, count); + pSMB->ByteCount =cpu_to_le16 (count); + + rc =SendReceive (xid, ses, smb_buffer, smb_buffer_response, &length, +0 ); + +/* above now done in SendReceive */ +if (rc ==0 ) { +bool is_unicode; + + tcon->tidStatus = CifsGood; + tcon->need_reconnect = false; + tcon->tid = smb_buffer_response->Tid; + bcc_ptr =pByteArea (smb_buffer_response); + bytes_left =get_bcc (smb_buffer_response); + length =strnlen (bcc_ptr, bytes_left -2 ); +if (smb_buffer->Flags2 &SMBFLG2_UNICODE ) + is_unicode = true; +else + is_unicode = false; + + +/* skip service field (NB: this field is always ASCII) */ +if (length ==3 ) { +if ((bcc_ptr[0 ] =='I' ) && (bcc_ptr[1 ] =='P' ) && + (bcc_ptr[2 ] =='C' )) { +cifs_dbg (FYI ,"IPC connection\n" ); + tcon->ipc = true; + tcon->pipe = true; + } + }else if (length ==2 ) { +if ((bcc_ptr[0 ] =='A' ) && (bcc_ptr[1 ] ==':' )) { +/* the most common case */ +cifs_dbg (FYI ,"disk share connection\n" ); + } + } + bcc_ptr += length +1 ; + bytes_left -= (length +1 ); +strlcpy (tcon->treeName, tree,sizeof (tcon->treeName)); + +/* mostly informational -- no need to fail on error here */ +kfree (tcon->nativeFileSystem); + tcon->nativeFileSystem =cifs_strndup_from_utf16 (bcc_ptr, + bytes_left, is_unicode, + nls_codepage); + +cifs_dbg (FYI ,"nativeFileSystem=%s\n" , tcon->nativeFileSystem); + +if ((smb_buffer_response->WordCount ==3 ) || + (smb_buffer_response->WordCount ==7 )) +/* field is in same location */ + tcon->Flags =le16_to_cpu (pSMBr->OptionalSupport); +else + tcon->Flags =0 ; +cifs_dbg (FYI ,"Tcon flags: 0x%x\n" , tcon->Flags); + } +cifs_buf_release (smb_buffer); +return rc; +} +int CIFSSMBTDis (const unsigned int xid,struct cifs_tcon *tcon) {
fs/cifs/connect.c +0 -129
135 lines not on this page · raw message
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/2 smb: client: reject a tree connect response whose byte count is too small
From: Bryam Vargas <[email protected]>
[ Upstream commit 65deb18359341141d37dc86fc7853511be3c87a7 ]
CIFSTCon() bounds its strnlen() over the byte area with the server's ByteCount minus two, which for ByteCount 0 or 1 goes negative as an int and converts to a huge size_t. The later subtraction wraps the __u16 bytes_left, and that is what bounds cifs_strndup_from_utf16(): a bound of up to 65535 against a ~16 KB cifs_req_poolp object runs off the end of the slab object, and the bytes reach userspace through tcon->nativeFileSystem in /proc/fs/cifs/DebugData.
Reject a byte area too small for what the parser consumes. Two bytes is the least it can consume, and no conformant response carries fewer. The new trace point is the 129th smb_eio_trace entry, which __mode(byte) cannot represent, so the attribute goes with it.
--- fs/cifs/cifssmb.c | 5 +++++ 1 file changed, 5 insertions(+)
fs/cifs/cifssmb.c +5 -0
@@ -665,6 +665,10 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses, tcon->tid = smb_buffer_response->Tid; bcc_ptr =pByteArea (smb_buffer_response); bytes_left =get_bcc (smb_buffer_response); +if (bytes_left <2 ) { + rc = -EIO ; + goto out; + } length =strnlen (bcc_ptr, bytes_left -2 );if (smb_buffer->Flags2 &SMBFLG2_UNICODE ) is_unicode = true;
@@ -706,6 +710,7 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses, tcon->Flags =0 ;cifs_dbg (FYI ,"Tcon flags: 0x%x\n" , tcon->Flags); } +out:cifs_buf_release (smb_buffer);return rc; }
Signature · 1 line
2.53.0