diff -Naurp VirtualBox-2.0.2/include/VBox/VBoxGuestLib.h VirtualBox-2.0.2.oden/include/VBox/VBoxGuestLib.h --- VirtualBox-2.0.2/include/VBox/VBoxGuestLib.h 2008-09-01 08:23:07.000000000 -0400 +++ VirtualBox-2.0.2.oden/include/VBox/VBoxGuestLib.h 2010-03-04 12:13:57.000000000 -0500 @@ -129,6 +129,18 @@ DECLVBGL(int) VbglGRPerform (VMMDevReque * @return VBox status code. */ DECLVBGL(void) VbglGRFree (VMMDevRequestHeader *pReq); + +/** + * Verify the generic request header. + * + * @param pReq pointer the request header structure. + * @param cbReq size of the request memory block. It should be equal to the request size + * for fixed size requests. It can be greater than the request size for + * variable size requests. + * + * @return VBox status code. + */ +DECLVBGL(int) VbglGRVerify (const VMMDevRequestHeader *pReq, size_t cbReq); /** @} */ #ifdef VBOX_WITH_HGCM diff -Naurp VirtualBox-2.0.2/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp VirtualBox-2.0.2.oden/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp --- VirtualBox-2.0.2/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp 2008-09-12 06:01:49.000000000 -0400 +++ VirtualBox-2.0.2.oden/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp 2010-03-04 12:13:57.000000000 -0500 @@ -767,6 +767,13 @@ static int VBoxGuestCommonIOCtl_VMMReque cbData, cbReq, pReqHdr->requestType)); return VERR_INVALID_PARAMETER; } + int rc = VbglGRVerify(pReqHdr, cbData); + if (RT_FAILURE(rc)) + { + Log(("VBoxGuestCommonIOCtl: VMMREQUEST: invalid header: size %#x, expected >= %#x (hdr); type=%#x; rc %d!!\n", + cbData, cbReq, enmType, rc)); + return rc; + } /* * Make a copy of the request in the physical memory heap so @@ -776,7 +783,7 @@ static int VBoxGuestCommonIOCtl_VMMReque * it does makes things a bit simpler wrt to phys address.) */ VMMDevRequestHeader *pReqCopy; - int rc = VbglGRAlloc(&pReqCopy, cbReq, pReqHdr->requestType); + rc = VbglGRAlloc(&pReqCopy, cbReq, pReqHdr->requestType); if (RT_FAILURE(rc)) { Log(("VBoxGuestCommonIOCtl: VMMREQUEST: failed to allocate %u (%#x) bytes to cache the request. rc=%d!!\n", diff -Naurp VirtualBox-2.0.2/src/VBox/Additions/common/VBoxGuestLib/GenericRequest.cpp VirtualBox-2.0.2.oden/src/VBox/Additions/common/VBoxGuestLib/GenericRequest.cpp --- VirtualBox-2.0.2/src/VBox/Additions/common/VBoxGuestLib/GenericRequest.cpp 2008-06-25 14:09:34.000000000 -0400 +++ VirtualBox-2.0.2.oden/src/VBox/Additions/common/VBoxGuestLib/GenericRequest.cpp 2010-03-04 12:13:57.000000000 -0500 @@ -26,6 +26,72 @@ #include <iprt/string.h> #include <iprt/assert.h> +DECLVBGL(int) VbglGRVerify (const VMMDevRequestHeader *pReq, size_t cbReq) +{ + if (!pReq || cbReq < sizeof (VMMDevRequestHeader)) + { + dprintf(("VbglGRVerify: Invalid parameter: pReq = %p, cbReq = %d\n", pReq, cbReq)); + return VERR_INVALID_PARAMETER; + } + + if (pReq->size > cbReq) + { + dprintf(("VbglGRVerify: request size %d > buffer size %d\n", pReq->size, cbReq)); + return VERR_INVALID_PARAMETER; + } + + /* The request size must correspond to the request type. */ + size_t cbReqExpected = vmmdevGetRequestSize(pReq->requestType); + + if (cbReq < cbReqExpected) + { + dprintf(("VbglGRVerify: buffer size %d < expected size %d\n", cbReq, cbReqExpected)); + return VERR_INVALID_PARAMETER; + } + + if (cbReqExpected == cbReq) + { + /* This is most likely a fixed size request, and in this case the request size + * must be also equal to the expected size. + */ + if (pReq->size != cbReqExpected) + { + dprintf(("VbglGRVerify: request size %d != expected size %d\n", pReq->size, cbReqExpected)); + return VERR_INVALID_PARAMETER; + } + + return VINF_SUCCESS; + } + + /* This can be a variable size request. Check the request type and limit the size + * to VMMDEV_MAX_VMMDEVREQ_SIZE, which is max size supported by the host. + */ + if ( pReq->requestType == VMMDevReq_LogString + || pReq->requestType == VMMDevReq_VideoSetVisibleRegion + || pReq->requestType == VMMDevReq_SetPointerShape +#ifdef VBOX_WITH_64_BITS_GUESTS + || pReq->requestType == VMMDevReq_HGCMCall32 + || pReq->requestType == VMMDevReq_HGCMCall64 +#else + || pReq->requestType == VMMDevReq_HGCMCall +#endif /* VBOX_WITH_64_BITS_GUESTS */ + || pReq->requestType == VMMDevReq_ChangeMemBalloon) + { + if (cbReq > VMMDEV_MAX_VMMDEVREQ_SIZE) + { + dprintf(("VbglGRVerify: VMMDevReq_LogString: buffer size %d too big\n", cbReq)); + return VERR_BUFFER_OVERFLOW; /* @todo is this error code ok? */ + } + } + else + { + dprintf(("VbglGRVerify: request size %d > buffer size %d\n", pReq->size, cbReq)); + return VERR_IO_BAD_LENGTH; /* @todo is this error code ok? */ + } + + return VINF_SUCCESS; +} + DECLVBGL(int) VbglGRAlloc (VMMDevRequestHeader **ppReq, uint32_t cbSize, VMMDevRequestType reqType) { VMMDevRequestHeader *pReq; diff -Naurp VirtualBox-2.0.2/src/VBox/Additions/linux/module/vboxmod.c VirtualBox-2.0.2.oden/src/VBox/Additions/linux/module/vboxmod.c --- VirtualBox-2.0.2/src/VBox/Additions/linux/module/vboxmod.c 2008-09-12 06:01:49.000000000 -0400 +++ VirtualBox-2.0.2.oden/src/VBox/Additions/linux/module/vboxmod.c 2010-03-04 12:13:57.000000000 -0500 @@ -462,6 +462,21 @@ static int vboxadd_ioctl(struct inode *i } if (0 == rc) { + rc = VbglGRVerify(&reqHeader, cbRequestSize); + if (RT_FAILURE(rc)) + { + Log(("VBOXGUEST_IOCTL_VMMREQUEST: invalid request header: size %d min: %d type: %d rc: %d\n", + cbRequestSize, + cbVanillaRequestSize, + reqHeader.requestType, + rc)); + rc = -EINVAL; + } + else + rc = 0; + } + if (0 == rc) + { /* request storage for the full request */ rc = VbglGRAlloc(&reqFull, cbRequestSize, reqHeader.requestType); if (VBOX_FAILURE(rc))