1) we were not setting CAP_MULTICHANNEL on negotiate request 2) we were ignoring whether the server set CAP_NEGOTIATE in the response 3) we were silently ignoring multichannel when "max_channels" was > 1 but the user forgot to include "multichannel" in mount line. -- Thanks, Steve
From 16fcf9422d70cb28056518b30c377fe88a7ad7b9 Mon Sep 17 00:00:00 2001 From: Steve French <stfrench@xxxxxxxxxxxxx> Date: Fri, 7 May 2021 19:33:51 -0500 Subject: [PATCH 2/4] smb3: if max_channels set to more than one channel request multichannel Mounting with "multichannel" is obviously implied if user requested more than one channel on mount (ie mount parm max_channels>1). Currently both have to be specified. Fix that so that if max_channels is greater than 1 on mount, enable multichannel rather than silently falling back to non-multichannel. Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx> --- fs/cifs/fs_context.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/cifs/fs_context.c b/fs/cifs/fs_context.c index 3bcf881c3ae9..8f7af6fcdc76 100644 --- a/fs/cifs/fs_context.c +++ b/fs/cifs/fs_context.c @@ -1021,6 +1021,9 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, goto cifs_parse_mount_err; } ctx->max_channels = result.uint_32; + /* If more than one channel requested ... they want multichan */ + if ((ctx->multichannel == false) && (result.uint_32 > 1)) + ctx->multichannel = true; break; case Opt_handletimeout: ctx->handle_timeout = result.uint_32; -- 2.27.0
From 9984843c7cb5be498c3fea50e9fa016dc44424ef Mon Sep 17 00:00:00 2001 From: Steve French <stfrench@xxxxxxxxxxxxx> Date: Fri, 7 May 2021 20:00:41 -0500 Subject: [PATCH 3/4] smb3: do not attempt multichannel to server which does not support it We were ignoring CAP_MULTI_CHANNEL in the server response - if the server doesn't support multichannel we should not be attempting it. See MS-SMB2 section 3.2.5.2 Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx> --- fs/cifs/sess.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 63d517b9f2ff..a391ca3166f3 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -97,6 +97,12 @@ int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses) return 0; } + if ((ses->server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL) == false) { + cifs_dbg(VFS, "server does not support CAP_MULTI_CHANNEL, multichannel disabled\n"); + ses->chan_max = 1; + return 0; + } + /* * Make a copy of the iface list at the time and use that * instead so as to not hold the iface spinlock for opening -- 2.27.0
From a2bdd5ceb7090ea4f3ee091da2418f23d270b391 Mon Sep 17 00:00:00 2001 From: Steve French <stfrench@xxxxxxxxxxxxx> Date: Fri, 7 May 2021 18:24:11 -0500 Subject: [PATCH 1/4] smb3: when mounting with multichannel include it in requested capabilities In the SMB3/SMB3.1.1 negotiate protocol request, we are supposed to advertise CAP_MULTICHANNEL capability when establishing multiple channels has been requested by the user doing the mount. See MS-SMB2 sections 2.2.3 and 3.2.5.2 Without setting it there is some risk that multichannel could fail if the server interpreted the field strictly. Cc: <stable@xxxxxxxxxxxxxxx> # v5.8+ Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx> --- fs/cifs/smb2pdu.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index e36c2a867783..a8bf43184773 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -841,6 +841,8 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) req->SecurityMode = 0; req->Capabilities = cpu_to_le32(server->vals->req_capabilities); + if (ses->chan_max > 1) + req->Capabilities |= cpu_to_le32(SMB2_GLOBAL_CAP_MULTI_CHANNEL); /* ClientGUID must be zero for SMB2.02 dialect */ if (server->vals->protocol_id == SMB20_PROT_ID) @@ -1032,6 +1034,9 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) pneg_inbuf->Capabilities = cpu_to_le32(server->vals->req_capabilities); + if (tcon->ses->chan_max > 1) + pneg_inbuf->Capabilities |= cpu_to_le32(SMB2_GLOBAL_CAP_MULTI_CHANNEL); + memcpy(pneg_inbuf->Guid, server->client_guid, SMB2_CLIENT_GUID_SIZE); -- 2.27.0