]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Hgfs Server: write op move argument checks security fixes
authorOliver Kurth <okurth@vmware.com>
Fri, 15 Sep 2017 18:23:02 +0000 (11:23 -0700)
committerOliver Kurth <okurth@vmware.com>
Fri, 15 Sep 2017 18:23:02 +0000 (11:23 -0700)
Complete the argument verifications in the common code adding the
missing checks for the write request packet size checks and the
write request data size (separated from the request itself as
in V4 of the HGFS protocol).  This will now catch any attempts
from a client to pass a write request containing a data size
argument for the data to write that is greater than the amount
of data in the HGFS packet or data buffer passed.

open-vm-tools/lib/hgfsServer/hgfsServer.c
open-vm-tools/lib/hgfsServer/hgfsServerInt.h
open-vm-tools/lib/hgfsServer/hgfsServerPacketUtil.c

index f5187f4de612b45efd990f4cacd83ece0236fb8a..cb900ce02f01d0d8aac6748013d2f258b506602f 100644 (file)
@@ -6369,9 +6369,18 @@ HgfsServerValidateWrite(HgfsInputParam *input,     // IN: Input params
    }
 
    /*
-    * TBD -
-    * - validate the packet size with the header, write request and write data
+    * Validate the packet size with the header, write request and write data.
     */
+   if (!HSPU_ValidateDataPacketSize(input->packet, requestWriteDataSize) ||
+       !HSPU_ValidateRequestPacketSize(input->packet,
+                                       requestWriteHeaderSize,
+                                       requestWritePacketSize,
+                                       requestWritePacketDataSize)) {
+      status = HGFS_ERROR_INVALID_PARAMETER;
+      LOG(4, ("%s: Error: write data size pkt %"FMTSZ"u data %"FMTSZ"u\n",
+               __FUNCTION__, requestWritePacketDataSize, requestWriteDataSize));
+      goto exit;
+   }
 
    /*
     * Now map the file handle, and extract the details of the write e.g. writing
index f9d046ca45916f690cdb9d8e5d6e1704c1b1f501..dcac80536bc4aa819d406ecbfda623e24223c229 100644 (file)
@@ -859,6 +859,12 @@ void
 HSPU_PutMetaPacket(HgfsPacket *packet,                   // IN/OUT: Hgfs Packet
                    HgfsServerChannelCallbacks *chanCb);  // IN: Channel callbacks
 
+Bool
+HSPU_ValidateRequestPacketSize(HgfsPacket *packet,        // IN: Hgfs Packet
+                               size_t requestHeaderSize,  // IN: request header size
+                               size_t requestOpSize,      // IN: request packet size
+                               size_t requestOpDataSize); // IN: request packet data size
+
 Bool
 HSPU_ValidateReplyPacketSize(HgfsPacket *packet,         // IN: Hgfs Packet
                              size_t replyHeaderSize,     // IN: reply header size
index d92daf0eea2f6a0d741eb6444c61200ce0450d7f..9fa48fdec492128fce7b9c328d503d0ee8b0c1db 100644 (file)
@@ -76,6 +76,57 @@ static void HSPUUnmapBuf(HgfsChannelUnmapVirtAddrFunc unmapVa,
 
 
 
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HSPU_ValidateRequestPacketSize --
+ *
+ *    Validate an HGFS packet size with the HGFS header in use, the HGFS opcode request
+ *    (its arguments) and optionally any opcode request data that is contained in the
+ *    size for the packet.
+ *
+ * Results:
+ *    TRUE if the packet size is large enough for the required request data.
+ *    FALSE if not.
+ *
+ * Side effects:
+ *    None.
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+HSPU_ValidateRequestPacketSize(HgfsPacket *packet,           // IN: Hgfs Packet
+                               size_t requestHeaderSize,     // IN: request header size
+                               size_t requestOpSize,         // IN: request op size
+                               size_t requestOpDataSize)     // IN: request op data size
+{
+   size_t bytesRemaining = packet->metaPacketDataSize;
+   Bool requestSizeIsOkay = FALSE;
+
+   /*
+    * Validate the request buffer size ensuring that the the contained components
+    * (request header, the operation arguments and lastly any data) fall within it.
+    */
+
+   if (bytesRemaining >= requestHeaderSize) {
+      bytesRemaining -= requestHeaderSize;
+   } else {
+      goto exit;
+   }
+   if (bytesRemaining >= requestOpSize) {
+      bytesRemaining -= requestOpSize;
+   } else {
+      goto exit;
+   }
+   if (bytesRemaining >= requestOpDataSize) {
+      requestSizeIsOkay = TRUE;
+   }
+
+exit:
+   return requestSizeIsOkay;
+}
+
+
 /*
  *-----------------------------------------------------------------------------
  *