public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: David Howells <dhowells@redhat.com>
To: Steve French <sfrench@samba.org>
Cc: David Howells <dhowells@redhat.com>,
	Paulo Alcantara <pc@manguebit.org>,
	Enzo Matsumiya <ematsumiya@suse.de>,
	linux-cifs@vger.kernel.org, linux-fsdevel@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: [PATCH 23/37] cifs: SMB1 split: Move some SMB1 received PDU checking bits to smb1transport.c
Date: Mon, 22 Dec 2025 22:29:48 +0000	[thread overview]
Message-ID: <20251222223006.1075635-24-dhowells@redhat.com> (raw)
In-Reply-To: <20251222223006.1075635-1-dhowells@redhat.com>

Move some SMB1 received checking bits to smb1transport.c from misc.c
so that they're with the rest of the receive handling code.

Signed-off-by: David Howells <dhowells@redhat.com>
cc: Steve French <sfrench@samba.org>
cc: Paulo Alcantara <pc@manguebit.org>
cc: Enzo Matsumiya <ematsumiya@suse.de>
cc: linux-cifs@vger.kernel.org
cc: linux-fsdevel@vger.kernel.org
cc: linux-kernel@vger.kernel.org
---
 fs/smb/client/cifsproto.h     |   2 -
 fs/smb/client/misc.c          | 126 ----------------------------------
 fs/smb/client/smb1proto.h     |   2 +
 fs/smb/client/smb1transport.c | 126 ++++++++++++++++++++++++++++++++++
 4 files changed, 128 insertions(+), 128 deletions(-)

diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
index b151796b3ba5..53d23958b9da 100644
--- a/fs/smb/client/cifsproto.h
+++ b/fs/smb/client/cifsproto.h
@@ -131,8 +131,6 @@ void cifs_signal_cifsd_for_reconnect(struct TCP_Server_Info *server,
 void cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server,
 					   bool mark_smb_session);
 int cifs_reconnect(struct TCP_Server_Info *server, bool mark_smb_session);
-int checkSMB(char *buf, unsigned int pdu_len, unsigned int total_read,
-	     struct TCP_Server_Info *server);
 bool is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv);
 bool backup_cred(struct cifs_sb_info *cifs_sb);
 bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file,
diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c
index 9529fa385938..f3ecdf20dbe0 100644
--- a/fs/smb/client/misc.c
+++ b/fs/smb/client/misc.c
@@ -314,132 +314,6 @@ header_assemble(struct smb_hdr *buffer, char smb_command,
 	return in_len;
 }
 
