OSDN Git Service

cifs: update smb2_check_message to handle PDUs without a 4 byte length header
authorRonnie Sahlberg <lsahlber@redhat.com>
Wed, 30 May 2018 21:43:34 +0000 (07:43 +1000)
committerSteve French <stfrench@microsoft.com>
Wed, 30 May 2018 22:24:14 +0000 (17:24 -0500)
Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/cifs/smb2misc.c

index f7f3ad7..8cee72e 100644 (file)
@@ -94,7 +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,
+static __u32 get_neg_ctxt_len(struct smb2_sync_hdr *hdr, __u32 len,
+                             __u32 non_ctxlen,
                                size_t hdr_preamble_size)
 {
        __u16 neg_count;
@@ -131,25 +132,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 +169,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 +223,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);
+               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 +251,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;
                }