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
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 <fge...@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
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 <fge...@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. */
signature.asc
Description: OpenPGP digital signature