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 22/37] cifs: SMB1 split: Move some SMB1 receive bits to smb1transport.c
Date: Mon, 22 Dec 2025 22:29:47 +0000 [thread overview]
Message-ID: <20251222223006.1075635-23-dhowells@redhat.com> (raw)
In-Reply-To: <20251222223006.1075635-1-dhowells@redhat.com>
Move some SMB1 receive bits to smb1transport.c from smb1ops.c where they're
mixed in with unrelated code to do with encoding, decoding and processing
PDUs.
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/smb1ops.c | 171 ----------------------------------
fs/smb/client/smb1proto.h | 2 +
fs/smb/client/smb1transport.c | 171 ++++++++++++++++++++++++++++++++++
3 files changed, 173 insertions(+), 171 deletions(-)
diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c
index 9729b56bd9d4..2534113596c7 100644
--- a/fs/smb/client/smb1ops.c
+++ b/fs/smb/client/smb1ops.c
@@ -284,146 +284,6 @@ cifs_get_next_mid(struct TCP_Server_Info *server)
return mid;
}
-/*
- return codes:
- 0 not a transact2, or all data present
- >0 transact2 with that much data missing
- -EINVAL invalid transact2
- */
-static int
-check2ndT2(char *buf)
-{
- struct smb_hdr *pSMB = (struct smb_hdr *)buf;
- struct smb_t2_rsp *pSMBt;
- int remaining;
- __u16 total_data_size, data_in_this_rsp;
-
- if (pSMB->Command != SMB_COM_TRANSACTION2)
- return 0;
-
- /* check for plausible wct, bcc and t2 data and parm sizes */
- /* check for parm and data offset going beyond end of smb */
- if (pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
- cifs_dbg(FYI, "Invalid transact2 word count\n");
- return -EINVAL;
- }
-
- pSMBt = (struct smb_t2_rsp *)pSMB;
-
- total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
- data_in_this_rsp = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
-
- if (total_data_size == data_in_this_rsp)
- return 0;
- else if (total_data_size < data_in_this_rsp) {
- cifs_dbg(FYI, "total data %d smaller than data in frame %d\n",
- total_data_size, data_in_this_rsp);
- return -EINVAL;
- }
-
- remaining = total_data_size - data_in_this_rsp;
-
- cifs_dbg(FYI, "missing %d bytes from transact2, check next response\n",
- remaining);
- if (total_data_size > CIFSMaxBufSize) {
- cifs_dbg(VFS, "TotalDataSize %d is over maximum buffer %d\n",
- total_data_size, CIFSMaxBufSize);
- return -EINVAL;
- }
- return remaining;
-}
-
-static int
-coalesce_t2(char *second_buf, struct smb_hdr *target_hdr, unsigned int *pdu_len)
-{
- struct smb_t2_rsp *pSMBs = (struct smb_t2_rsp *)second_buf;
- struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)target_hdr;
- char *data_area_of_tgt;
- char *data_area_of_src;
- int remaining;
- unsigned int byte_count, total_in_tgt;
- __u16 tgt_total_cnt, src_total_cnt, total_in_src;
-
- src_total_cnt = get_unaligned_le16(&pSMBs->t2_rsp.TotalDataCount);
- tgt_total_cnt = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
-
- if (tgt_total_cnt != src_total_cnt)
- cifs_dbg(FYI, "total data count of primary and secondary t2 differ source=%hu target=%hu\n",
- src_total_cnt, tgt_total_cnt);
-
- total_in_tgt = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
-
- remaining = tgt_total_cnt - total_in_tgt;
-
- if (remaining < 0) {
- cifs_dbg(FYI, "Server sent too much data. tgt_total_cnt=%hu total_in_tgt=%u\n",
- tgt_total_cnt, total_in_tgt);
- return -EPROTO;
- }
-
- if (remaining == 0) {
- /* nothing to do, ignore */
- cifs_dbg(FYI, "no more data remains\n");
- return 0;
- }
-
- total_in_src = get_unaligned_le16(&pSMBs->t2_rsp.DataCount);
- if (remaining < total_in_src)
- cifs_dbg(FYI, "transact2 2nd response contains too much data\n");
-
- /* find end of first SMB data area */
- data_area_of_tgt = (char *)&pSMBt->hdr.Protocol +
- get_unaligned_le16(&pSMBt->t2_rsp.DataOffset);
-
- /* validate target area */
- data_area_of_src = (char *)&pSMBs->hdr.Protocol +
- get_unaligned_le16(&pSMBs->t2_rsp.DataOffset);
-
- data_area_of_tgt += total_in_tgt;
-
- total_in_tgt += total_in_src;
- /* is the result too big for the field? */
- if (total_in_tgt > USHRT_MAX) {
- cifs_dbg(FYI, "coalesced DataCount too large (%u)\n",
- total_in_tgt);
- return -EPROTO;
- }
- put_unaligned_le16(total_in_tgt, &pSMBt->t2_rsp.DataCount);
-
- /* fix up the BCC */
- byte_count = get_bcc(target_hdr);
- byte_count += total_in_src;
- /* is the result too big for the field? */
- if (byte_count > USHRT_MAX) {
- cifs_dbg(FYI, "coalesced BCC too large (%u)\n", byte_count);
- return -EPROTO;
- }
- put_bcc(byte_count, target_hdr);
-
- byte_count = *pdu_len;
- byte_count += total_in_src;
- /* don't allow buffer to overflow */
- if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
- cifs_dbg(FYI, "coalesced BCC exceeds buffer size (%u)\n",
- byte_count);
- return -ENOBUFS;
- }
- *pdu_len = byte_count;
-
- /* copy second buffer into end of first buffer */
- memcpy(data_area_of_tgt, data_area_of_src, total_in_src);
-
- if (remaining != total_in_src) {
- /* more responses to go */
- cifs_dbg(FYI, "waiting for more secondary responses\n");
- return 1;
- }
-
- /* we are done */
- cifs_dbg(FYI, "found the last secondary response\n");
- return 0;
-}
-
static void
cifs_downgrade_oplock(struct TCP_Server_Info *server,
struct cifsInodeInfo *cinode, __u32 oplock,
@@ -432,37 +292,6 @@ cifs_downgrade_oplock(struct TCP_Server_Info *server,
cifs_set_oplock_level(cinode, oplock);
}
-static 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)
- return false;
- mid->multiRsp = true;
- if (mid->resp_buf) {
- /* merge response - fix up 1st*/
- malformed = coalesce_t2(buf, mid->resp_buf, &mid->response_pdu_len);
- if (malformed > 0)
- return true;
- /* All parts received or packet is malformed. */
- mid->multiEnd = true;
- dequeue_mid(server, mid, malformed);
- return true;
- }
- if (!server->large_buf) {
- /*FIXME: switch to already allocated largebuf?*/
- cifs_dbg(VFS, "1st trans2 resp needs bigbuf\n");
- } else {
- /* Have first buffer */
- mid->resp_buf = buf;
- mid->large_buf = true;
- server->bigbuf = NULL;
- }
- return true;
-}
-
static bool
cifs_need_neg(struct TCP_Server_Info *server)
{
diff --git a/fs/smb/client/smb1proto.h b/fs/smb/client/smb1proto.h
index 1fd4fd0bbb7a..bf24974fbb00 100644
--- a/fs/smb/client/smb1proto.h
+++ b/fs/smb/client/smb1proto.h
@@ -233,6 +233,8 @@ int SendReceive(const unsigned int xid, struct cifs_ses *ses,
struct smb_hdr *in_buf, unsigned int in_len,
struct smb_hdr *out_buf, int *pbytes_returned,
const int flags);
+bool cifs_check_trans2(struct mid_q_entry *mid, struct TCP_Server_Info *server,
+ char *buf, int malformed);
#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
diff --git a/fs/smb/client/smb1transport.c b/fs/smb/client/smb1transport.c
index 28d1cee90625..5f95bffc8e44 100644
--- a/fs/smb/client/smb1transport.c
+++ b/fs/smb/client/smb1transport.c
@@ -261,3 +261,174 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
free_rsp_buf(resp_buf_type, resp_iov.iov_base);
return rc;
}
+
+/*
+ return codes:
+ 0 not a transact2, or all data present
+ >0 transact2 with that much data missing
+ -EINVAL invalid transact2
+ */
+static int
+check2ndT2(char *buf)
+{
+ struct smb_hdr *pSMB = (struct smb_hdr *)buf;
+ struct smb_t2_rsp *pSMBt;
+ int remaining;
+ __u16 total_data_size, data_in_this_rsp;
+
+ if (pSMB->Command != SMB_COM_TRANSACTION2)
+ return 0;
+
+ /* check for plausible wct, bcc and t2 data and parm sizes */
+ /* check for parm and data offset going beyond end of smb */
+ if (pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
+ cifs_dbg(FYI, "Invalid transact2 word count\n");
+ return -EINVAL;
+ }
+
+ pSMBt = (struct smb_t2_rsp *)pSMB;
+
+ total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
+ data_in_this_rsp = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
+
+ if (total_data_size == data_in_this_rsp)
+ return 0;
+ else if (total_data_size < data_in_this_rsp) {
+ cifs_dbg(FYI, "total data %d smaller than data in frame %d\n",
+ total_data_size, data_in_this_rsp);
+ return -EINVAL;
+ }
+
+ remaining = total_data_size - data_in_this_rsp;
+
+ cifs_dbg(FYI, "missing %d bytes from transact2, check next response\n",
+ remaining);
+ if (total_data_size > CIFSMaxBufSize) {
+ cifs_dbg(VFS, "TotalDataSize %d is over maximum buffer %d\n",
+ total_data_size, CIFSMaxBufSize);
+ return -EINVAL;
+ }
+ return remaining;
+}
+
+static int
+coalesce_t2(char *second_buf, struct smb_hdr *target_hdr, unsigned int *pdu_len)
+{
+ struct smb_t2_rsp *pSMBs = (struct smb_t2_rsp *)second_buf;
+ struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)target_hdr;
+ char *data_area_of_tgt;
+ char *data_area_of_src;
+ int remaining;
+ unsigned int byte_count, total_in_tgt;
+ __u16 tgt_total_cnt, src_total_cnt, total_in_src;
+
+ src_total_cnt = get_unaligned_le16(&pSMBs->t2_rsp.TotalDataCount);
+ tgt_total_cnt = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
+
+ if (tgt_total_cnt != src_total_cnt)
+ cifs_dbg(FYI, "total data count of primary and secondary t2 differ source=%hu target=%hu\n",
+ src_total_cnt, tgt_total_cnt);
+
+ total_in_tgt = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
+
+ remaining = tgt_total_cnt - total_in_tgt;
+
+ if (remaining < 0) {
+ cifs_dbg(FYI, "Server sent too much data. tgt_total_cnt=%hu total_in_tgt=%u\n",
+ tgt_total_cnt, total_in_tgt);
+ return -EPROTO;
+ }
+
+ if (remaining == 0) {
+ /* nothing to do, ignore */
+ cifs_dbg(FYI, "no more data remains\n");
+ return 0;
+ }
+
+ total_in_src = get_unaligned_le16(&pSMBs->t2_rsp.DataCount);
+ if (remaining < total_in_src)
+ cifs_dbg(FYI, "transact2 2nd response contains too much data\n");
+
+ /* find end of first SMB data area */
+ data_area_of_tgt = (char *)&pSMBt->hdr.Protocol +
+ get_unaligned_le16(&pSMBt->t2_rsp.DataOffset);
+
+ /* validate target area */
+ data_area_of_src = (char *)&pSMBs->hdr.Protocol +
+ get_unaligned_le16(&pSMBs->t2_rsp.DataOffset);
+
+ data_area_of_tgt += total_in_tgt;
+
+ total_in_tgt += total_in_src;
+ /* is the result too big for the field? */
+ if (total_in_tgt > USHRT_MAX) {
+ cifs_dbg(FYI, "coalesced DataCount too large (%u)\n",
+ total_in_tgt);
+ return -EPROTO;
+ }
+ put_unaligned_le16(total_in_tgt, &pSMBt->t2_rsp.DataCount);
+
+ /* fix up the BCC */
+ byte_count = get_bcc(target_hdr);
+ byte_count += total_in_src;
+ /* is the result too big for the field? */
+ if (byte_count > USHRT_MAX) {
+ cifs_dbg(FYI, "coalesced BCC too large (%u)\n", byte_count);
+ return -EPROTO;
+ }
+ put_bcc(byte_count, target_hdr);
+
+ byte_count = *pdu_len;
+ byte_count += total_in_src;
+ /* don't allow buffer to overflow */
+ if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
+ cifs_dbg(FYI, "coalesced BCC exceeds buffer size (%u)\n",
+ byte_count);
+ return -ENOBUFS;
+ }
+ *pdu_len = byte_count;
+
+ /* copy second buffer into end of first buffer */
+ memcpy(data_area_of_tgt, data_area_of_src, total_in_src);
+
+ if (remaining != total_in_src) {
+ /* more responses to go */
+ cifs_dbg(FYI, "waiting for more secondary responses\n");
+ return 1;
+ }
+
+ /* we are done */
+ cifs_dbg(FYI, "found the last secondary response\n");
+ return 0;
+}
+
+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)
+ return false;
+ mid->multiRsp = true;
+ if (mid->resp_buf) {
+ /* merge response - fix up 1st*/
+ malformed = coalesce_t2(buf, mid->resp_buf, &mid->response_pdu_len);
+ if (malformed > 0)
+ return true;
+ /* All parts received or packet is malformed. */
+ mid->multiEnd = true;
+ dequeue_mid(server, mid, malformed);
+ return true;
+ }
+ if (!server->large_buf) {
+ /*FIXME: switch to already allocated largebuf?*/
+ cifs_dbg(VFS, "1st trans2 resp needs bigbuf\n");
+ } else {
+ /* Have first buffer */
+ mid->resp_buf = buf;
+ mid->large_buf = true;
+ server->bigbuf = NULL;
+ }
+ return true;
+}
next prev 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 ` David Howells [this message]
2025-12-22 22:29 ` [PATCH 23/37] cifs: SMB1 split: Move some SMB1 received PDU checking bits to smb1transport.c David Howells
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-23-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