-static int
-check_smb_hdr(struct smb_hdr *smb)
-{
-	/* does it have the right SMB "signature" ? */
-	if (*(__le32 *) smb->Protocol != SMB1_PROTO_NUMBER) {
-		cifs_dbg(VFS, "Bad protocol string signature header 0x%x\n",
-			 *(unsigned int *)smb->Protocol);
-		return 1;
-	}
-
-	/* if it's a response then accept */
-	if (smb->Flags & SMBFLG_RESPONSE)
-		return 0;
-
-	/* only one valid case where server sends us request */
-	if (smb->Command == SMB_COM_LOCKING_ANDX)
-		return 0;
-
-	/*
-	 * Windows NT server returns error resposne (e.g. STATUS_DELETE_PENDING
-	 * or STATUS_OBJECT_NAME_NOT_FOUND or ERRDOS/ERRbadfile or any other)
-	 * for some TRANS2 requests without the RESPONSE flag set in header.
-	 */
-	if (smb->Command == SMB_COM_TRANSACTION2 && smb->Status.CifsError != 0)
-		return 0;
-
-	cifs_dbg(VFS, "Server sent request, not response. mid=%u\n",
-		 get_mid(smb));
-	return 1;
-}
-
-int
-checkSMB(char *buf, unsigned int pdu_len, unsigned int total_read,
-	 struct TCP_Server_Info *server)
-{
-	struct smb_hdr *smb = (struct smb_hdr *)buf;
-	__u32 rfclen = pdu_len;
-	__u32 clc_len;  /* calculated length */
-	cifs_dbg(FYI, "checkSMB Length: 0x%x, smb_buf_length: 0x%x\n",
-		 total_read, rfclen);
-
-	/* is this frame too small to even get to a BCC? */
-	if (total_read < 2 + sizeof(struct smb_hdr)) {
-		if ((total_read >= sizeof(struct smb_hdr) - 1)
-			    && (smb->Status.CifsError != 0)) {
-			/* it's an error return */
-			smb->WordCount = 0;
-			/* some error cases do not return wct and bcc */
-			return 0;
-		} else if ((total_read == sizeof(struct smb_hdr) + 1) &&
-				(smb->WordCount == 0)) {
-			char *tmp = (char *)smb;
-			/* Need to work around a bug in two servers here */
-			/* First, check if the part of bcc they sent was zero */
-			if (tmp[sizeof(struct smb_hdr)] == 0) {
-				/* some servers return only half of bcc
-				 * on simple responses (wct, bcc both zero)
-				 * in particular have seen this on
-				 * ulogoffX and FindClose. This leaves
-				 * one byte of bcc potentially uninitialized
-				 */
-				/* zero rest of bcc */
-				tmp[sizeof(struct smb_hdr)+1] = 0;
-				return 0;
-			}
-			cifs_dbg(VFS, "rcvd invalid byte count (bcc)\n");
-			return smb_EIO1(smb_eio_trace_rx_inv_bcc, tmp[sizeof(struct smb_hdr)]);
-		} else {
-			cifs_dbg(VFS, "Length less than smb header size\n");
-			return smb_EIO2(smb_eio_trace_rx_too_short,
-					total_read, smb->WordCount);
-		}
-	} else if (total_read < sizeof(*smb) + 2 * smb->WordCount) {
-		cifs_dbg(VFS, "%s: can't read BCC due to invalid WordCount(%u)\n",
-			 __func__, smb->WordCount);
-		return smb_EIO2(smb_eio_trace_rx_check_rsp,
-				total_read, 2 + sizeof(struct smb_hdr));
-	}
-
-	/* otherwise, there is enough to get to the BCC */
-	if (check_smb_hdr(smb))
-		return smb_EIO1(smb_eio_trace_rx_rfc1002_magic, *(u32 *)smb->Protocol);
-	clc_len = smbCalcSize(smb);
-
-	if (rfclen != total_read) {
-		cifs_dbg(VFS, "Length read does not match RFC1001 length %d/%d\n",
-			 rfclen, total_read);
-		return smb_EIO2(smb_eio_trace_rx_check_rsp,
-				total_read, rfclen);
-	}
-
-	if (rfclen != clc_len) {
-		__u16 mid = get_mid(smb);
-		/* check if bcc wrapped around for large read responses */
-		if ((rfclen > 64 * 1024) && (rfclen > clc_len)) {
-			/* check if lengths match mod 64K */
-			if (((rfclen) & 0xFFFF) == (clc_len & 0xFFFF))
-				return 0; /* bcc wrapped */
-		}
-		cifs_dbg(FYI, "Calculated size %u vs length %u mismatch for mid=%u\n",
-			 clc_len, rfclen, mid);
-
-		if (rfclen < clc_len) {
-			cifs_dbg(VFS, "RFC1001 size %u smaller than SMB for mid=%u\n",
-				 rfclen, mid);
-			return smb_EIO2(smb_eio_trace_rx_calc_len_too_big,
-					rfclen, clc_len);
-		} else if (rfclen > clc_len + 512) {
-			/*
-			 * Some servers (Windows XP in particular) send more
-			 * data than the lengths in the SMB packet would
-			 * indicate on certain calls (byte range locks and
-			 * trans2 find first calls in particular). While the
-			 * client can handle such a frame by ignoring the
-			 * trailing data, we choose limit the amount of extra
-			 * data to 512 bytes.
-			 */
-			cifs_dbg(VFS, "RFC1001 size %u more than 512 bytes larger than SMB for mid=%u\n",
-				 rfclen, mid);
-			return smb_EIO2(smb_eio_trace_rx_overlong,
-					rfclen, clc_len + 512);
-		}
-	}
-	return 0;
-}
-
 bool
 is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
 {
diff --git a/fs/smb/client/smb1proto.h b/fs/smb/client/smb1proto.h
index bf24974fbb00..c73cc10dfcc8 100644
--- a/fs/smb/client/smb1proto.h
+++ b/fs/smb/client/smb1proto.h
@@ -235,6 +235,8 @@ int SendReceive(const unsigned int xid, struct cifs_ses *ses,
 		const int flags);
 bool cifs_check_trans2(struct mid_q_entry *mid, struct TCP_Server_Info *server,
 		       char *buf, int malformed);
+int checkSMB(char *buf, unsigned int pdu_len, unsigned int total_read,
+	     struct TCP_Server_Info *server);
 
 
 #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
diff --git a/fs/smb/client/smb1transport.c b/fs/smb/client/smb1transport.c
index 5f95bffc8e44..5e508b2c661f 100644
--- a/fs/smb/client/smb1transport.c
+++ b/fs/smb/client/smb1transport.c
@@ -432,3 +432,129 @@ cifs_check_trans2(struct mid_q_entry *mid, struct TCP_Server_Info *server,
 	}
 	return true;
 }
