VirtualBox

Changeset 40713 in vbox for trunk/src/VBox/Storage/VDI.cpp


Ignore:
Timestamp:
Mar 29, 2012 4:06:14 PM (13 years ago)
Author:
vboxsync
Message:

Storage/VDI: Check for out of bounds access when reading from an image

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Storage/VDI.cpp

    r40241 r40713  
    487487         */
    488488        rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, cbTotal);
     489        pImage->cbImage = cbTotal;
    489490    }
    490491    else
     
    492493        /* Set file size to hold header and blocks array. */
    493494        rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, pImage->offStartData);
     495        pImage->cbImage = pImage->offStartData;
    494496    }
    495497    if (RT_FAILURE(rc))
     
    615617        /* Do NOT signal an appropriate error here, as the VD layer has the
    616618         * choice of retrying the open if it failed. */
     619        goto out;
     620    }
     621
     622    /* Get file size. */
     623    rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage,
     624                              &pImage->cbImage);
     625    if (RT_FAILURE(rc))
     626    {
     627        vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VDI: error getting the image size in '%s'"), pImage->pszFilename);
     628        rc = VERR_VD_VDI_INVALID_HEADER;
    617629        goto out;
    618630    }
     
    962974            break;
    963975
    964         /* Set new file size. */
    965         rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &cbImage);
    966         if (RT_FAILURE(rc))
    967             break;
    968 
    969         LogFlowFunc(("Set new size %llu\n", cbImage - pImage->cbTotalBlockData));
    970         rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, cbImage - pImage->cbTotalBlockData);
     976        pImage->cbImage -= pImage->cbTotalBlockData;
     977        LogFlowFunc(("Set new size %llu\n", pImage->cbImage));
     978        rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, pImage->cbImage);
    971979    } while (0);
    972980
     
    10461054                break;
    10471055
    1048             /* Set new file size. */
    1049             rc2 = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &cbImage);
    1050             if (RT_FAILURE(rc2))
    1051                 break;
    1052 
    1053             LogFlowFunc(("Set new size %llu\n", cbImage - pImage->cbTotalBlockData));
    1054             rc2 = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, cbImage - pImage->cbTotalBlockData);
     1056            pImage->cbImage -= pImage->cbTotalBlockData;
     1057            LogFlowFunc(("Set new size %llu\n", pImage->cbImage));
     1058            rc2 = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, pImage->cbImage);
    10551059            if (RT_FAILURE(rc2))
    10561060                rc = rc2;
     
    11441148
    11451149    pbmAllocationBitmap = RTMemAllocZ(cSectors / 8);
     1150    if (!pbmAllocationBitmap)
     1151        return NULL;
    11461152
    11471153    while (uSectorCur < cSectors)
     
    11641170}
    11651171
     1172
     1173/**
     1174 * Updates the state of the async cluster allocation.
     1175 *
     1176 * @returns VBox status code.
     1177 * @param   pBackendData    The opaque backend data.
     1178 * @param   pIoCtx          I/O context associated with this request.
     1179 * @param   pvUser          Opaque user data passed during a read/write request.
     1180 * @param   rcReq           Status code for the completed request.
     1181 */
     1182static DECLCALLBACK(int) vdiAsyncBlockAllocUpdate(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq)
     1183{
     1184    int rc = VINF_SUCCESS;
     1185    PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData;
     1186    PVDIASYNCBLOCKALLOC pBlockAlloc = (PVDIASYNCBLOCKALLOC)pvUser;
     1187
     1188    if (RT_SUCCESS(rcReq))
     1189    {
     1190        pImage->cbImage += pImage->cbTotalBlockData;
     1191        pImage->paBlocks[pBlockAlloc->uBlock] = pBlockAlloc->cBlocksAllocated;
     1192
     1193        if (pImage->paBlocksRev)
     1194            pImage->paBlocksRev[pBlockAlloc->cBlocksAllocated] = pBlockAlloc->uBlock;
     1195
     1196        setImageBlocksAllocated(&pImage->Header, pBlockAlloc->cBlocksAllocated + 1);
     1197        rc = vdiUpdateBlockInfoAsync(pImage, pBlockAlloc->uBlock, pIoCtx,
     1198                                     true /* fUpdateHdr */);
     1199    }
     1200    /* else: I/O error don't update the block table. */
     1201
     1202    RTMemFree(pBlockAlloc);
     1203    return rc;
     1204}
    11661205
    11671206/** @copydoc VBOXHDDBACKEND::pfnCheckIfValid */
     
    12651304    void *pvUser = NULL;
    12661305    PVDINTERFACEPROGRESS pIfProgress = VDIfProgressGet(pVDIfsOperation);
     1306    if (pIfProgress)
     1307    {
     1308        pfnProgress = pIfProgress->pfnProgress;
     1309        pvUser = pIfProgress->Core.pvUser;
     1310    }
    12671311
    12681312    /* Check the image flags. */
     
    14411485        uint64_t u64Offset = (uint64_t)pImage->paBlocks[uBlock] * pImage->cbTotalBlockData
    14421486                           + (pImage->offStartData + pImage->offStartBlockData + offRead);
    1443         rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, u64Offset,
    1444                                    pvBuf, cbToRead, NULL);
     1487
     1488        if (u64Offset + cbToRead <= pImage->cbImage)
     1489            rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, u64Offset,
     1490                                       pvBuf, cbToRead, NULL);
     1491        else
     1492        {
     1493            LogRel(("VDI: Out of range access (%llu) in image %s, image size %llu\n",
     1494                    u64Offset, pImage->pszFilename, pImage->cbImage));
     1495            memset(pvBuf, 0, cbToRead);
     1496            rc = VERR_VD_READ_OUT_OF_RANGE;
     1497        }
    14451498    }
    14461499
     
    15401593                    goto out;
    15411594
     1595                pImage->cbImage += cbToWrite;
    15421596                *pcbPreRead = 0;
    15431597                *pcbPostRead = 0;
     
    22432297        uint64_t u64Offset = (uint64_t)pImage->paBlocks[uBlock] * pImage->cbTotalBlockData
    22442298                           + (pImage->offStartData + pImage->offStartBlockData + offRead);
    2245         rc = vdIfIoIntFileReadUserAsync(pImage->pIfIo, pImage->pStorage, u64Offset,
    2246                                         pIoCtx, cbToRead);
     2299
     2300        if (u64Offset + cbToRead <= pImage->cbImage)
     2301            rc = vdIfIoIntFileReadUserAsync(pImage->pIfIo, pImage->pStorage, u64Offset,
     2302                                            pIoCtx, cbToRead);
     2303        else
     2304        {
     2305            LogRel(("VDI: Out of range access (%llu) in image %s, image size %llu\n",
     2306                    u64Offset, pImage->pszFilename, pImage->cbImage));
     2307            vdIfIoIntIoCtxSet(pImage->pIfIo, pIoCtx, 0, cbToRead);
     2308            rc = VERR_VD_READ_OUT_OF_RANGE;
     2309        }
    22472310    }
    22482311
     
    23252388                 * Allocate block and write data. */
    23262389                Assert(!offWrite);
     2390                PVDIASYNCBLOCKALLOC pBlockAlloc = (PVDIASYNCBLOCKALLOC)RTMemAllocZ(sizeof(VDIASYNCBLOCKALLOC));
     2391                if (!pBlockAlloc)
     2392                {
     2393                    rc = VERR_NO_MEMORY;
     2394                    break;
     2395                }
     2396
    23272397                unsigned cBlocksAllocated = getImageBlocksAllocated(&pImage->Header);
    23282398                uint64_t u64Offset = (uint64_t)cBlocksAllocated * pImage->cbTotalBlockData
    23292399                                   + (pImage->offStartData + pImage->offStartBlockData);
    2330                 rc = vdIfIoIntFileWriteUserAsync(pImage->pIfIo, pImage->pStorage,
    2331                                                  u64Offset, pIoCtx, cbToWrite, NULL, NULL);
    2332                 if (RT_UNLIKELY(RT_FAILURE_NP(rc) && (rc != VERR_VD_ASYNC_IO_IN_PROGRESS)))
    2333                     goto out;
    2334                 pImage->paBlocks[uBlock] = cBlocksAllocated;
    2335 
    2336                 if (pImage->paBlocksRev)
    2337                     pImage->paBlocksRev[cBlocksAllocated] = uBlock;
    2338 
    2339                 setImageBlocksAllocated(&pImage->Header, cBlocksAllocated + 1);
    2340 
    2341                 rc = vdiUpdateBlockInfoAsync(pImage, uBlock, pIoCtx, true /* fUpdateHdr */);
    2342                 if (RT_FAILURE(rc) && (rc != VERR_VD_ASYNC_IO_IN_PROGRESS))
    2343                     goto out;
     2400
     2401                pBlockAlloc->cBlocksAllocated = cBlocksAllocated;
     2402                pBlockAlloc->uBlock           = uBlock;
    23442403
    23452404                *pcbPreRead = 0;
    23462405                *pcbPostRead = 0;
     2406
     2407                rc = vdIfIoIntFileWriteUserAsync(pImage->pIfIo, pImage->pStorage,
     2408                                                 u64Offset, pIoCtx, cbToWrite,
     2409                                                 vdiAsyncBlockAllocUpdate, pBlockAlloc);
     2410                if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
     2411                    break;
     2412                else if (RT_FAILURE(rc))
     2413                {
     2414                    RTMemFree(pBlockAlloc);
     2415                    break;
     2416                }
     2417
     2418                rc = vdiAsyncBlockAllocUpdate(pImage, pIoCtx, pBlockAlloc, rc);
    23472419            }
    23482420            else
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette