Oracle VM VirtualBox: Integer Overflow Leading To Out-Of-Bounds Read in virtioNetR3CtrlMac
Summary
A guest inside a VirtualBox VM using the virtio-net network adapter can trigger an integer overflow leading to out-of-bounds read in src/VBox/Devices/Network/DevVirtioNet.cpp to cause a denial-of-service or leak information of the hypervisor.
Severity
High - An attacker with high privileges in the guest can cause a denial-of-service or leak information of the hypervisor.
Proof of Concept
The following function handles a VIRTIONET_CTRL_MAC control command which fetches multiple 32bit cMacs values from the guest:
```c++
static uint8_t virtioNetR3CtrlMac(PVIRTIONET pThis, PVIRTIONET_CTRL_HDR_T pCtrlPktHdr, PVIRTQBUF pVirtqBuf)
{
LogFunc(("[%s] Processing CTRL MAC command\n", pThis->szInst));
AssertMsgReturn(pVirtqBuf->cbPhysSend >= sizeof(*pCtrlPktHdr),
("insufficient descriptor space for ctrl pkt hdr"),
VIRTIONET_ERROR);
size_t cbRemaining = pVirtqBuf->cbPhysSend;
switch(pCtrlPktHdr->uCmd)
{
// ...
case VIRTIONET_CTRL_MAC_TABLE_SET:
{
VIRTIONET_CTRL_MAC_TABLE_LEN cMacs;
/* Load unicast MAC filter table */
AssertMsgReturn(cbRemaining >= sizeof(cMacs),
("DESC chain too small to process CTRL_MAC_TABLE_SET cmd\n"), VIRTIONET_ERROR);
/* Fetch count of unicast filter MACs from guest buffer */...
Affected versions
| Package | Affected | Fixed in |
|---|---|---|
| VirtualBox Product | < https://www.virtualbox.org/changeset/101400/vbox | https://www.virtualbox.org/changeset/101400/vbox |
Details and references
### Summary A guest inside a VirtualBox VM using the virtio-net network adapter can trigger an integer overflow leading to out-of-bounds read in `src/VBox/Devices/Network/DevVirtioNet.cpp` to cause a denial-of-service or leak information of the hypervisor. ### Severity High - An attacker with high privileges in the guest can cause a denial-of-service or leak information of the hypervisor. ### Proof of Concept The following function handles a `VIRTIONET_CTRL_MAC` control command which fetches multiple 32bit `cMacs` values from the guest: ```c++ static uint8_t virtioNetR3CtrlMac(PVIRTIONET pThis, PVIRTIONET_CTRL_HDR_T pCtrlPktHdr, PVIRTQBUF pVirtqBuf) { LogFunc(("[%s] Processing CTRL MAC command\n", pThis->szInst)); AssertMsgReturn(pVirtqBuf->cbPhysSend >= sizeof(*pCtrlPktHdr), ("insufficient descriptor space for ctrl pkt hdr"), VIRTIONET_ERROR); size_t cbRemaining = pVirtqBuf->cbPhysSend; switch(pCtrlPktHdr->uCmd) { // ... case VIRTIONET_CTRL_MAC_TABLE_SET: { VIRTIONET_CTRL_MAC_TABLE_LEN cMacs; /* Load unicast MAC filter table */ AssertMsgReturn(cbRemaining >= sizeof(cMacs), ("DESC chain too small to process CTRL_MAC_TABLE_SET cmd\n"), VIRTIONET_ERROR); /* Fetch count of unicast filter MACs from guest buffer */ virtioCoreR3VirtqBufDrain(&pThis->Virtio, pVirtqBuf, &cMacs, sizeof(cMacs)); cbRemaining -= sizeof(cMacs); Log7Func(("[%s] Guest provided %d unicast MAC Table entries\n", pThis->szInst, cMacs)); if (cMacs) { uint32_t cbMacs = cMacs * sizeof(RTMAC); AssertMsgReturn(cbMacs <= sizeof(pThis->aMacUnicastFilter) / sizeof(RTMAC), ("Guest provided Unicast MAC filter table exceeds hardcoded table size"), VIRTIONET_ERROR); AssertMsgReturn(cbRemaining >= cbMacs, ("Virtq buffer too small to process CTRL_MAC_TABLE_SET cmd\n"), VIRTIONET_ERROR); /* Fetch unicast table contents from guest buffer */ virtioCoreR3VirtqBufDrain(&pThis->Virtio, pVirtqBuf, &pThis->aMacUnicastFilter, cbMacs); cbRemaining -= cbMacs; } pThis->cUnicastFilterMacs = cMacs; /* Load multicast MAC filter table */ AssertMsgReturn(cbRemaining >= sizeof(cMacs), ("Virtq buffer too small to process CTRL_MAC_TABLE_SET cmd\n"), VIRTIONET_ERROR); /* Fetch count of multicast filter MACs from guest buffer */ virtioCoreR3VirtqBufDrain(&pThis->Virtio, pVirtqBuf, &cMacs, sizeof(cMacs)); cbRemaining -= sizeof(cMacs); Log10Func(("[%s] Guest provided %d multicast MAC Table entries\n", pThis->szInst, cMacs)); if (cMacs) { uint32_t cbMacs = cMacs * sizeof(RTMAC); AssertMsgReturn(cbMacs <= sizeof(pThis->aMacMulticastFilter) / sizeof(RTMAC), ("Guest provided Unicast MAC filter table exceeds hardcoded table size"), VIRTIONET_ERROR); AssertMsgReturn(cbRemaining >= cbMacs, ("Virtq buffer too small to process CTRL_MAC_TABLE_SET cmd\n"), VIRTIONET_ERROR); /* Fetch multicast table contents from guest buffer */ virtioCoreR3VirtqBufDrain(&pThis->Virtio, pVirtqBuf, &pThis->aMacMulticastFilter, cbMacs); cbRemaining -= cbMacs; } pThis->cMulticastFilterMacs = cMacs; // ... break; } default: LogRelFunc(("Unrecognized MAC subcommand in CTRL pkt from guest\n")); return VIRTIONET_ERROR; } return VIRTIONET_OK; } ``` There are
- Severity from
- GitHub (reviewed advisory)