to get it to build I had to fix a couple lines (get_neg_ctxt_len) and merged in with your patch 1- see attached On Tue, May 29, 2018 at 7:47 PM, Ronnie Sahlberg <lsahlber@xxxxxxxxxx> wrote: > Signed-off-by: Ronnie Sahlberg <lsahlber@xxxxxxxxxx> > --- > fs/cifs/smb2misc.c | 43 ++++++++++++++++--------------------------- > 1 file changed, 16 insertions(+), 27 deletions(-) > > diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c > index f7f3ad760401..0a12c2133770 100644 > --- a/fs/cifs/smb2misc.c > +++ b/fs/cifs/smb2misc.c > @@ -131,25 +131,20 @@ static __u32 get_neg_ctxt_len(struct smb2_hdr *hdr, __u32 len, __u32 non_ctxlen, > #endif /* CIFS_SMB311 */ > > int > -smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) > +smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr) > { > - struct smb2_pdu *pdu = (struct smb2_pdu *)buf; > - struct smb2_hdr *hdr = &pdu->hdr; > - struct smb2_sync_hdr *shdr = get_sync_hdr(buf); > + struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)(buf + srvr->vals->header_preamble_size); > + struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)shdr; > __u64 mid; > - __u32 len = get_rfc1002_length(buf); > __u32 clc_len; /* calculated length */ > int command; > - > - /* BB disable following printk later */ > - cifs_dbg(FYI, "%s length: 0x%x, smb_buf_length: 0x%x\n", > - __func__, length, len); > + int pdu_size = sizeof(struct smb2_sync_pdu); > + int hdr_size = sizeof(struct smb2_sync_hdr); > > /* > * Add function to do table lookup of StructureSize by command > * ie Validate the wct via smb2_struct_sizes table above > */ > - > if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) { > struct smb2_transform_hdr *thdr = > (struct smb2_transform_hdr *)buf; > @@ -173,8 +168,8 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) > } > > mid = le64_to_cpu(shdr->MessageId); > - if (length < sizeof(struct smb2_pdu)) { > - if ((length >= sizeof(struct smb2_hdr)) > + if (len < pdu_size) { > + if ((len >= hdr_size) > && (shdr->Status != 0)) { > pdu->StructureSize2 = 0; > /* > @@ -227,31 +222,25 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) > } > } > > - if (srvr->vals->header_preamble_size + len != length) { > - cifs_dbg(VFS, "Total length %u RFC1002 length %zu mismatch mid %llu\n", > - length, srvr->vals->header_preamble_size + len, mid); > - return 1; > - } > - > - clc_len = smb2_calc_size(hdr, srvr); > + clc_len = smb2_calc_size(buf, srvr); > > #ifdef CONFIG_CIFS_SMB311 > if (shdr->Command == SMB2_NEGOTIATE) > clc_len += get_neg_ctxt_len(hdr, len, clc_len, > srvr->vals->header_preamble_size); > #endif /* SMB311 */ > - if (srvr->vals->header_preamble_size + len != clc_len) { > - cifs_dbg(FYI, "Calculated size %u length %zu mismatch mid %llu\n", > - clc_len, srvr->vals->header_preamble_size + len, mid); > + if (len != clc_len) { > + cifs_dbg(FYI, "Calculated size %u length %u mismatch mid %llu\n", > + clc_len, len, mid); > /* create failed on symlink */ > if (command == SMB2_CREATE_HE && > shdr->Status == STATUS_STOPPED_ON_SYMLINK) > return 0; > /* Windows 7 server returns 24 bytes more */ > - if (clc_len + 24 - srvr->vals->header_preamble_size == len && command == SMB2_OPLOCK_BREAK_HE) > + if (clc_len + 24 == len && command == SMB2_OPLOCK_BREAK_HE) > return 0; > /* server can return one byte more due to implied bcc[0] */ > - if (clc_len == srvr->vals->header_preamble_size + len + 1) > + if (clc_len == len + 1) > return 0; > > /* > @@ -261,10 +250,10 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) > * Log the server error (once), but allow it and continue > * since the frame is parseable. > */ > - if (clc_len < srvr->vals->header_preamble_size /* RFC1001 header size */ + len) { > + if (clc_len < len) { > printk_once(KERN_WARNING > - "SMB2 server sent bad RFC1001 len %d not %zu\n", > - len, clc_len - srvr->vals->header_preamble_size); > + "SMB2 server sent bad RFC1001 len %d not %u\n", > + len, clc_len); > return 0; > } > > -- > 2.13.3 > -- Thanks, Steve
From 5b540f13736fe4f7e11fd7d2ab27ae29b91c8ad0 Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg <lsahlber@xxxxxxxxxx> Date: Wed, 30 May 2018 10:47:01 +1000 Subject: [PATCH 1/2] cifs: update smb2_check_message to handle PDUs without a 4 byte length header Signed-off-by: Ronnie Sahlberg <lsahlber@xxxxxxxxxx> Signed-off-by: Steve French <smfrench@xxxxxxxxx> --- fs/cifs/smb2misc.c | 49 ++++++++++++++++++---------------------------- 1 file changed, 19 insertions(+), 30 deletions(-) diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c index f7f3ad760401..ba1a20cf9846 100644 --- a/fs/cifs/smb2misc.c +++ b/fs/cifs/smb2misc.c @@ -94,8 +94,8 @@ static const __le16 smb2_rsp_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = { }; #ifdef CONFIG_CIFS_SMB311 -static __u32 get_neg_ctxt_len(struct smb2_hdr *hdr, __u32 len, __u32 non_ctxlen, - size_t hdr_preamble_size) +static __u32 get_neg_ctxt_len(struct smb2_sync_hdr *hdr, __u32 len, + __u32 non_ctxlen, size_t hdr_preamble_size) { __u16 neg_count; __u32 nc_offset, size_of_pad_before_neg_ctxts; @@ -131,25 +131,20 @@ static __u32 get_neg_ctxt_len(struct smb2_hdr *hdr, __u32 len, __u32 non_ctxlen, #endif /* CIFS_SMB311 */ int -smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) +smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr) { - struct smb2_pdu *pdu = (struct smb2_pdu *)buf; - struct smb2_hdr *hdr = &pdu->hdr; - struct smb2_sync_hdr *shdr = get_sync_hdr(buf); + struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)(buf + srvr->vals->header_preamble_size); + struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)shdr; __u64 mid; - __u32 len = get_rfc1002_length(buf); __u32 clc_len; /* calculated length */ int command; - - /* BB disable following printk later */ - cifs_dbg(FYI, "%s length: 0x%x, smb_buf_length: 0x%x\n", - __func__, length, len); + int pdu_size = sizeof(struct smb2_sync_pdu); + int hdr_size = sizeof(struct smb2_sync_hdr); /* * Add function to do table lookup of StructureSize by command * ie Validate the wct via smb2_struct_sizes table above */ - if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) { struct smb2_transform_hdr *thdr = (struct smb2_transform_hdr *)buf; @@ -173,8 +168,8 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) } mid = le64_to_cpu(shdr->MessageId); - if (length < sizeof(struct smb2_pdu)) { - if ((length >= sizeof(struct smb2_hdr)) + if (len < pdu_size) { + if ((len >= hdr_size) && (shdr->Status != 0)) { pdu->StructureSize2 = 0; /* @@ -227,31 +222,25 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) } } - if (srvr->vals->header_preamble_size + len != length) { - cifs_dbg(VFS, "Total length %u RFC1002 length %zu mismatch mid %llu\n", - length, srvr->vals->header_preamble_size + len, mid); - return 1; - } - - clc_len = smb2_calc_size(hdr, srvr); + clc_len = smb2_calc_size(buf, srvr); #ifdef CONFIG_CIFS_SMB311 if (shdr->Command == SMB2_NEGOTIATE) - clc_len += get_neg_ctxt_len(hdr, len, clc_len, + clc_len += get_neg_ctxt_len(shdr, len, clc_len, srvr->vals->header_preamble_size); #endif /* SMB311 */ - if (srvr->vals->header_preamble_size + len != clc_len) { - cifs_dbg(FYI, "Calculated size %u length %zu mismatch mid %llu\n", - clc_len, srvr->vals->header_preamble_size + len, mid); + if (len != clc_len) { + cifs_dbg(FYI, "Calculated size %u length %u mismatch mid %llu\n", + clc_len, len, mid); /* create failed on symlink */ if (command == SMB2_CREATE_HE && shdr->Status == STATUS_STOPPED_ON_SYMLINK) return 0; /* Windows 7 server returns 24 bytes more */ - if (clc_len + 24 - srvr->vals->header_preamble_size == len && command == SMB2_OPLOCK_BREAK_HE) + if (clc_len + 24 == len && command == SMB2_OPLOCK_BREAK_HE) return 0; /* server can return one byte more due to implied bcc[0] */ - if (clc_len == srvr->vals->header_preamble_size + len + 1) + if (clc_len == len + 1) return 0; /* @@ -261,10 +250,10 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) * Log the server error (once), but allow it and continue * since the frame is parseable. */ - if (clc_len < srvr->vals->header_preamble_size /* RFC1001 header size */ + len) { + if (clc_len < len) { printk_once(KERN_WARNING - "SMB2 server sent bad RFC1001 len %d not %zu\n", - len, clc_len - srvr->vals->header_preamble_size); + "SMB2 server sent bad RFC1001 len %d not %u\n", + len, clc_len); return 0; } -- 2.17.0