From: Oliver Kurth Date: Fri, 15 Sep 2017 18:23:02 +0000 (-0700) Subject: Hgfs Server: write op move argument checks security fixes X-Git-Tag: stable-10.2.0~546 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f25e6759cf0d274a87d740cd418c49eb306a1fe2;p=thirdparty%2Fopen-vm-tools.git Hgfs Server: write op move argument checks security fixes 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. --- diff --git a/open-vm-tools/lib/hgfsServer/hgfsServer.c b/open-vm-tools/lib/hgfsServer/hgfsServer.c index f5187f4de..cb900ce02 100644 --- a/open-vm-tools/lib/hgfsServer/hgfsServer.c +++ b/open-vm-tools/lib/hgfsServer/hgfsServer.c @@ -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 diff --git a/open-vm-tools/lib/hgfsServer/hgfsServerInt.h b/open-vm-tools/lib/hgfsServer/hgfsServerInt.h index f9d046ca4..dcac80536 100644 --- a/open-vm-tools/lib/hgfsServer/hgfsServerInt.h +++ b/open-vm-tools/lib/hgfsServer/hgfsServerInt.h @@ -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 diff --git a/open-vm-tools/lib/hgfsServer/hgfsServerPacketUtil.c b/open-vm-tools/lib/hgfsServer/hgfsServerPacketUtil.c index d92daf0ee..9fa48fdec 100644 --- a/open-vm-tools/lib/hgfsServer/hgfsServerPacketUtil.c +++ b/open-vm-tools/lib/hgfsServer/hgfsServerPacketUtil.c @@ -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; +} + + /* *----------------------------------------------------------------------------- *