Re: [PATCH] cifs: implementation id context as negotiate context

Shyam Prasad N
2026-03-11T23:52:39Z

On Mon, Mar 9, 2026 at 11:29 PM Enzo Matsumiya <ematsumiya@suse.de> wrote:
>
> On 03/09, Shyam Prasad N wrote:
> >On Mon, Mar 9, 2026 at 9:49 PM Ralph Boehme <slow@samba.org> wrote:
> >>
> >> Hi!
> >>
> >> I wonder which servers are expected to be implementing this? I suppose
> >> this protocol extension is not proposed without a server vendor
> >> interested in actually implementing it, otherwise the whole metrics
> >> story doesn't make sense.
> >
> >Hi Ralph,
> >
> >This is supposed to give the server an idea of what version of cifs.ko
> >the client is actually running.
>
> I agree with others on this point -- cifs.ko version is useless to match
> to a particular behaviour or pinpoint a specific bug.

Acked. Can you suggest an alternative field that will make the matching easier?

>
> >This can be useful for servers like Azure SMB servers, where it is not
> >easy to explain client side behaviour without knowing what exact
> >version of the code is running on the client.
>
> If the proposal is going to be bidirectional, it would be much better,
> for cifs.ko, to have servers sending such information to clients
> instead; even when there's a problem on the server, it'll usually
> reflect on the client (crashes, misbehaviour, etc).
>
> Also useful for cases where customers don't have direct/easy access to
> their SMB infrastructure (e.g. external/3rd party hosting, or 1000s of
> servers mixed with DFS and/or clusters).

Good point. Let me rework the draft on this.

