[PATCH] smb: client: fix UAF and buffer leak in cifs_check_trans2() for malformed secondary T2
Frank Sorenson <[email protected]>
| Newsgroups | org.kernel.vger.linux-cifs,org.kernel.vger.stable |
|---|---|
| Message-ID | <[email protected]> |
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.
Fixes: 316cf94a910f ("CIFS: Move trans2 processing to ops struct")
Cc: [email protected] # cifs_check_trans2() is in smb1ops.c on kernels < 7.0
Signed-off-by: Frank Sorenson <[email protected]>
---
fs/smb/client/smb1transport.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/fs/smb/client/smb1transport.c b/fs/smb/client/smb1transport.c
index 966f2cf83a51..f11a4a243784 100644
--- a/fs/smb/client/smb1transport.c
+++ b/fs/smb/client/smb1transport.c
@@ -430,10 +430,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*/
--
2.55.0