Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[sfrench/cifs-2.6.git] / fs / cifs / smb2pdu.c
index ba3865b338d870c371b46431640405f064545eb3..5331631386a23bd4a7458ecb5fb96efe1773cf71 100644 (file)
@@ -648,7 +648,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
 {
        int rc = 0;
        struct validate_negotiate_info_req vneg_inbuf;
-       struct validate_negotiate_info_rsp *pneg_rsp;
+       struct validate_negotiate_info_rsp *pneg_rsp = NULL;
        u32 rsplen;
        u32 inbuflen; /* max of 4 dialects */
 
@@ -727,8 +727,9 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
                         rsplen);
 
                /* relax check since Mac returns max bufsize allowed on ioctl */
-               if (rsplen > CIFSMaxBufSize)
-                       return -EIO;
+               if ((rsplen > CIFSMaxBufSize)
+                    || (rsplen < sizeof(struct validate_negotiate_info_rsp)))
+                       goto err_rsp_free;
        }
 
        /* check validate negotiate info response matches what we got earlier */
@@ -747,10 +748,13 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
 
        /* validate negotiate successful */
        cifs_dbg(FYI, "validate negotiate info successful\n");
+       kfree(pneg_rsp);
        return 0;
 
 vneg_out:
        cifs_dbg(VFS, "protocol revalidation - security settings mismatch\n");
+err_rsp_free:
+       kfree(pneg_rsp);
        return -EIO;
 }
 
@@ -1255,7 +1259,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
        struct smb2_tree_connect_req *req;
        struct smb2_tree_connect_rsp *rsp = NULL;
        struct kvec iov[2];
-       struct kvec rsp_iov;
+       struct kvec rsp_iov = { NULL, 0 };
        int rc = 0;
        int resp_buftype;
        int unc_path_len;
@@ -1372,7 +1376,7 @@ tcon_exit:
        return rc;
 
 tcon_error_exit:
-       if (rsp->hdr.sync_hdr.Status == STATUS_BAD_NETWORK_NAME) {
+       if (rsp && rsp->hdr.sync_hdr.Status == STATUS_BAD_NETWORK_NAME) {
                cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree);
        }
        goto tcon_exit;
@@ -1975,6 +1979,9 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
        } else
                iov[0].iov_len = get_rfc1002_length(req) + 4;
 
+       /* validate negotiate request must be signed - see MS-SMB2 3.2.5.5 */
+       if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO)
+               req->hdr.sync_hdr.Flags |= SMB2_FLAGS_SIGNED;
 
        rc = SendReceive2(xid, ses, iov, n_iov, &resp_buftype, flags, &rsp_iov);
        cifs_small_buf_release(req);
@@ -2191,9 +2198,13 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon,
        req->PersistentFileId = persistent_fid;
        req->VolatileFileId = volatile_fid;
        req->AdditionalInformation = cpu_to_le32(additional_info);
-       /* 4 for rfc1002 length field and 1 for Buffer */
-       req->InputBufferOffset =
-               cpu_to_le16(sizeof(struct smb2_query_info_req) - 1 - 4);
+
+       /*
+        * We do not use the input buffer (do not send extra byte)
+        */
+       req->InputBufferOffset = 0;
+       inc_rfc1001_len(req, -1);
+
        req->OutputBufferLength = cpu_to_le32(output_len);
 
        iov[0].iov_base = (char *)req;