VirtualBox

Changeset 20797 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Jun 22, 2009 7:22:10 PM (15 years ago)
Author:
vboxsync
Message:

VHD: Fix access beyond the data block bitmap with ASMBitTest and ASMBitSet. Fix crash with snapshots

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/VHDHDDCore.cpp

    r20695 r20797  
    223223
    224224/**
     225 * Internal: Allocates the block bitmap rounding up to the next 32bit boundary.
     226 *           Can be freed with RTMemFree. The memory is zeroed.
     227 */
     228DECLINLINE(uint8_t *)vhdBlockBitmapAllocate(PVHDIMAGE pImage)
     229{
     230    return (uint8_t *)RTMemAllocZ(RT_ALIGN_T(pImage->cbDataBlockBitmap, 4, uint32_t));
     231}
     232
     233/**
    225234 * Internal: Compute and update header checksum.
    226235 */
     
    373382        if (ddh.ParentLocatorEntry[i].u32Code != RT_H2BE_U32(VHD_PLATFORM_CODE_NONE))
    374383        {
    375             rc = vhdLocatorUpdate(pImage, &ddh.ParentLocatorEntry[i], pImage->pszParentFilename);
    376             if (RT_FAILURE(rc))
    377                 goto out;
     384            if (pImage->pszParentFilename)
     385            {
     386                rc = vhdLocatorUpdate(pImage, &ddh.ParentLocatorEntry[i], pImage->pszParentFilename);
     387                if (RT_FAILURE(rc))
     388                    goto out;
     389            }
     390            else
     391            {
     392                /* The parent was deleted. */
     393                ddh.ParentLocatorEntry[i].u32Code = RT_H2BE_U32(VHD_PLATFORM_CODE_NONE);
     394            }
    378395        }
    379396    }
     
    546563    LogFlowFunc(("cbDataBlockBitmap=%u\n", pImage->cbDataBlockBitmap));
    547564
    548     pImage->pu8Bitmap = (uint8_t *)RTMemAllocZ(pImage->cbDataBlockBitmap);
     565    pImage->pu8Bitmap = vhdBlockBitmapAllocate(pImage);
    549566    if (!pImage->pu8Bitmap)
    550567        return VERR_NO_MEMORY;
     
    889906}
    890907
     908/**
     909 * Internal: Checks if a sector in the block bitmap is set
     910 */
     911DECLINLINE(bool) vhdBlockBitmapSectorContainsData(PVHDIMAGE pImage, uint32_t cBlockBitmapEntry)
     912{
     913    uint32_t iBitmap = (cBlockBitmapEntry / 8) & ~3; /* Byte in the block bitmap. */
     914
     915    /*
     916     * The index of the bit in the byte of the data block bitmap.
     917     * The most signifcant bit stands for a lower sector number.
     918     */
     919    uint8_t  iBitInByte = (32-1) - (cBlockBitmapEntry % 32);
     920    uint8_t *puBitmap = pImage->pu8Bitmap + iBitmap;
     921
     922    AssertMsg(puBitmap < (pImage->pu8Bitmap + pImage->cbDataBlockBitmap),
     923                ("VHD: Current bitmap position exceeds maximum size of the bitmap\n"));
     924
     925    return ASMBitTest(puBitmap, iBitInByte);
     926}
     927
     928/**
     929 * Internal: Sets the given sector in the sector bitmap.
     930 */
     931DECLINLINE(void) vhdBlockBitmapSectorSet(PVHDIMAGE pImage, uint32_t cBlockBitmapEntry)
     932{
     933    uint32_t iBitmap = (cBlockBitmapEntry / 8) & ~3; /* Byte in the block bitmap. */
     934
     935    /*
     936     * The index of the bit in the byte of the data block bitmap.
     937     * The most signifcant bit stands for a lower sector number.
     938     */
     939    uint8_t  iBitInByte = (32-1) - (cBlockBitmapEntry % 32);
     940    uint8_t  *puBitmap  = pImage->pu8Bitmap + iBitmap;
     941
     942    AssertMsg(puBitmap < (pImage->pu8Bitmap + pImage->cbDataBlockBitmap),
     943                ("VHD: Current bitmap position exceeds maximum size of the bitmap\n"));
     944
     945    ASMBitSet(puBitmap, iBitInByte);
     946}
     947
    891948static int vhdRead(void *pBackendData, uint64_t uOffset, void *pvBuf, size_t cbRead, size_t *pcbActuallyRead)
    892949{
     
    939996        {
    940997            uint32_t cSectors = 0;
    941             uint32_t iBitmap = cBATEntryIndex / 8; /* Byte in the block bitmap. */
    942             Assert(iBitmap < pImage->cbDataBlockBitmap);
    943 
    944             /*
    945              * The index of the bit in the byte of the data block bitmap.
    946              * The most signifcant bit stands for a lower sector number.
    947              *
    948              * There are 8 bits in a byte but they go from 0 .. 7
    949              * hence the (8 - 1) to get the index in the bitmap byte.
    950              */
    951             uint8_t  iBitInByte = (8 - 1) - (cBATEntryIndex % 8);
    952             uint8_t *puBitmap   = pImage->pu8Bitmap + iBitmap;
    953 
    954             if (ASMBitTest(puBitmap, iBitInByte))
     998
     999            if (vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex))
    9551000            {
    956                 uint32_t iBATEntryIndexCurr = cBATEntryIndex + 1;
    957 
     1001                cBATEntryIndex++;
    9581002                cSectors = 1;
    9591003
     
    9631007                 * must be read from child.
    9641008                 */
    965                 while (cSectors < (cbRead / VHD_SECTOR_SIZE))
     1009                while (   (cSectors < (cbRead / VHD_SECTOR_SIZE))
     1010                       && vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex))
    9661011                {
    967 
    968                     iBitmap    = iBATEntryIndexCurr / 8; /* Byte in the block bitmap. */
    969                     iBitInByte = (8 - 1) - (iBATEntryIndexCurr % 8);
    970                     puBitmap  = pImage->pu8Bitmap + iBitmap;
    971                     AssertMsg(puBitmap < (pImage->pu8Bitmap + pImage->cbDataBlockBitmap),
    972                               ("VHD: Current bitmap position exceeds maximum size of the bitmap\n"));
    973                     if (!ASMBitTest(puBitmap, iBitInByte))
    974                         break;
    975 
    976                     iBATEntryIndexCurr++;
     1012                    cBATEntryIndex++;
    9771013                    cSectors++;
    9781014                }
     
    9851021            else
    9861022            {
    987                 uint32_t iBATEntryIndexCurr = cBATEntryIndex + 1;
    988 
    9891023                /*
    9901024                 * The first sector being read is marked clean, so we should read from
     
    9951029                 * should be read from the parent.
    9961030                 */
    997 
     1031                cBATEntryIndex++;
    9981032                cSectors = 1;
    9991033
    1000                 while (cSectors < (cbRead / VHD_SECTOR_SIZE))
     1034                while (   (cSectors < (cbRead / VHD_SECTOR_SIZE))
     1035                       && !vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex))
    10011036                {
    1002                     iBitmap    = iBATEntryIndexCurr / 8; /* Byte in the block bitmap. */
    1003                     iBitInByte = (8 - 1) - (iBATEntryIndexCurr % 8);
    1004                     puBitmap  = pImage->pu8Bitmap + iBitmap;
    1005                     AssertMsg(puBitmap < (pImage->pu8Bitmap + pImage->cbDataBlockBitmap),
    1006                               ("VHD: Current bitmap position exceeds maximum size of the bitmap\n"));
    1007                     if (ASMBitTest(puBitmap, iBitInByte))
    1008                         break;
    1009 
    1010                     iBATEntryIndexCurr++;
     1037                    cBATEntryIndex++;
    10111038                    cSectors++;
    10121039                }
     
    11201147            for (uint32_t iSector = 0; iSector < (cbToWrite / VHD_SECTOR_SIZE); iSector++)
    11211148            {
    1122                 uint32_t iBitmap    = cBATEntryIndex / 8; /* Byte in the block bitmap. */
    1123                 uint8_t  iBitInByte = (8 - 1) - (cBATEntryIndex % 8);
    1124                 uint8_t  *puBitmap  = pImage->pu8Bitmap + iBitmap;
    1125 
    1126                 ASMBitSet(puBitmap, iBitInByte);
     1149                vhdBlockBitmapSectorSet(pImage, cBATEntryIndex);
    11271150                cBATEntryIndex++;
    11281151            }
     
    15271550    pImage->cbDataBlockBitmap       = pImage->cSectorsPerDataBlock / 8;
    15281551    pImage->cDataBlockBitmapSectors = pImage->cbDataBlockBitmap / VHD_SECTOR_SIZE;
    1529     pImage->pu8Bitmap               = (uint8_t *)RTMemAllocZ(pImage->cbDataBlockBitmap);
     1552    pImage->pu8Bitmap               = vhdBlockBitmapAllocate(pImage);
    15301553    if (!pImage->pu8Bitmap)
    15311554        return vhdError(pImage, VERR_NO_MEMORY, RT_SRC_POS, N_("VHD: cannot allocate memory for bitmap storage"));
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