Fix corrupt SMB2 ioctl requests
authorSteve French <smfrench@gmail.com>
Mon, 14 Oct 2013 05:44:19 +0000 (00:44 -0500)
committerSteve French <smfrench@gmail.com>
Mon, 28 Oct 2013 14:21:36 +0000 (09:21 -0500)
We were off by one calculating the length of ioctls in some cases
because the protocol specification for SMB2 ioctl includes a mininum
one byte payload but not all SMB2 ioctl requests actually have
a data buffer to send. We were also not zeroing out the
return buffer (in case of error this is helpful).

Signed-off-by: Steve French <smfrench@gmail.com>
fs/cifs/smb2pdu.c

index edccb5252462b6b465d3d71cb7d3de20e8d2be9a..6e18686112333c27d47b44fe6e3ae5596b5d6361 100644 (file)
@@ -1137,6 +1137,7 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
 
        cifs_dbg(FYI, "SMB2 IOCTL\n");
 
+       *out_data = NULL;
        /* zero out returned data len, in case of error */
        if (plen)
                *plen = 0;
@@ -1182,11 +1183,23 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
                req->Flags = 0;
 
        iov[0].iov_base = (char *)req;
-       /* 4 for rfc1002 length field */
-       iov[0].iov_len = get_rfc1002_length(req) + 4;
 
-       if (indatalen)
-               inc_rfc1001_len(req, indatalen);
+       /*
+        * If no input data, the size of ioctl struct in
+        * protocol spec still includes a 1 byte data buffer,
+        * but if input data passed to ioctl, we do not
+        * want to double count this, so we do not send
+        * the dummy one byte of data in iovec[0] if sending
+        * input data (in iovec[1]). We also must add 4 bytes
+        * in first iovec to allow for rfc1002 length field.
+        */
+
+       if (indatalen) {
+               iov[0].iov_len = get_rfc1002_length(req) + 4 - 1;
+               inc_rfc1001_len(req, indatalen - 1);
+       } else
+               iov[0].iov_len = get_rfc1002_length(req) + 4;
+
 
        rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buftype, 0);
        rsp = (struct smb2_ioctl_rsp *)iov[0].iov_base;