FAILED: patch "[PATCH] smb: client: fix UAF and buffer leak in cifs_check_trans2()" failed to apply to 6.1-stable tree
Subsystems (5)
[email protected]
maintainerThe patch below does not apply to the 6.1-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-6.1.y
git checkout FETCH_HEAD
git cherry-pick -x 730d0bb19507b9e19c2fe5343109ac618e2fbce5
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026090304-drowsily-unread-e280@gregkh' --subject-prefix 'PATCH 6.1.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 730d0bb19507b9e19c2fe5343109ac618e2fbce5 Mon Sep 17 00:00:00 2001
From: Frank Sorenson <[email protected]>
Date: Wed, 12 Aug 2026 21:39:51 -0500
Subject: [PATCH] smb: client: fix UAF and buffer leak in cifs_check_trans2()
for malformed secondary T2
When a valid primary TRANSACT2 response has been received (mid->resp_buf set, mid->multiRsp true) and a subsequent secondary response causes cifs_check_trans2() to return false -- either because the SMB header is invalid (malformed != 0) or because check2ndT2() rejects the PDU -- handle_mid() overwrites mid->resp_buf with the new buffer (leaking the primary buffer) and, because mid->multiRsp is set, skips the server->smallbuf/bigbuf NULL-out. When the user thread frees mid->resp_buf, server->smallbuf or server->bigbuf is left dangling; the demux thread reuses it for the next packet, resulting in a use-after-free.
Combine both early-exit conditions and, when mid->multiRsp is already set, abort the pending transaction inline: set multiEnd, call dequeue_mid() with malformed=true, and return true so handle_mid() exits without touching mid->resp_buf or the server buffer pointers.
fs/smb/client/smb1transport.c +11 -3
@@ -449,10 +449,18 @@ bool cifs_check_trans2(struct mid_q_entry *mid, struct TCP_Server_Info *server, char *buf, int malformed) { - if (malformed) - return false; -if (check2ndT2 (buf) <=0 ) + if (malformed || check2ndT2(buf) <= 0) { + /* mid->multiRsp blocks the server buf detach in handle_mid(); + * returning false here would leak resp_buf and leave a dangling + * server->smallbuf/bigbuf after the user thread frees resp_buf. + */ + if (mid->multiRsp) { + mid->multiEnd = true; +dequeue_mid (server, mid, true); +return true; + }return false; + } mid->multiRsp = true;if (mid->resp_buf) {/* merge response - fix up 1st*/
Sasha Levin
maintainerPATCH 1/4 cifs: Remove the server pointer from smb_message
From: David Howells <[email protected]>
[ Upstream commit 87fba18abbb8433a47045c785f2edc027e4d2bc5 ]
Remove the server pointer from smb_message and instead pass it down to all the things that access it.
[ sashal: Reduced backport -- upstream 87fba18abbb84 touches 12 file(s), this
backport carries 6. Not backported here:
fs/smb/client/cifsfs.c
fs/smb/client/cifsglob.h
fs/smb/client/cifssmb.c
fs/smb/client/cifstransport.c
fs/smb/client/netmisc.c
fs/smb/client/smb1ops.c
fs/smb/client/smb2pdu.c
fs/smb/client/smb2transport.c
This note is generated from the file lists only; see the resolution record for the reasoning. ]
Stable-dep-of: 730d0bb19507 ("smb: client: fix UAF and buffer leak in cifs_check_trans2() for malformed secondary T2")
---
fs/smb/client/Makefile | 2 +-
fs/smb/client/cifsproto.h | 3 ++-
fs/smb/client/connect.c | 11 ++++++-----
fs/smb/client/{smb1ops.c => smb1transport.c} | 2 +-
fs/smb/client/smb2ops.c | 14 +++++++-------
fs/smb/client/transport.c | 4 ++--
6 files changed, 19 insertions(+), 17 deletions(-)
rename fs/smb/client/{smb1ops.c => smb1transport.c} (99%)fs/smb/client/Makefile +1 -1
@@ -31,4 +31,4 @@ cifs-$(CONFIG_CIFS_SMB_DIRECT) += smbdirect.o cifs-$(CONFIG_CIFS_ROOT) += cifsroot.o -cifs-$(CONFIG_CIFS_ALLOW_INSECURE_LEGACY) += smb1ops.o cifssmb.o +cifs-$(CONFIG_CIFS_ALLOW_INSECURE_LEGACY) += smb1transport.o cifssmb.o
fs/smb/client/cifsproto.h +2 -1
@@ -257,7 +257,8 @@ extern unsigned int setup_authusers_ACE(struct cifs_ace *pace);extern unsigned int setup_special_mode_ACE (struct cifs_ace *pace,__u64 nmode);extern unsigned int setup_special_user_owner_ACE (struct cifs_ace *pace); -extern void dequeue_mid (struct mid_q_entry *mid,bool malformed); +extern void dequeue_mid (struct TCP_Server_Info *server, +struct mid_q_entry *mid,bool malformed);extern int cifs_read_from_socket (struct TCP_Server_Info *server,char *buf,unsigned int to_read); extern ssize_t cifs_discard_from_socket(struct TCP_Server_Info *server,
fs/smb/client/connect.c +6 -5
@@ -892,12 +892,13 @@ is_smb_response(struct TCP_Server_Info *server, unsigned char type) }void -dequeue_mid (struct mid_q_entry *mid,bool malformed) +dequeue_mid (struct TCP_Server_Info *server,struct mid_q_entry *mid, +bool malformed) {#ifdef CONFIG_CIFS_STATS2 mid->when_received = jiffies;#endif -spin_lock (&mid->server->mid_lock); +spin_lock (&server->mid_lock);if (!malformed) mid->mid_state =MID_RESPONSE_RECEIVED ;else
@@ -907,12 +908,12 @@ dequeue_mid(struct mid_q_entry *mid, bool malformed)* function has finished processing it is a bug. */ if (mid->mid_flags &MID_DELETED ) { -spin_unlock (&mid->server->mid_lock); +spin_unlock (&server->mid_lock);pr_warn_once ("trying to dequeue a deleted mid\n" ); }else {list_del_init (&mid->qhead); mid->mid_flags |=MID_DELETED ; -spin_unlock (&mid->server->mid_lock); +spin_unlock (&server->mid_lock); } }
@@ -948,7 +949,7 @@ handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,else server->smallbuf =NULL ; } -dequeue_mid (mid, malformed); +dequeue_mid (server, mid, malformed); }int
fs/smb/client/smb1transport.c renamed from fs/smb/client/smb1ops.c +1 -1
@@ -398,7 +398,7 @@ cifs_check_trans2(struct mid_q_entry *mid, struct TCP_Server_Info *server,return true;/* All parts received or packet is malformed. */ mid->multiEnd = true; -dequeue_mid (mid, malformed); +dequeue_mid (server, mid, malformed);return true; }if (!server->large_buf) {
fs/smb/client/smb2ops.c +7 -7
@@ -4881,7 +4881,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,if (is_offloaded) mid->mid_state =MID_RESPONSE_RECEIVED ;else -dequeue_mid (mid, false); +dequeue_mid (server, mid, false);return 0 ; }
@@ -4908,7 +4908,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,if (is_offloaded) mid->mid_state =MID_RESPONSE_MALFORMED ;else -dequeue_mid (mid, rdata->result); +dequeue_mid (server, mid, rdata->result);return 0 ; }
@@ -4927,7 +4927,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,if (is_offloaded) mid->mid_state =MID_RESPONSE_MALFORMED ;else -dequeue_mid (mid, rdata->result); +dequeue_mid (server, mid, rdata->result);return 0 ; }
@@ -4937,7 +4937,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,if (is_offloaded) mid->mid_state =MID_RESPONSE_MALFORMED ;else -dequeue_mid (mid, rdata->result); +dequeue_mid (server, mid, rdata->result);return 0 ; }
@@ -4947,7 +4947,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,if (is_offloaded) mid->mid_state =MID_RESPONSE_MALFORMED ;else -dequeue_mid (mid, rdata->result); +dequeue_mid (server, mid, rdata->result);return 0 ; }
@@ -4965,7 +4965,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,if (is_offloaded) mid->mid_state =MID_RESPONSE_MALFORMED ;else -dequeue_mid (mid, rdata->result); +dequeue_mid (server, mid, rdata->result);return 0 ; }
@@ -4979,7 +4979,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,if (is_offloaded) mid->mid_state =MID_RESPONSE_RECEIVED ;else -dequeue_mid (mid, false); +dequeue_mid (server, mid, false);return length; }
fs/smb/client/transport.c +2 -2
@@ -1710,7 +1710,7 @@ __cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid,int length; length =cifs_discard_remaining_data (server); -dequeue_mid (mid, malformed); +dequeue_mid (server, mid, malformed); mid->resp_buf = server->smallbuf; server->smallbuf =NULL ;return length;
@@ -1848,7 +1848,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)if (server->total_read < buflen)return cifs_readv_discard (server, mid); -dequeue_mid (mid, false); +dequeue_mid (server, mid, false); mid->resp_buf = server->smallbuf; server->smallbuf =NULL ;return length;
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/4 cifs: Scripted clean up fs/smb/client/fscache.h
From: David Howells <[email protected]>
[ Upstream commit bc3de356aae666de5d8b5131545be87cf7754431 ]
Remove externs, correct argument names and reformat declarations.
Stable-dep-of: 730d0bb19507 ("smb: client: fix UAF and buffer leak in cifs_check_trans2() for malformed secondary T2")
--- fs/smb/client/fscache.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
fs/smb/client/fscache.h +5 -5
@@ -38,12 +38,12 @@ struct cifs_fscache_inode_coherency_data {/* * fscache.c */ -extern int cifs_fscache_get_super_cookie (struct cifs_tcon *); -extern void cifs_fscache_release_super_cookie (struct cifs_tcon *); +int cifs_fscache_get_super_cookie (struct cifs_tcon *tcon); +void cifs_fscache_release_super_cookie (struct cifs_tcon *tcon); -extern void cifs_fscache_get_inode_cookie (struct inode *inode); -extern void cifs_fscache_release_inode_cookie (struct inode *); -extern void cifs_fscache_unuse_inode_cookie (struct inode *inode,bool update); +void cifs_fscache_get_inode_cookie (struct inode *inode); +void cifs_fscache_release_inode_cookie (struct inode *inode); +void cifs_fscache_unuse_inode_cookie (struct inode *inode,bool update); static inline void cifs_fscache_fill_coherency(struct inode *inode,
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 3/4 cifs: SMB1 split: Create smb1proto.h for SMB1 declarations
In reply to Sasha LevinFrom: David Howells <[email protected]>
[ Upstream commit 86c666506ea2c42649879eeac7f29e7bedef2f23 ]
Stable-dep-of: 730d0bb19507 ("smb: client: fix UAF and buffer leak in cifs_check_trans2() for malformed secondary T2")
--- fs/smb/client/cifsglob.h | 2 -- fs/smb/client/cifsproto.h | 11 +--------- fs/smb/client/smb1proto.h | 40 +++++++++++++++++++++++++++++++++++ fs/smb/client/smb1transport.c | 2 +- 4 files changed, 42 insertions(+), 13 deletions(-) create mode 100644 fs/smb/client/smb1proto.h
fs/smb/client/cifsglob.h +0 -2
@@ -1995,8 +1995,6 @@ extern mempool_t *cifs_mid_poolp;/* Operations for different SMB versions */ #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY -extern struct smb_version_operations smb1_operations; -extern struct smb_version_values smb1_values;extern struct smb_version_operations smb20_operations;extern struct smb_version_values smb20_values;#endif /* CIFS_ALLOW_INSECURE_LEGACY */
fs/smb/client/cifsproto.h +1 -10
@@ -12,6 +12,7 @@#ifdef CONFIG_CIFS_DFS_UPCALL #include "dfs_cache.h" #endif +#include "smb1proto.h" struct statfs ;struct smb_rqst ;
@@ -416,16 +417,6 @@ extern int CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon, struct cifsFileInfo *cfile, __u64 size, bool set_allocation); -struct cifs_unix_set_info_args { -__u64 ctime; -__u64 atime; -__u64 mtime; -__u64 mode; -kuid_t uid; -kgid_t gid; -dev_t device; -}; - extern int CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon, const struct cifs_unix_set_info_args *args,
fs/smb/client/smb1proto.h new file +40 -0
@@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: LGPL-2.1 */ +/* +* +* Copyright (c) International Business Machines Corp., 2002,2008 +* Author(s): Steve French ([email protected]) +* +*/ +#ifndef _SMB1PROTO_H +#define _SMB1PROTO_H + +struct cifs_unix_set_info_args { +__u64 ctime; +__u64 atime; +__u64 mtime; +__u64 mode; +kuid_t uid; +kgid_t gid; +dev_t device; +}; + +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY + +/* +* cifssmb.c +*/ + +/* +* smb1ops.c +*/ +extern struct smb_version_operations smb1_operations; +extern struct smb_version_values smb1_values; + +/* +* smb1transport.c +*/ +bool cifs_check_trans2 (struct mid_q_entry *mid,struct TCP_Server_Info *server, +char *buf,int malformed); + +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ +#endif /* _SMB1PROTO_H */
fs/smb/client/smb1transport.c +1 -1
@@ -382,7 +382,7 @@ cifs_downgrade_oplock(struct TCP_Server_Info *server,cifs_set_oplock_level (cinode, oplock); } -static bool +bool cifs_check_trans2 (struct mid_q_entry *mid,struct TCP_Server_Info *server,char *buf,int malformed) {
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 4/4 smb: client: fix UAF and buffer leak in cifs_check_trans2() for malformed secondary T2
In reply to Sasha LevinFrom: Frank Sorenson <[email protected]>
[ Upstream commit 730d0bb19507b9e19c2fe5343109ac618e2fbce5 ]
When a valid primary TRANSACT2 response has been received (mid->resp_buf set, mid->multiRsp true) and a subsequent secondary response causes cifs_check_trans2() to return false -- either because the SMB header is invalid (malformed != 0) or because check2ndT2() rejects the PDU -- handle_mid() overwrites mid->resp_buf with the new buffer (leaking the primary buffer) and, because mid->multiRsp is set, skips the server->smallbuf/bigbuf NULL-out. When the user thread frees mid->resp_buf, server->smallbuf or server->bigbuf is left dangling; the demux thread reuses it for the next packet, resulting in a use-after-free.
Combine both early-exit conditions and, when mid->multiRsp is already set, abort the pending transaction inline: set multiEnd, call dequeue_mid() with malformed=true, and return true so handle_mid() exits without touching mid->resp_buf or the server buffer pointers.
--- fs/smb/client/smb1transport.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
fs/smb/client/smb1transport.c +11 -3
@@ -386,10 +386,18 @@ bool cifs_check_trans2(struct mid_q_entry *mid, struct TCP_Server_Info *server, char *buf, int malformed) { - if (malformed) - return false; -if (check2ndT2 (buf) <=0 ) + if (malformed || check2ndT2(buf) <= 0) { + /* mid->multiRsp blocks the server buf detach in handle_mid(); + * returning false here would leak resp_buf and leave a dangling + * server->smallbuf/bigbuf after the user thread frees resp_buf. + */ + if (mid->multiRsp) { + mid->multiEnd = true; +dequeue_mid (server, mid, true); +return true; + }return false; + } mid->multiRsp = true;if (mid->resp_buf) {/* merge response - fix up 1st*/
Signature · 1 line
2.53.0