+
+static int
+check_smb_hdr(struct smb_hdr *smb)
+{
+	/* does it have the right SMB "signature" ? */
+	if (*(__le32 *) smb->Protocol != SMB1_PROTO_NUMBER) {
+		cifs_dbg(VFS, "Bad protocol string signature header 0x%x\n",
+			 *(unsigned int *)smb->Protocol);
+		return 1;
+	}
+
+	/* if it's a response then accept */
+	if (smb->Flags & SMBFLG_RESPONSE)
+		return 0;
+
+	/* only one valid case where server sends us request */
+	if (smb->Command == SMB_COM_LOCKING_ANDX)
+		return 0;
+
+	/*
+	 * Windows NT server returns error resposne (e.g. STATUS_DELETE_PENDING
+	 * or STATUS_OBJECT_NAME_NOT_FOUND or ERRDOS/ERRbadfile or any other)
+	 * for some TRANS2 requests without the RESPONSE flag set in header.
+	 */
+	if (smb->Command == SMB_COM_TRANSACTION2 && smb->Status.CifsError != 0)
+		return 0;
+
+	cifs_dbg(VFS, "Server sent request, not response. mid=%u\n",
+		 get_mid(smb));
+	return 1;
+}
+
+int
+checkSMB(char *buf, unsigned int pdu_len, unsigned int total_read,
+	 struct TCP_Server_Info *server)
+{
+	struct smb_hdr *smb = (struct smb_hdr *)buf;
+	__u32 rfclen = pdu_len;
+	__u32 clc_len;  /* calculated length */
+	cifs_dbg(FYI, "checkSMB Length: 0x%x, smb_buf_length: 0x%x\n",
+		 total_read, rfclen);
+
+	/* is this frame too small to even get to a BCC? */
+	if (total_read < 2 + sizeof(struct smb_hdr)) {
+		if ((total_read >= sizeof(struct smb_hdr) - 1)
+			    && (smb->Status.CifsError != 0)) {
+			/* it's an error return */
+			smb->WordCount = 0;
+			/* some error cases do not return wct and bcc */
+			return 0;
+		} else if ((total_read == sizeof(struct smb_hdr) + 1) &&
+				(smb->WordCount == 0)) {
+			char *tmp = (char *)smb;
+			/* Need to work around a bug in two servers here */
+			/* First, check if the part of bcc they sent was zero */
+			if (tmp[sizeof(struct smb_hdr)] == 0) {
+				/* some servers return only half of bcc
+				 * on simple responses (wct, bcc both zero)
+				 * in particular have seen this on
+				 * ulogoffX and FindClose. This leaves
+				 * one byte of bcc potentially uninitialized
+				 */
+				/* zero rest of bcc */
+				tmp[sizeof(struct smb_hdr)+1] = 0;
+				return 0;
+			}
+			cifs_dbg(VFS, "rcvd invalid byte count (bcc)\n");
+			return smb_EIO1(smb_eio_trace_rx_inv_bcc, tmp[sizeof(struct smb_hdr)]);
+		} else {
+			cifs_dbg(VFS, "Length less than smb header size\n");
+			return smb_EIO2(smb_eio_trace_rx_too_short,
+					total_read, smb->WordCount);
+		}
+	} else if (total_read < sizeof(*smb) + 2 * smb->WordCount) {
+		cifs_dbg(VFS, "%s: can't read BCC due to invalid WordCount(%u)\n",
+			 __func__, smb->WordCount);
+		return smb_EIO2(smb_eio_trace_rx_check_rsp,
+				total_read, 2 + sizeof(struct smb_hdr));
+	}
+
+	/* otherwise, there is enough to get to the BCC */
+	if (check_smb_hdr(smb))
+		return smb_EIO1(smb_eio_trace_rx_rfc1002_magic, *(u32 *)smb->Protocol);
+	clc_len = smbCalcSize(smb);
+
+	if (rfclen != total_read) {
+		cifs_dbg(VFS, "Length read does not match RFC1001 length %d/%d\n",
+			 rfclen, total_read);
+		return smb_EIO2(smb_eio_trace_rx_check_rsp,
+				total_read, rfclen);
+	}
+
+	if (rfclen != clc_len) {
+		__u16 mid = get_mid(smb);
+		/* check if bcc wrapped around for large read responses */
+		if ((rfclen > 64 * 1024) && (rfclen > clc_len)) {
+			/* check if lengths match mod 64K */
+			if (((rfclen) & 0xFFFF) == (clc_len & 0xFFFF))
+				return 0; /* bcc wrapped */
+		}
+		cifs_dbg(FYI, "Calculated size %u vs length %u mismatch for mid=%u\n",
+			 clc_len, rfclen, mid);
+
+		if (rfclen < clc_len) {
+			cifs_dbg(VFS, "RFC1001 size %u smaller than SMB for mid=%u\n",
+				 rfclen, mid);
+			return smb_EIO2(smb_eio_trace_rx_calc_len_too_big,
+					rfclen, clc_len);
+		} else if (rfclen > clc_len + 512) {
+			/*
+			 * Some servers (Windows XP in particular) send more
+			 * data than the lengths in the SMB packet would
+			 * indicate on certain calls (byte range locks and
+			 * trans2 find first calls in particular). While the
+			 * client can handle such a frame by ignoring the
+			 * trailing data, we choose limit the amount of extra
+			 * data to 512 bytes.
+			 */
+			cifs_dbg(VFS, "RFC1001 size %u more than 512 bytes larger than SMB for mid=%u\n",
+				 rfclen, mid);
+			return smb_EIO2(smb_eio_trace_rx_overlong,
+					rfclen, clc_len + 512);
+		}
+	}
+	return 0;
+}


  parent reply	other threads:[~2025-12-22 22:31 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-12-22 22:29 [PATCH 00/37] cifs: Scripted header file cleanup and SMB1 split David Howells
2025-12-22 22:29 ` [PATCH 01/37] cifs: Scripted clean up fs/smb/client/cached_dir.h David Howells
2025-12-22 22:29 ` [PATCH 02/37] cifs: Scripted clean up fs/smb/client/dfs.h David Howells
2025-12-22 22:29 ` [PATCH 03/37] cifs: Scripted clean up fs/smb/client/cifsproto.h David Howells
2025-12-22 22:29 ` [PATCH 04/37] cifs: Scripted clean up fs/smb/client/cifs_unicode.h David Howells
2025-12-22 22:29 ` [PATCH 05/37] cifs: Scripted clean up fs/smb/client/netlink.h David Howells
2025-12-22 22:29 ` [PATCH 06/37] cifs: Scripted clean up fs/smb/client/cifsfs.h David Howells
2025-12-22 22:29 ` [PATCH 07/37] cifs: Scripted clean up fs/smb/client/dfs_cache.h David Howells
2025-12-22 22:29 ` [PATCH 08/37] cifs: Scripted clean up fs/smb/client/dns_resolve.h David Howells
2025-12-22 22:29 ` [PATCH 09/37] cifs: Scripted clean up fs/smb/client/cifsglob.h David Howells
2025-12-22 22:29 ` [PATCH 10/37] cifs: Scripted clean up fs/smb/client/fscache.h David Howells
2025-12-22 22:29 ` [PATCH 11/37] cifs: Scripted clean up fs/smb/client/fs_context.h David Howells
2025-12-22 22:29 ` [PATCH 12/37] cifs: Scripted clean up fs/smb/client/cifs_spnego.h David Howells
2025-12-22 22:29 ` [PATCH 13/37] cifs: Scripted clean up fs/smb/client/compress.h David Howells
2025-12-22 22:29 ` [PATCH 14/37] cifs: Scripted clean up fs/smb/client/cifs_swn.h David Howells
2025-12-22 22:29 ` [PATCH 15/37] cifs: Scripted clean up fs/smb/client/cifs_debug.h David Howells
2025-12-22 22:29 ` [PATCH 16/37] cifs: Scripted clean up fs/smb/client/smb2proto.h David Howells
2025-12-22 22:29 ` [PATCH 17/37] cifs: Scripted clean up fs/smb/client/reparse.h David Howells
2025-12-22 22:29 ` [PATCH 18/37] cifs: Scripted clean up fs/smb/client/ntlmssp.h David Howells
2025-12-22 22:29 ` [PATCH 19/37] cifs: SMB1 split: Rename cifstransport.c David Howells
2025-12-22 22:29 ` [PATCH 20/37] cifs: SMB1 split: Create smb1proto.h for SMB1 declarations David Howells
2025-12-22 22:29 ` [PATCH 21/37] cifs: SMB1 split: Separate out SMB1 decls into smb1proto.h David Howells
2025-12-22 22:29 ` [PATCH 22/37] cifs: SMB1 split: Move some SMB1 receive bits to smb1transport.c David Howells
2025-12-22 22:29 ` David Howells [this message]
2025-12-22 22:29 ` [PATCH 24/37] cifs: SMB1 split: Add some #includes David Howells
2025-12-22 22:29 ` [PATCH 25/37] cifs: SMB1 split: Split SMB1 protocol defs into smb1pdu.h David Howells
2026-01-19  6:51   ` ChenXiaoSong
2025-12-22 22:29 ` [PATCH 26/37] cifs: SMB1 split: Adjust #includes David Howells
2025-12-22 22:29 ` [PATCH 27/37] cifs: SMB1 split: Move BCC access functions David Howells
2025-12-22 22:29 ` [PATCH 28/37] cifs: SMB1 split: Don't return smb_hdr from cifs_{,small_}buf_get() David Howells
2025-12-22 22:29 ` [PATCH 29/37] cifs: Fix cifs_dump_mids() to call ->dump_detail David Howells
2025-12-22 22:29 ` [PATCH 30/37] cifs: SMB1 split: Move inline funcs David Howells
2025-12-22 22:29 ` [PATCH 31/37] cifs: SMB1 split: cifs_debug.c David Howells
2025-12-22 22:29 ` [PATCH 32/37] cifs: SMB1 split: misc.c David Howells
2025-12-22 22:29 ` [PATCH 33/37] cifs: SMB1 split: netmisc.c David Howells
2025-12-22 22:29 ` [PATCH 34/37] cifs: SMB1 split: cifsencrypt.c David Howells
2025-12-22 22:30 ` [PATCH 35/37] cifs: SMB1 split: sess.c David Howells
2025-12-22 22:30 ` [PATCH 36/37] cifs: SMB1 split: connect.c David Howells
2025-12-22 22:30 ` [PATCH 37/37] cifs: SMB1 split: Make BCC accessors conditional David Howells
2026-01-15 16:53 ` [PATCH 00/37] cifs: Scripted header file cleanup and SMB1 split Enzo Matsumiya
2026-01-16  2:50   ` Steve French
2026-01-16  3:06     ` ChenXiaoSong
     [not found]       ` <CAH2r5msqwTqvCzpozKz_SPZsB-qP3RV_pfXZxZwMKMXWfmJHDg@mail.gmail.com>
2026-01-16  6:57         ` ChenXiaoSong
2026-01-16  6:58     ` David Howells
2026-01-16  7:04       ` ChenXiaoSong
2026-01-16  9:21         ` David Howells

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251222223006.1075635-24-dhowells@redhat.com \
    --to=dhowells@redhat.com \
    --cc=ematsumiya@suse.de \
    --cc=linux-cifs@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pc@manguebit.org \
    --cc=sfrench@samba.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox