[Pkg-virtualbox-devel] Bug#735410: virtualbox: CVE-2013-5892 CVE-2014-0407 CVE-2014-0406 CVE-2014-0404
Felix Geyer
fgeyer at debian.org
Tue Jan 28 21:26:06 UTC 2014
On 15.01.2014 09:19, Moritz Muehlenhoff wrote:
> Package: virtualbox
> Severity: grave
> Tags: security
>
> http://www.oracle.com/technetwork/topics/security/cpujan2014-1972949.html
>
> Several vulnerabilities have been reported in VirtualBox. Details are scarce, so
> please get in touch with upstream for more information on eventual backports
> to oldstable/stable. Judging from the CVSS scores this is likely only local
> denial of service, in that case we likely don't need a DSA.
>
> CVE-2013-5892
> CVE-2014-0407
> CVE-2014-0406
> CVE-2014-0404
Upstream kindly provided a patch that fixes the 4 CVEs. Attached are yet untested
debdiffs for wheezy and squeeze.
Do you want to handle this through a security update?
According to upstream the vulnerabilities are mostly about users on the VM being able
to crash their VM. No ways to execute code on the host are known.
> In addition CVE-2014-0405 seems to affect virtualbox-guest-additions-iso from non-free
I guess we can't really fix that. The only option would be to upgrade the package
to 4.1.30 / 3.2.12.
Regards,
Felix
-------------- next part --------------
diff -Nru virtualbox-4.1.18-dfsg/debian/changelog virtualbox-4.1.18-dfsg/debian/changelog
--- virtualbox-4.1.18-dfsg/debian/changelog 2013-03-31 20:45:33.000000000 +0200
+++ virtualbox-4.1.18-dfsg/debian/changelog 2014-01-28 21:18:42.000000000 +0100
@@ -1,3 +1,11 @@
+virtualbox (4.1.18-dfsg-2+deb7u2) wheezy; urgency=high
+
+ * Apply fixes from the January 2014 security advisory. (Closes: #735410)
+ - Add debian/patches/38-security-fixes-2014-01.patch
+ - CVE-2013-5892, CVE-2014-0407, CVE-2014-0406, CVE-2014-0404
+
+ -- Felix Geyer <fgeyer at debian.org> Tue, 28 Jan 2014 21:12:21 +0100
+
virtualbox (4.1.18-dfsg-2+deb7u1) unstable; urgency=high
* Fix build failure with the Debian wheezy kernel which backports the drm
diff -Nru virtualbox-4.1.18-dfsg/debian/patches/38-security-fixes-2014-01.patch virtualbox-4.1.18-dfsg/debian/patches/38-security-fixes-2014-01.patch
--- virtualbox-4.1.18-dfsg/debian/patches/38-security-fixes-2014-01.patch 1970-01-01 01:00:00.000000000 +0100
+++ virtualbox-4.1.18-dfsg/debian/patches/38-security-fixes-2014-01.patch 2014-01-28 21:20:29.000000000 +0100
@@ -0,0 +1,471 @@
+--- a/include/VBox/VMMDev.h
++++ b/include/VBox/VMMDev.h
+@@ -114,6 +114,10 @@
+
+ /** Maximum request packet size. */
+ #define VMMDEV_MAX_VMMDEVREQ_SIZE _1M
++/** Maximum number of HGCM parameters. */
++#define VMMDEV_MAX_HGCM_PARMS 1024
++/** Maximum total size of hgcm buffers in one call. */
++#define VMMDEV_MAX_HGCM_DATA_SIZE UINT32_C(0x7FFFFFFF)
+
+ /**
+ * VMMDev request types.
+--- a/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp
++++ b/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp
+@@ -613,6 +613,13 @@
+
+ if (fShape)
+ {
++ if (pShape->u32Width > 8192 || pShape->u32Height > 8192)
++ {
++ Log(("vbvaMousePointerShape: unsupported size %ux%u\n",
++ pShape->u32Width, pShape->u32Height));
++ return VERR_INVALID_PARAMETER;
++ }
++
+ cbPointerData = ((((pShape->u32Width + 7) / 8) * pShape->u32Height + 3) & ~3)
+ + pShape->u32Width * 4 * pShape->u32Height;
+ }
+--- a/src/VBox/Devices/VMMDev/VMMDev.cpp
++++ b/src/VBox/Devices/VMMDev/VMMDev.cpp
+@@ -795,6 +795,20 @@
+
+ #endif /* VBOX_WITH_PAGE_SHARING */
+
++static int vmmdevVerifyPointerShape(VMMDevReqMousePointer *pReq)
++{
++ /* Should be enough for most mouse pointers. */
++ if (pReq->width > 8192 || pReq->height > 8192)
++ return VERR_INVALID_PARAMETER;
++
++ uint32_t cbShape = (pReq->width + 7) / 8 * pReq->height; /* size of the AND mask */
++ cbShape = ((cbShape + 3) & ~3) + pReq->width * 4 * pReq->height; /* + gap + size of the XOR mask */
++ if (RT_UOFFSETOF(VMMDevReqMousePointer, pointerData) + cbShape > pReq->header.size)
++ return VERR_INVALID_PARAMETER;
++
++ return VINF_SUCCESS;
++}
++
+ /**
+ * Port I/O Handler for the generic request interface
+ * @see FNIOMIOPORTOUT for details.
+@@ -1163,6 +1177,10 @@
+ /* forward call to driver */
+ if (fShape)
+ {
++ pRequestHeader->rc = vmmdevVerifyPointerShape(pointerShape);
++ if (RT_FAILURE(pRequestHeader->rc))
++ break;
++
+ pThis->pDrv->pfnUpdatePointerShape(pThis->pDrv,
+ fVisible,
+ fAlpha,
+--- a/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp
++++ b/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp
+@@ -97,6 +97,9 @@
+ */
+ VBOXHGCMSVCPARM *paHostParms;
+
++ /* Number of elements in paHostParms */
++ uint32_t cHostParms;
++
+ /* Linear pointer parameters information. */
+ int cLinPtrs;
+
+@@ -250,8 +253,6 @@
+ {
+ int rc = VINF_SUCCESS;
+
+- AssertRelease (u32Size > 0);
+-
+ VBOXHGCMLINPTR *pLinPtr = &paLinPtrs[iLinPtr];
+
+ /* Take the offset into the current page also into account! */
+@@ -294,8 +295,6 @@
+ GCPtr += PAGE_SIZE;
+ }
+
+- AssertRelease (iPage == cPages);
+-
+ return rc;
+ }
+
+@@ -310,7 +309,7 @@
+
+ VBOXHGCMLINPTR *pLinPtr = &paLinPtrs[iLinPtr];
+
+- AssertRelease (u32Size > 0 && iParm == (uint32_t)pLinPtr->iParm);
++ AssertLogRelReturn(u32Size > 0 && iParm == (uint32_t)pLinPtr->iParm, VERR_INVALID_PARAMETER);
+
+ RTGCPHYS GCPhysDst = pLinPtr->paPages[0] + pLinPtr->offFirstPage;
+ uint8_t *pu8Src = (uint8_t *)pvHost;
+@@ -332,12 +331,17 @@
+
+ if (cbWrite >= u32Size)
+ {
+- PDMDevHlpPhysWrite(pDevIns, GCPhysDst, pu8Src, u32Size);
++ rc = PDMDevHlpPhysWrite(pDevIns, GCPhysDst, pu8Src, u32Size);
++ if (RT_FAILURE(rc))
++ break;
++
+ u32Size = 0;
+ break;
+ }
+
+ PDMDevHlpPhysWrite(pDevIns, GCPhysDst, pu8Src, cbWrite);
++ if (RT_FAILURE(rc))
++ break;
+
+ /* next */
+ u32Size -= cbWrite;
+@@ -346,8 +350,10 @@
+ GCPhysDst = pLinPtr->paPages[iPage];
+ }
+
+- AssertRelease (iPage == pLinPtr->cPages);
+- Assert(u32Size == 0);
++ if (RT_SUCCESS(rc))
++ {
++ AssertLogRelReturn(iPage == pLinPtr->cPages, VERR_INVALID_PARAMETER);
++ }
+
+ return rc;
+ }
+@@ -623,6 +629,20 @@
+ Log(("vmmdevHGCMCall: cParms = %d\n", cParms));
+
+ /*
++ * Sane upper limit.
++ */
++ if (cParms > VMMDEV_MAX_HGCM_PARMS)
++ {
++ static int s_cRelWarn;
++ if (s_cRelWarn < 50)
++ {
++ s_cRelWarn++;
++ LogRel(("VMMDev: request packet with too many parameters (%d). Refusing operation.\n", cParms));
++ }
++ return VERR_INVALID_PARAMETER;
++ }
++
++ /*
+ * Compute size of required memory buffer.
+ */
+
+@@ -654,6 +674,12 @@
+ if (pGuestParm->u.Pointer.size > 0)
+ {
+ /* Only pointers with some actual data are counted. */
++ if (pGuestParm->u.Pointer.size > VMMDEV_MAX_HGCM_DATA_SIZE - cbCmdSize)
++ {
++ rc = VERR_INVALID_PARAMETER;
++ break;
++ }
++
+ cbCmdSize += pGuestParm->u.Pointer.size;
+
+ cLinPtrs++;
+@@ -667,6 +693,12 @@
+
+ case VMMDevHGCMParmType_PageList:
+ {
++ if (pGuestParm->u.PageList.size > VMMDEV_MAX_HGCM_DATA_SIZE - cbCmdSize)
++ {
++ rc = VERR_INVALID_PARAMETER;
++ break;
++ }
++
+ cbCmdSize += pGuestParm->u.PageList.size;
+ Log(("vmmdevHGCMCall: pagelist size = %d\n", pGuestParm->u.PageList.size));
+ } break;
+@@ -706,6 +738,12 @@
+ if (pGuestParm->u.Pointer.size > 0)
+ {
+ /* Only pointers with some actual data are counted. */
++ if (pGuestParm->u.Pointer.size > VMMDEV_MAX_HGCM_DATA_SIZE - cbCmdSize)
++ {
++ rc = VERR_INVALID_PARAMETER;
++ break;
++ }
++
+ cbCmdSize += pGuestParm->u.Pointer.size;
+
+ cLinPtrs++;
+@@ -719,6 +757,12 @@
+
+ case VMMDevHGCMParmType_PageList:
+ {
++ if (pGuestParm->u.PageList.size > VMMDEV_MAX_HGCM_DATA_SIZE - cbCmdSize)
++ {
++ rc = VERR_INVALID_PARAMETER;
++ break;
++ }
++
+ cbCmdSize += pGuestParm->u.PageList.size;
+ Log(("vmmdevHGCMCall: pagelist size = %d\n", pGuestParm->u.PageList.size));
+ } break;
+@@ -787,6 +831,7 @@
+ uint8_t *pcBuf = (uint8_t *)pHostParm + cParms * sizeof (VBOXHGCMSVCPARM);
+
+ pCmd->paHostParms = pHostParm;
++ pCmd->cHostParms = cParms;
+
+ uint32_t iLinPtr = 0;
+ RTGCPHYS *pPages = (RTGCPHYS *)((uint8_t *)pCmd->paLinPtrs + sizeof (VBOXHGCMLINPTR) *cLinPtrs);
+@@ -1135,6 +1180,20 @@
+ Log(("vmmdevHGCMCall: cParms = %d\n", cParms));
+
+ /*
++ * Sane upper limit.
++ */
++ if (cParms > VMMDEV_MAX_HGCM_PARMS)
++ {
++ static int s_cRelWarn;
++ if (s_cRelWarn < 50)
++ {
++ s_cRelWarn++;
++ LogRel(("VMMDev: request packet with too many parameters (%d). Refusing operation.\n", cParms));
++ }
++ return VERR_INVALID_PARAMETER;
++ }
++
++ /*
+ * Compute size of required memory buffer.
+ */
+
+@@ -1289,6 +1348,7 @@
+ uint8_t *pu8Buf = (uint8_t *)pHostParm + cParms * sizeof (VBOXHGCMSVCPARM);
+
+ pCmd->paHostParms = pHostParm;
++ pCmd->cHostParms = cParms;
+
+ uint32_t iParm;
+ int iLinPtr = 0;
+@@ -1758,6 +1818,88 @@
+ return VERR_INVALID_PARAMETER;
+ }
+
++#ifdef VBOX_WITH_64_BITS_GUESTS
++static int vmmdevHGCMParmVerify64(HGCMFunctionParameter64 *pGuestParm, VBOXHGCMSVCPARM *pHostParm)
++{
++ int rc = VERR_INVALID_PARAMETER;
++
++ switch (pGuestParm->type)
++ {
++ case VMMDevHGCMParmType_32bit:
++ if (pHostParm->type == VBOX_HGCM_SVC_PARM_32BIT)
++ rc = VINF_SUCCESS;
++ break;
++
++ case VMMDevHGCMParmType_64bit:
++ if (pHostParm->type == VBOX_HGCM_SVC_PARM_64BIT)
++ rc = VINF_SUCCESS;
++ break;
++
++ case VMMDevHGCMParmType_LinAddr_In: /* In (read) */
++ case VMMDevHGCMParmType_LinAddr_Out: /* Out (write) */
++ case VMMDevHGCMParmType_LinAddr: /* In & Out */
++ if ( pHostParm->type == VBOX_HGCM_SVC_PARM_PTR
++ && pGuestParm->u.Pointer.size >= pHostParm->u.pointer.size)
++ rc = VINF_SUCCESS;
++ break;
++
++ case VMMDevHGCMParmType_PageList:
++ if ( pHostParm->type == VBOX_HGCM_SVC_PARM_PTR
++ && pGuestParm->u.PageList.size >= pHostParm->u.pointer.size)
++ rc = VINF_SUCCESS;
++ break;
++
++ default:
++ AssertLogRelMsgFailed(("hgcmCompleted: invalid parameter type %08X\n", pGuestParm->type));
++ break;
++ }
++
++ return rc;
++}
++#endif /* VBOX_WITH_64_BITS_GUESTS */
++
++#ifdef VBOX_WITH_64_BITS_GUESTS
++static int vmmdevHGCMParmVerify32(HGCMFunctionParameter32 *pGuestParm, VBOXHGCMSVCPARM *pHostParm)
++#else
++static int vmmdevHGCMParmVerify32(HGCMFunctionParameter *pGuestParm, VBOXHGCMSVCPARM *pHostParm)
++#endif
++{
++ int rc = VERR_INVALID_PARAMETER;
++
++ switch (pGuestParm->type)
++ {
++ case VMMDevHGCMParmType_32bit:
++ if (pHostParm->type == VBOX_HGCM_SVC_PARM_32BIT)
++ rc = VINF_SUCCESS;
++ break;
++
++ case VMMDevHGCMParmType_64bit:
++ if (pHostParm->type == VBOX_HGCM_SVC_PARM_64BIT)
++ rc = VINF_SUCCESS;
++ break;
++
++ case VMMDevHGCMParmType_LinAddr_In: /* In (read) */
++ case VMMDevHGCMParmType_LinAddr_Out: /* Out (write) */
++ case VMMDevHGCMParmType_LinAddr: /* In & Out */
++ if ( pHostParm->type == VBOX_HGCM_SVC_PARM_PTR
++ && pGuestParm->u.Pointer.size >= pHostParm->u.pointer.size)
++ rc = VINF_SUCCESS;
++ break;
++
++ case VMMDevHGCMParmType_PageList:
++ if ( pHostParm->type == VBOX_HGCM_SVC_PARM_PTR
++ && pGuestParm->u.PageList.size >= pHostParm->u.pointer.size)
++ rc = VINF_SUCCESS;
++ break;
++
++ default:
++ AssertLogRelMsgFailed(("hgcmCompleted: invalid parameter type %08X\n", pGuestParm->type));
++ break;
++ }
++
++ return rc;
++}
++
+ #define PDMIHGCMPORT_2_VMMDEVSTATE(pInterface) ( (VMMDevState *) ((uintptr_t)pInterface - RT_OFFSETOF(VMMDevState, IHGCMPort)) )
+
+ DECLCALLBACK(void) hgcmCompletedWorker (PPDMIHGCMPORT pInterface, int32_t result, PVBOXHGCMCMD pCmd)
+@@ -1858,6 +2000,8 @@
+ VMMDevHGCMCall *pHGCMCall = (VMMDevHGCMCall *)pHeader;
+
+ uint32_t cParms = pHGCMCall->cParms;
++ if (cParms != pCmd->cHostParms)
++ rc = VERR_INVALID_PARAMETER;
+
+ VBOXHGCMSVCPARM *pHostParm = pCmd->paHostParms;
+
+@@ -1866,8 +2010,12 @@
+
+ HGCMFunctionParameter64 *pGuestParm = VMMDEV_HGCM_CALL_PARMS64(pHGCMCall);
+
+- for (i = 0; i < cParms; i++, pGuestParm++, pHostParm++)
++ for (i = 0; i < cParms && RT_SUCCESS(rc); i++, pGuestParm++, pHostParm++)
+ {
++ rc = vmmdevHGCMParmVerify64(pGuestParm, pHostParm);
++ if (RT_FAILURE(rc))
++ break;
++
+ switch (pGuestParm->type)
+ {
+ case VMMDevHGCMParmType_32bit:
+@@ -1894,7 +2042,6 @@
+ /* Use the saved page list to write data back to the guest RAM. */
+ rc = vmmdevHGCMWriteLinPtr (pVMMDevState->pDevIns, i, pHostParm->u.pointer.addr,
+ size, iLinPtr, pCmd->paLinPtrs);
+- AssertReleaseRC(rc);
+ }
+
+ /* All linptrs with size > 0 were saved. Advance the index to the next linptr. */
+@@ -1945,7 +2092,8 @@
+ default:
+ {
+ /* This indicates that the guest request memory was corrupted. */
+- AssertReleaseMsgFailed(("hgcmCompleted: invalid parameter type %08X\n", pGuestParm->type));
++ rc = VERR_INVALID_PARAMETER;
++ break;
+ }
+ }
+ }
+@@ -1961,6 +2109,8 @@
+ VMMDevHGCMCall *pHGCMCall = (VMMDevHGCMCall *)pHeader;
+
+ uint32_t cParms = pHGCMCall->cParms;
++ if (cParms != pCmd->cHostParms)
++ rc = VERR_INVALID_PARAMETER;
+
+ VBOXHGCMSVCPARM *pHostParm = pCmd->paHostParms;
+
+@@ -1969,8 +2119,12 @@
+
+ HGCMFunctionParameter32 *pGuestParm = VMMDEV_HGCM_CALL_PARMS32(pHGCMCall);
+
+- for (i = 0; i < cParms; i++, pGuestParm++, pHostParm++)
++ for (i = 0; i < cParms && RT_SUCCESS(rc); i++, pGuestParm++, pHostParm++)
+ {
++ rc = vmmdevHGCMParmVerify32(pGuestParm, pHostParm);
++ if (RT_FAILURE(rc))
++ break;
++
+ switch (pGuestParm->type)
+ {
+ case VMMDevHGCMParmType_32bit:
+@@ -1996,7 +2150,6 @@
+ {
+ /* Use the saved page list to write data back to the guest RAM. */
+ rc = vmmdevHGCMWriteLinPtr (pVMMDevState->pDevIns, i, pHostParm->u.pointer.addr, size, iLinPtr, pCmd->paLinPtrs);
+- AssertReleaseRC(rc);
+ }
+
+ /* All linptrs with size > 0 were saved. Advance the index to the next linptr. */
+@@ -2047,7 +2200,8 @@
+ default:
+ {
+ /* This indicates that the guest request memory was corrupted. */
+- AssertReleaseMsgFailed(("hgcmCompleted: invalid parameter type %08X\n", pGuestParm->type));
++ rc = VERR_INVALID_PARAMETER;
++ break;
+ }
+ }
+ }
+@@ -2063,6 +2217,8 @@
+ VMMDevHGCMCall *pHGCMCall = (VMMDevHGCMCall *)pHeader;
+
+ uint32_t cParms = pHGCMCall->cParms;
++ if (cParms != pCmd->cHostParms)
++ rc = VERR_INVALID_PARAMETER;
+
+ VBOXHGCMSVCPARM *pHostParm = pCmd->paHostParms;
+
+@@ -2071,8 +2227,12 @@
+
+ HGCMFunctionParameter *pGuestParm = VMMDEV_HGCM_CALL_PARMS(pHGCMCall);
+
+- for (i = 0; i < cParms; i++, pGuestParm++, pHostParm++)
++ for (i = 0; i < cParms && RT_SUCCESS(rc); i++, pGuestParm++, pHostParm++)
+ {
++ rc = vmmdevHGCMParmVerify32(pGuestParm, pHostParm);
++ if (RT_FAILURE(rc))
++ break;
++
+ switch (pGuestParm->type)
+ {
+ case VMMDevHGCMParmType_32bit:
+@@ -2098,7 +2258,6 @@
+ {
+ /* Use the saved page list to write data back to the guest RAM. */
+ rc = vmmdevHGCMWriteLinPtr (pVMMDevState->pDevIns, i, pHostParm->u.pointer.addr, size, iLinPtr, pCmd->paLinPtrs);
+- AssertReleaseRC(rc);
+ }
+
+ /* All linptrs with size > 0 were saved. Advance the index to the next linptr. */
+@@ -2149,7 +2308,8 @@
+ default:
+ {
+ /* This indicates that the guest request memory was corrupted. */
+- AssertReleaseMsgFailed(("hgcmCompleted: invalid parameter type %08X\n", pGuestParm->type));
++ rc = VERR_INVALID_PARAMETER;
++ break;
+ }
+ }
+ }
+@@ -2175,10 +2335,11 @@
+ break;
+ }
+ }
+- else
++
++ if (RT_FAILURE(rc))
+ {
+- /* Command type is wrong. Return error to the guest. */
+- pHeader->header.rc = rc;
++ /* Command is wrong. Return HGCM error result to the guest. */
++ pHeader->result = rc;
+ }
+
+ /* Mark request as processed. */
diff -Nru virtualbox-4.1.18-dfsg/debian/patches/series virtualbox-4.1.18-dfsg/debian/patches/series
--- virtualbox-4.1.18-dfsg/debian/patches/series 2013-03-31 20:34:11.000000000 +0200
+++ virtualbox-4.1.18-dfsg/debian/patches/series 2014-01-28 21:12:08.000000000 +0100
@@ -17,3 +17,4 @@
cve-2012-3221.patch
CVE-2013-0420.patch
37-wheezy-kernel-drm.patch
+38-security-fixes-2014-01.patch
-------------- next part --------------
diff -u virtualbox-ose-3.2.10-dfsg/debian/changelog virtualbox-ose-3.2.10-dfsg/debian/changelog
--- virtualbox-ose-3.2.10-dfsg/debian/changelog
+++ virtualbox-ose-3.2.10-dfsg/debian/changelog
@@ -1,3 +1,11 @@
+virtualbox-ose (3.2.10-dfsg-1+squeeze2) squeeze; urgency=high
+
+ * Apply fixes from the January 2014 security advisory. (Closes: #735410)
+ - Add debian/patches/28-security-fixes-2014-01.patch
+ - CVE-2013-5892, CVE-2014-0407, CVE-2014-0406, CVE-2014-0404
+
+ -- Felix Geyer <fgeyer at debian.org> Tue, 28 Jan 2014 22:05:32 +0100
+
virtualbox-ose (3.2.10-dfsg-1+squeeze1) stable-security; urgency=high
* Non-maintainer upload by the Security Team.
diff -u virtualbox-ose-3.2.10-dfsg/debian/patches/series virtualbox-ose-3.2.10-dfsg/debian/patches/series
--- virtualbox-ose-3.2.10-dfsg/debian/patches/series
+++ virtualbox-ose-3.2.10-dfsg/debian/patches/series
@@ -13,0 +14 @@
+28-security-fixes-2014-01.patch
only in patch2:
unchanged:
--- virtualbox-ose-3.2.10-dfsg.orig/debian/patches/28-security-fixes-2014-01.patch
+++ virtualbox-ose-3.2.10-dfsg/debian/patches/28-security-fixes-2014-01.patch
@@ -0,0 +1,470 @@
+--- a/include/VBox/VMMDev.h
++++ b/include/VBox/VMMDev.h
+@@ -114,6 +114,9 @@
+
+ /** Maximum request packet size. */
+ #define VMMDEV_MAX_VMMDEVREQ_SIZE _1M
++#define VMMDEV_MAX_VMMDEV_PARMS 1024
++/** Maximum total size of hgcm buffers in one call. */
++#define VMMDEV_MAX_HGCM_DATA_SIZE UINT32_C(0x7FFFFFFF)
+
+ /**
+ * VMMDev request types.
+--- a/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp
++++ b/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp
+@@ -604,6 +604,13 @@
+
+ if (fShape)
+ {
++ if (pShape->u32Width > 8192 || pShape->u32Height > 8192)
++ {
++ Log(("vbvaMousePointerShape: unsupported size %ux%u\n",
++ pShape->u32Width, pShape->u32Height));
++ return VERR_INVALID_PARAMETER;
++ }
++
+ cbPointerData = ((((pShape->u32Width + 7) / 8) * pShape->u32Height + 3) & ~3)
+ + pShape->u32Width * 4 * pShape->u32Height;
+ }
+--- a/src/VBox/Devices/VMMDev/VMMDev.cpp
++++ b/src/VBox/Devices/VMMDev/VMMDev.cpp
+@@ -380,6 +380,20 @@
+ }
+ #endif /* TIMESYNC_BACKDOOR */
+
++static int vmmdevVerifyPointerShape(VMMDevReqMousePointer *pReq)
++{
++ /* Should be enough for most mouse pointers. */
++ if (pReq->width > 8192 || pReq->height > 8192)
++ return VERR_INVALID_PARAMETER;
++
++ uint32_t cbShape = (pReq->width + 7) / 8 * pReq->height; /* size of the AND mask */
++ cbShape = ((cbShape + 3) & ~3) + pReq->width * 4 * pReq->height; /* + gap + size of the XOR mask */
++ if (RT_UOFFSETOF(VMMDevReqMousePointer, pointerData) + cbShape > pReq->header.size)
++ return VERR_INVALID_PARAMETER;
++
++ return VINF_SUCCESS;
++}
++
+ /**
+ * Port I/O Handler for the generic request interface
+ * @see FNIOMIOPORTOUT for details.
+@@ -710,6 +724,10 @@
+ /* forward call to driver */
+ if (fShape)
+ {
++ pRequestHeader->rc = vmmdevVerifyPointerShape(pointerShape);
++ if (RT_FAILURE(pRequestHeader->rc))
++ break;
++
+ pThis->pDrv->pfnUpdatePointerShape(pThis->pDrv,
+ fVisible,
+ fAlpha,
+--- a/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp
++++ b/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp
+@@ -91,6 +91,9 @@
+ */
+ VBOXHGCMSVCPARM *paHostParms;
+
++ /* Number of elements in paHostParms */
++ uint32_t cHostParms;
++
+ /* Linear pointer parameters information. */
+ int cLinPtrs;
+
+@@ -231,8 +234,6 @@
+ {
+ int rc = VINF_SUCCESS;
+
+- AssertRelease (u32Size > 0);
+-
+ VBOXHGCMLINPTR *pLinPtr = &paLinPtrs[iLinPtr];
+
+ /* Take the offset into the current page also into account! */
+@@ -275,8 +276,6 @@
+ GCPtr += PAGE_SIZE;
+ }
+
+- AssertRelease (iPage == cPages);
+-
+ return rc;
+ }
+
+@@ -291,7 +290,7 @@
+
+ VBOXHGCMLINPTR *pLinPtr = &paLinPtrs[iLinPtr];
+
+- AssertRelease (u32Size > 0 && iParm == (uint32_t)pLinPtr->iParm);
++ AssertLogRelReturn(u32Size > 0 && iParm == (uint32_t)pLinPtr->iParm, VERR_INVALID_PARAMETER);
+
+ RTGCPHYS GCPhysDst = pLinPtr->paPages[0] + pLinPtr->offFirstPage;
+ uint8_t *pu8Src = (uint8_t *)pvHost;
+@@ -313,12 +312,17 @@
+
+ if (cbWrite >= u32Size)
+ {
+- PDMDevHlpPhysWrite(pDevIns, GCPhysDst, pu8Src, u32Size);
++ rc = PDMDevHlpPhysWrite(pDevIns, GCPhysDst, pu8Src, u32Size);
++ if (RT_FAILURE(rc))
++ break;
++
+ u32Size = 0;
+ break;
+ }
+
+ PDMDevHlpPhysWrite(pDevIns, GCPhysDst, pu8Src, cbWrite);
++ if (RT_FAILURE(rc))
++ break;
+
+ /* next */
+ u32Size -= cbWrite;
+@@ -327,8 +331,10 @@
+ GCPhysDst = pLinPtr->paPages[iPage];
+ }
+
+- AssertRelease (iPage == pLinPtr->cPages);
+- Assert(u32Size == 0);
++ if (RT_SUCCESS(rc))
++ {
++ AssertLogRelReturn(iPage == pLinPtr->cPages, VERR_INVALID_PARAMETER);
++ }
+
+ return rc;
+ }
+@@ -604,6 +610,20 @@
+ Log(("vmmdevHGCMCall: cParms = %d\n", cParms));
+
+ /*
++ * Sane upper limit.
++ */
++ if (cParms > VMMDEV_MAX_VMMDEV_PARMS)
++ {
++ static int s_cRelWarn;
++ if (s_cRelWarn < 50)
++ {
++ s_cRelWarn++;
++ LogRel(("VMMDev: request packet with too many parameters (%d). Refusing operation.\n", cParms));
++ return VERR_NOT_SUPPORTED;
++ }
++ }
++
++ /*
+ * Compute size of required memory buffer.
+ */
+
+@@ -635,6 +655,12 @@
+ if (pGuestParm->u.Pointer.size > 0)
+ {
+ /* Only pointers with some actual data are counted. */
++ if (pGuestParm->u.Pointer.size > VMMDEV_MAX_HGCM_DATA_SIZE - cbCmdSize)
++ {
++ rc = VERR_INVALID_PARAMETER;
++ break;
++ }
++
+ cbCmdSize += pGuestParm->u.Pointer.size;
+
+ cLinPtrs++;
+@@ -648,6 +674,12 @@
+
+ case VMMDevHGCMParmType_PageList:
+ {
++ if (pGuestParm->u.PageList.size > VMMDEV_MAX_HGCM_DATA_SIZE - cbCmdSize)
++ {
++ rc = VERR_INVALID_PARAMETER;
++ break;
++ }
++
+ cbCmdSize += pGuestParm->u.PageList.size;
+ Log(("vmmdevHGCMCall: pagelist size = %d\n", pGuestParm->u.PageList.size));
+ } break;
+@@ -687,6 +719,12 @@
+ if (pGuestParm->u.Pointer.size > 0)
+ {
+ /* Only pointers with some actual data are counted. */
++ if (pGuestParm->u.Pointer.size > VMMDEV_MAX_HGCM_DATA_SIZE - cbCmdSize)
++ {
++ rc = VERR_INVALID_PARAMETER;
++ break;
++ }
++
+ cbCmdSize += pGuestParm->u.Pointer.size;
+
+ cLinPtrs++;
+@@ -700,6 +738,12 @@
+
+ case VMMDevHGCMParmType_PageList:
+ {
++ if (pGuestParm->u.PageList.size > VMMDEV_MAX_HGCM_DATA_SIZE - cbCmdSize)
++ {
++ rc = VERR_INVALID_PARAMETER;
++ break;
++ }
++
+ cbCmdSize += pGuestParm->u.PageList.size;
+ Log(("vmmdevHGCMCall: pagelist size = %d\n", pGuestParm->u.PageList.size));
+ } break;
+@@ -768,6 +812,7 @@
+ uint8_t *pcBuf = (uint8_t *)pHostParm + cParms * sizeof (VBOXHGCMSVCPARM);
+
+ pCmd->paHostParms = pHostParm;
++ pCmd->cHostParms = cParms;
+
+ uint32_t iLinPtr = 0;
+ RTGCPHYS *pPages = (RTGCPHYS *)((uint8_t *)pCmd->paLinPtrs + sizeof (VBOXHGCMLINPTR) *cLinPtrs);
+@@ -1116,6 +1161,20 @@
+ Log(("vmmdevHGCMCall: cParms = %d\n", cParms));
+
+ /*
++ * Sane upper limit.
++ */
++ if (cParms > VMMDEV_MAX_VMMDEV_PARMS)
++ {
++ static int s_cRelWarn;
++ if (s_cRelWarn < 50)
++ {
++ s_cRelWarn++;
++ LogRel(("VMMDev: request packet with too many parameters (%d). Refusing operation.\n", cParms));
++ return VERR_NOT_SUPPORTED;
++ }
++ }
++
++ /*
+ * Compute size of required memory buffer.
+ */
+
+@@ -1270,6 +1329,7 @@
+ uint8_t *pu8Buf = (uint8_t *)pHostParm + cParms * sizeof (VBOXHGCMSVCPARM);
+
+ pCmd->paHostParms = pHostParm;
++ pCmd->cHostParms = cParms;
+
+ uint32_t iParm;
+ int iLinPtr = 0;
+@@ -1739,6 +1799,88 @@
+ return VERR_INVALID_PARAMETER;
+ }
+
++#ifdef VBOX_WITH_64_BITS_GUESTS
++static int vmmdevHGCMParmVerify64(HGCMFunctionParameter64 *pGuestParm, VBOXHGCMSVCPARM *pHostParm)
++{
++ int rc = VERR_INVALID_PARAMETER;
++
++ switch (pGuestParm->type)
++ {
++ case VMMDevHGCMParmType_32bit:
++ if (pHostParm->type == VBOX_HGCM_SVC_PARM_32BIT)
++ rc = VINF_SUCCESS;
++ break;
++
++ case VMMDevHGCMParmType_64bit:
++ if (pHostParm->type == VBOX_HGCM_SVC_PARM_64BIT)
++ rc = VINF_SUCCESS;
++ break;
++
++ case VMMDevHGCMParmType_LinAddr_In: /* In (read) */
++ case VMMDevHGCMParmType_LinAddr_Out: /* Out (write) */
++ case VMMDevHGCMParmType_LinAddr: /* In & Out */
++ if ( pHostParm->type == VBOX_HGCM_SVC_PARM_PTR
++ && pGuestParm->u.Pointer.size >= pHostParm->u.pointer.size)
++ rc = VINF_SUCCESS;
++ break;
++
++ case VMMDevHGCMParmType_PageList:
++ if ( pHostParm->type == VBOX_HGCM_SVC_PARM_PTR
++ && pGuestParm->u.PageList.size >= pHostParm->u.pointer.size)
++ rc = VINF_SUCCESS;
++ break;
++
++ default:
++ AssertLogRelMsgFailed(("hgcmCompleted: invalid parameter type %08X\n", pGuestParm->type));
++ break;
++ }
++
++ return rc;
++}
++#endif /* VBOX_WITH_64_BITS_GUESTS */
++
++#ifdef VBOX_WITH_64_BITS_GUESTS
++static int vmmdevHGCMParmVerify32(HGCMFunctionParameter32 *pGuestParm, VBOXHGCMSVCPARM *pHostParm)
++#else
++static int vmmdevHGCMParmVerify32(HGCMFunctionParameter *pGuestParm, VBOXHGCMSVCPARM *pHostParm)
++#endif
++{
++ int rc = VERR_INVALID_PARAMETER;
++
++ switch (pGuestParm->type)
++ {
++ case VMMDevHGCMParmType_32bit:
++ if (pHostParm->type == VBOX_HGCM_SVC_PARM_32BIT)
++ rc = VINF_SUCCESS;
++ break;
++
++ case VMMDevHGCMParmType_64bit:
++ if (pHostParm->type == VBOX_HGCM_SVC_PARM_64BIT)
++ rc = VINF_SUCCESS;
++ break;
++
++ case VMMDevHGCMParmType_LinAddr_In: /* In (read) */
++ case VMMDevHGCMParmType_LinAddr_Out: /* Out (write) */
++ case VMMDevHGCMParmType_LinAddr: /* In & Out */
++ if ( pHostParm->type == VBOX_HGCM_SVC_PARM_PTR
++ && pGuestParm->u.Pointer.size >= pHostParm->u.pointer.size)
++ rc = VINF_SUCCESS;
++ break;
++
++ case VMMDevHGCMParmType_PageList:
++ if ( pHostParm->type == VBOX_HGCM_SVC_PARM_PTR
++ && pGuestParm->u.PageList.size >= pHostParm->u.pointer.size)
++ rc = VINF_SUCCESS;
++ break;
++
++ default:
++ AssertLogRelMsgFailed(("hgcmCompleted: invalid parameter type %08X\n", pGuestParm->type));
++ break;
++ }
++
++ return rc;
++}
++
+ #define PDMIHGCMPORT_2_VMMDEVSTATE(pInterface) ( (VMMDevState *) ((uintptr_t)pInterface - RT_OFFSETOF(VMMDevState, IHGCMPort)) )
+
+ DECLCALLBACK(void) hgcmCompletedWorker (PPDMIHGCMPORT pInterface, int32_t result, PVBOXHGCMCMD pCmd)
+@@ -1839,6 +1981,8 @@
+ VMMDevHGCMCall *pHGCMCall = (VMMDevHGCMCall *)pHeader;
+
+ uint32_t cParms = pHGCMCall->cParms;
++ if (cParms != pCmd->cHostParms)
++ rc = VERR_INVALID_PARAMETER;
+
+ VBOXHGCMSVCPARM *pHostParm = pCmd->paHostParms;
+
+@@ -1847,8 +1991,12 @@
+
+ HGCMFunctionParameter64 *pGuestParm = VMMDEV_HGCM_CALL_PARMS64(pHGCMCall);
+
+- for (i = 0; i < cParms; i++, pGuestParm++, pHostParm++)
++ for (i = 0; i < cParms && RT_SUCCESS(rc); i++, pGuestParm++, pHostParm++)
+ {
++ rc = vmmdevHGCMParmVerify64(pGuestParm, pHostParm);
++ if (RT_FAILURE(rc))
++ break;
++
+ switch (pGuestParm->type)
+ {
+ case VMMDevHGCMParmType_32bit:
+@@ -1875,7 +2023,6 @@
+ /* Use the saved page list to write data back to the guest RAM. */
+ rc = vmmdevHGCMWriteLinPtr (pVMMDevState->pDevIns, i, pHostParm->u.pointer.addr,
+ size, iLinPtr, pCmd->paLinPtrs);
+- AssertReleaseRC(rc);
+ }
+
+ /* All linptrs with size > 0 were saved. Advance the index to the next linptr. */
+@@ -1926,7 +2073,8 @@
+ default:
+ {
+ /* This indicates that the guest request memory was corrupted. */
+- AssertReleaseMsgFailed(("hgcmCompleted: invalid parameter type %08X\n", pGuestParm->type));
++ rc = VERR_INVALID_PARAMETER;
++ break;
+ }
+ }
+ }
+@@ -1942,6 +2090,8 @@
+ VMMDevHGCMCall *pHGCMCall = (VMMDevHGCMCall *)pHeader;
+
+ uint32_t cParms = pHGCMCall->cParms;
++ if (cParms != pCmd->cHostParms)
++ rc = VERR_INVALID_PARAMETER;
+
+ VBOXHGCMSVCPARM *pHostParm = pCmd->paHostParms;
+
+@@ -1950,8 +2100,12 @@
+
+ HGCMFunctionParameter32 *pGuestParm = VMMDEV_HGCM_CALL_PARMS32(pHGCMCall);
+
+- for (i = 0; i < cParms; i++, pGuestParm++, pHostParm++)
++ for (i = 0; i < cParms && RT_SUCCESS(rc); i++, pGuestParm++, pHostParm++)
+ {
++ rc = vmmdevHGCMParmVerify32(pGuestParm, pHostParm);
++ if (RT_FAILURE(rc))
++ break;
++
+ switch (pGuestParm->type)
+ {
+ case VMMDevHGCMParmType_32bit:
+@@ -1977,7 +2131,6 @@
+ {
+ /* Use the saved page list to write data back to the guest RAM. */
+ rc = vmmdevHGCMWriteLinPtr (pVMMDevState->pDevIns, i, pHostParm->u.pointer.addr, size, iLinPtr, pCmd->paLinPtrs);
+- AssertReleaseRC(rc);
+ }
+
+ /* All linptrs with size > 0 were saved. Advance the index to the next linptr. */
+@@ -2028,7 +2181,8 @@
+ default:
+ {
+ /* This indicates that the guest request memory was corrupted. */
+- AssertReleaseMsgFailed(("hgcmCompleted: invalid parameter type %08X\n", pGuestParm->type));
++ rc = VERR_INVALID_PARAMETER;
++ break;
+ }
+ }
+ }
+@@ -2044,6 +2198,8 @@
+ VMMDevHGCMCall *pHGCMCall = (VMMDevHGCMCall *)pHeader;
+
+ uint32_t cParms = pHGCMCall->cParms;
++ if (cParms != pCmd->cHostParms)
++ rc = VERR_INVALID_PARAMETER;
+
+ VBOXHGCMSVCPARM *pHostParm = pCmd->paHostParms;
+
+@@ -2052,8 +2208,12 @@
+
+ HGCMFunctionParameter *pGuestParm = VMMDEV_HGCM_CALL_PARMS(pHGCMCall);
+
+- for (i = 0; i < cParms; i++, pGuestParm++, pHostParm++)
++ for (i = 0; i < cParms && RT_SUCCESS(rc); i++, pGuestParm++, pHostParm++)
+ {
++ rc = vmmdevHGCMParmVerify32(pGuestParm, pHostParm);
++ if (RT_FAILURE(rc))
++ break;
++
+ switch (pGuestParm->type)
+ {
+ case VMMDevHGCMParmType_32bit:
+@@ -2079,7 +2239,6 @@
+ {
+ /* Use the saved page list to write data back to the guest RAM. */
+ rc = vmmdevHGCMWriteLinPtr (pVMMDevState->pDevIns, i, pHostParm->u.pointer.addr, size, iLinPtr, pCmd->paLinPtrs);
+- AssertReleaseRC(rc);
+ }
+
+ /* All linptrs with size > 0 were saved. Advance the index to the next linptr. */
+@@ -2130,7 +2289,8 @@
+ default:
+ {
+ /* This indicates that the guest request memory was corrupted. */
+- AssertReleaseMsgFailed(("hgcmCompleted: invalid parameter type %08X\n", pGuestParm->type));
++ rc = VERR_INVALID_PARAMETER;
++ break;
+ }
+ }
+ }
+@@ -2156,10 +2316,11 @@
+ break;
+ }
+ }
+- else
++
++ if (RT_FAILURE(rc))
+ {
+- /* Command type is wrong. Return error to the guest. */
+- pHeader->header.rc = rc;
++ /* Command is wrong. Return HGCM error result to the guest. */
++ pHeader->result = rc;
+ }
+
+ /* Mark request as processed. */
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 901 bytes
Desc: OpenPGP digital signature
URL: <http://lists.alioth.debian.org/pipermail/pkg-virtualbox-devel/attachments/20140128/f2db4af2/attachment-0001.sig>
More information about the Pkg-virtualbox-devel
mailing list