Skip to content

Commit 09ee7a3

Browse files
author
Steve French
committed
[SMB3] send channel sequence number in SMB3 requests after reconnects
The ChannelSequence field in the SMB3 header is supposed to be increased after reconnect to allow the server to distinguish requests from before and after the reconnect. We had always been setting it to zero. There are cases where incrementing ChannelSequence on requests after network reconnects can reduce the chance of data corruptions. See MS-SMB2 3.2.4.1 and 3.2.7.1 Signed-off-by: Steve French <[email protected]> Cc: [email protected] # 5.16+
1 parent b6d44d4 commit 09ee7a3

File tree

5 files changed

+45
-1
lines changed

5 files changed

+45
-1
lines changed

fs/smb/client/cifsglob.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,7 @@ struct TCP_Server_Info {
747747
*/
748748
#define CIFS_SERVER_IS_CHAN(server) (!!(server)->primary_server)
749749
struct TCP_Server_Info *primary_server;
750+
__u16 channel_sequence_num; /* incremented on primary channel on each chan reconnect */
750751

751752
#ifdef CONFIG_CIFS_SWN_UPCALL
752753
bool use_swn_dstaddr;

fs/smb/client/connect.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1686,6 +1686,7 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx,
16861686
ctx->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
16871687
tcp_ses->session_estab = false;
16881688
tcp_ses->sequence_number = 0;
1689+
tcp_ses->channel_sequence_num = 0; /* only tracked for primary channel */
16891690
tcp_ses->reconnect_instance = 1;
16901691
tcp_ses->lstrp = jiffies;
16911692
tcp_ses->compress_algorithm = cpu_to_le16(ctx->compression);

fs/smb/client/smb2ops.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,17 @@ smb2_set_credits(struct TCP_Server_Info *server, const int val)
172172

173173
spin_lock(&server->req_lock);
174174
server->credits = val;
175-
if (val == 1)
175+
if (val == 1) {
176176
server->reconnect_instance++;
177+
/*
178+
* ChannelSequence updated for all channels in primary channel so that consistent
179+
* across SMB3 requests sent on any channel. See MS-SMB2 3.2.4.1 and 3.2.7.1
180+
*/
181+
if (CIFS_SERVER_IS_CHAN(server))
182+
server->primary_server->channel_sequence_num++;
183+
else
184+
server->channel_sequence_num++;
185+
}
177186
scredits = server->credits;
178187
in_flight = server->in_flight;
179188
spin_unlock(&server->req_lock);

fs/smb/client/smb2pdu.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,20 @@ smb2_hdr_assemble(struct smb2_hdr *shdr, __le16 smb2_cmd,
8888
const struct cifs_tcon *tcon,
8989
struct TCP_Server_Info *server)
9090
{
91+
struct smb3_hdr_req *smb3_hdr;
9192
shdr->ProtocolId = SMB2_PROTO_NUMBER;
9293
shdr->StructureSize = cpu_to_le16(64);
9394
shdr->Command = smb2_cmd;
95+
if (server->dialect >= SMB30_PROT_ID) {
96+
/* After reconnect SMB3 must set ChannelSequence on subsequent reqs */
97+
smb3_hdr = (struct smb3_hdr_req *)shdr;
98+
/* if primary channel is not set yet, use default channel for chan sequence num */
99+
if (CIFS_SERVER_IS_CHAN(server))
100+
smb3_hdr->ChannelSequence =
101+
cpu_to_le16(server->primary_server->channel_sequence_num);
102+
else
103+
smb3_hdr->ChannelSequence = cpu_to_le16(server->channel_sequence_num);
104+
}
94105
if (server) {
95106
spin_lock(&server->req_lock);
96107
/* Request up to 10 credits but don't go over the limit. */

fs/smb/common/smb2pdu.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,28 @@ struct smb2_hdr {
153153
__u8 Signature[16];
154154
} __packed;
155155

156+
struct smb3_hdr_req {
157+
__le32 ProtocolId; /* 0xFE 'S' 'M' 'B' */
158+
__le16 StructureSize; /* 64 */
159+
__le16 CreditCharge; /* MBZ */
160+
__le16 ChannelSequence; /* See MS-SMB2 3.2.4.1 and 3.2.7.1 */
161+
__le16 Reserved;
162+
__le16 Command;
163+
__le16 CreditRequest; /* CreditResponse */
164+
__le32 Flags;
165+
__le32 NextCommand;
166+
__le64 MessageId;
167+
union {
168+
struct {
169+
__le32 ProcessId;
170+
__le32 TreeId;
171+
} __packed SyncId;
172+
__le64 AsyncId;
173+
} __packed Id;
174+
__le64 SessionId;
175+
__u8 Signature[16];
176+
} __packed;
177+
156178
struct smb2_pdu {
157179
struct smb2_hdr hdr;
158180
__le16 StructureSize2; /* size of wct area (varies, request specific) */

0 commit comments

Comments
 (0)