>
>
> Cheers,
>
> Enzo
>
> >> *scratches head*
> >>
> >> Thanks!
> >> -slow
> >>
> >> On 3/4/26 1:27 PM, nspmangalore@gmail.com wrote:
> >> > From: Shyam Prasad N <sprasad@microsoft.com>
> >> >
> >> > MS-SMB2 does not allow any fields for the client to communicate
> >> > the client version details to the server. This change is a
> >> > proof-of-concept to add client details in a new negotiate context.
> >> >
> >> > Signed-off-by: Shyam Prasad N <sprasad@microsoft.com>
> >> > ---
> >> > fs/smb/client/smb2pdu.c | 78 +++++++++++++++++++++++++++++++++++++++++
> >> > fs/smb/common/smb2pdu.h | 32 +++++++++++++++++
> >> > 2 files changed, 110 insertions(+)
> >> >
> >> > diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
> >> > index ef655acf673df..9c89f6b4a6709 100644
> >> > --- a/fs/smb/client/smb2pdu.c
> >> > +++ b/fs/smb/client/smb2pdu.c
> >> > @@ -24,6 +24,7 @@
> >> > #include <linux/pagemap.h>
> >> > #include <linux/xattr.h>
> >> > #include <linux/netfs.h>
> >> > +#include <linux/utsname.h>
> >> > #include <trace/events/netfs.h>
> >> > #include "cifsglob.h"
> >> > #include "cifsproto.h"
> >> > @@ -45,6 +46,7 @@
> >> > #include "cached_dir.h"
> >> > #include "compress.h"
> >> > #include "fs_context.h"
> >> > +#include "cifsfs.h"
> >> >
> >> > /*
> >> > * The following table defines the expected "StructureSize" of SMB2 requests
> >> > @@ -724,6 +726,75 @@ build_posix_ctxt(struct smb2_posix_neg_context *pneg_ctxt)
> >> > pneg_ctxt->Name[15] = 0x7C;
> >> > }
> >> >
> >> > +static unsigned int
> >> > +build_implementation_id_ctxt(struct smb2_implementation_id_context *pneg_ctxt)
> >> > +{
> >> > + struct nls_table *cp = load_nls_default();
> >> > + struct new_utsname *uts = utsname();
> >> > + const char *impl_domain = "kernel.org";
> >> > + const char *impl_name = "fs/smb/client";
> >> > + const char *os_name = "Linux";
> >> > + unsigned int data_len = 0;
> >> > + __u8 *data_ptr;
> >> > + int len;
> >> > +
> >> > + pneg_ctxt->ContextType = SMB2_IMPLEMENTATION_ID_CONTEXT_ID;
> >> > + data_ptr = pneg_ctxt->Data;
> >> > +
> >> > + /* ImplDomain */
> >> > + len = cifs_strtoUTF16((__le16 *)data_ptr, impl_domain,
> >> > + SMB2_IMPL_ID_MAX_DOMAIN_LEN, cp);
> >> > + pneg_ctxt->ImplDomainLength = cpu_to_le16(len * 2);
> >> > + data_ptr += len * 2;
> >> > + data_len += len * 2;
> >> > +
> >> > + /* ImplName */
> >> > + len = cifs_strtoUTF16((__le16 *)data_ptr, impl_name,
> >> > + SMB2_IMPL_ID_MAX_NAME_LEN, cp);
> >> > + pneg_ctxt->ImplNameLength = cpu_to_le16(len * 2);
> >> > + data_ptr += len * 2;
> >> > + data_len += len * 2;
> >> > +
> >> > + /* ImplVersion - CIFS_VERSION from cifsfs.h */
> >> > + len = cifs_strtoUTF16((__le16 *)data_ptr, CIFS_VERSION,
> >> > + SMB2_IMPL_ID_MAX_VERSION_LEN, cp);
> >> > + pneg_ctxt->ImplVersionLength = cpu_to_le16(len * 2);
> >> > + data_ptr += len * 2;
> >> > + data_len += len * 2;
> >> > +
> >> > + /* HostName - from utsname()->nodename */
> >> > + len = cifs_strtoUTF16((__le16 *)data_ptr, uts->nodename,
> >> > + SMB2_IMPL_ID_MAX_HOSTNAME_LEN, cp);
> >> > + pneg_ctxt->HostNameLength = cpu_to_le16(len * 2);
> >> > + data_ptr += len * 2;
> >> > + data_len += len * 2;
> >> > +
> >> > + /* OSName */
> >> > + len = cifs_strtoUTF16((__le16 *)data_ptr, os_name,
> >> > + SMB2_IMPL_ID_MAX_OS_NAME_LEN, cp);
> >> > + pneg_ctxt->OSNameLength = cpu_to_le16(len * 2);
> >> > + data_ptr += len * 2;
> >> > + data_len += len * 2;
> >> > +
> >> > + /* OSVersion - from utsname()->release */
> >> > + len = cifs_strtoUTF16((__le16 *)data_ptr, uts->release,
> >> > + SMB2_IMPL_ID_MAX_OS_VERSION_LEN, cp);
> >> > + pneg_ctxt->OSVersionLength = cpu_to_le16(len * 2);
> >> > + data_ptr += len * 2;
> >> > + data_len += len * 2;
> >> > +
> >> > + /* Arch - from utsname()->machine */
> >> > + len = cifs_strtoUTF16((__le16 *)data_ptr, uts->machine,
> >> > + SMB2_IMPL_ID_MAX_ARCH_LEN, cp);
> >> > + pneg_ctxt->ArchLength = cpu_to_le16(len * 2);
> >> > + data_len += len * 2;
> >> > +
> >> > + pneg_ctxt->Reserved2 = 0;
> >> > + pneg_ctxt->DataLength = cpu_to_le16(data_len + 14); /* 14 = 7 length fields * 2 bytes */
> >> > + /* Context size is DataLength + minimal smb2_neg_context, aligned to 8 */
> >> > + return ALIGN(le16_to_cpu(pneg_ctxt->DataLength) + sizeof(struct smb2_neg_context), 8);
> >> > +}
> >> > +
> >> > static void
> >> > assemble_neg_contexts(struct smb2_negotiate_req *req,
> >> > struct TCP_Server_Info *server, unsigned int *total_len)
> >> > @@ -797,6 +868,13 @@ assemble_neg_contexts(struct smb2_negotiate_req *req,
> >> > neg_context_count++;
> >> > }
> >> >
> >> > + /* Add implementation ID context */
> >> > + ctxt_len = build_implementation_id_ctxt((struct smb2_implementation_id_context *)
> >> > + pneg_ctxt);
> >> > + *total_len += ctxt_len;
> >> > + pneg_ctxt += ctxt_len;
> >> > + neg_context_count++;
> >> > +
> >> > /* check for and add transport_capabilities and signing capabilities */
> >> > req->NegotiateContextCount = cpu_to_le16(neg_context_count);
> >> >
> >> > diff --git a/fs/smb/common/smb2pdu.h b/fs/smb/common/smb2pdu.h
> >> > index e482c86ceb00d..1ad7b57ce2952 100644
> >> > --- a/fs/smb/common/smb2pdu.h
> >> > +++ b/fs/smb/common/smb2pdu.h
> >> > @@ -457,6 +457,7 @@ struct smb2_tree_disconnect_rsp {
> >> > #define SMB2_TRANSPORT_CAPABILITIES cpu_to_le16(6)
> >> > #define SMB2_RDMA_TRANSFORM_CAPABILITIES cpu_to_le16(7)
> >> > #define SMB2_SIGNING_CAPABILITIES cpu_to_le16(8)
> >> > +#define SMB2_IMPLEMENTATION_ID_CONTEXT_ID cpu_to_le16(0xF100)
> >> > #define SMB2_POSIX_EXTENSIONS_AVAILABLE cpu_to_le16(0x100)
> >> >
> >> > struct smb2_neg_context {
> >> > @@ -596,6 +597,37 @@ struct smb2_signing_capabilities {
> >> > /* Followed by padding to 8 byte boundary (required by some servers) */
> >> > } __packed;
> >> >
> >> > +/*
> >> > + * For implementation ID context see MS-SMB2 2.2.3.1.8
> >> > + * Maximum string lengths per specification
> >> > + */
> >> > +#define SMB2_IMPL_ID_MAX_DOMAIN_LEN 128
> >> > +#define SMB2_IMPL_ID_MAX_NAME_LEN 260
> >> > +#define SMB2_IMPL_ID_MAX_VERSION_LEN 260
> >> > +#define SMB2_IMPL_ID_MAX_HOSTNAME_LEN 64
> >> > +#define SMB2_IMPL_ID_MAX_OS_NAME_LEN 64
> >> > +#define SMB2_IMPL_ID_MAX_OS_VERSION_LEN 64
> >> > +#define SMB2_IMPL_ID_MAX_ARCH_LEN 64
> >> > +
> >> > +struct smb2_implementation_id_context {
> >> > + __le16 ContextType; /* 9 */
> >> > + __le16 DataLength;
> >> > + __le32 Reserved;
> >> > + __le16 ImplDomainLength;
> >> > + __le16 ImplNameLength;
> >> > + __le16 ImplVersionLength;
> >> > + __le16 HostNameLength;
> >> > + __le16 OSNameLength;
> >> > + __le16 OSVersionLength;
> >> > + __le16 ArchLength;
> >> > + __le16 Reserved2;
> >> > + /* Followed by variable length UTF-16 strings:
> >> > + * ImplDomain, ImplName, ImplVersion, HostName,
> >> > + * OSName, OSVersion, Arch
> >> > + */
> >> > + __u8 Data[];
> >> > +} __packed;
> >> > +
> >> > #define POSIX_CTXT_DATA_LEN 16
> >> > struct smb2_posix_neg_context {
> >> > __le16 ContextType; /* 0x100 */
> >>
> >
> >
> >--
> >Regards,
> >Shyam
> >

--
Regards,
Shyam