VirtualBox

Changeset 83564 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Apr 5, 2020 2:14:13 PM (5 years ago)
Author:
vboxsync
Message:

VMM/MMR3Heap: Zero on free and realloc. Always unlink _before_ realloc. bugref:9698

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/MMHeap.cpp

    r82968 r83564  
    304304
    305305/**
     306 * Links @a pHdr into the heap block list (tail).
     307 *
     308 * @param   pHeap       Heap handle.
     309 * @param   pHdr        The block to link.
     310 *
     311 * @note    Caller has locked the heap!
     312 */
     313DECLINLINE(void) mmR3HeapLink(PMMHEAP pHeap, PMMHEAPHDR pHdr)
     314{
     315    /* Tail insertion: */
     316    pHdr->pNext = NULL;
     317    PMMHEAPHDR pTail = pHeap->pTail;
     318    pHdr->pPrev = pTail;
     319    if (pTail)
     320    {
     321        Assert(!pTail->pNext);
     322        pTail->pNext = pHdr;
     323    }
     324    else
     325    {
     326        Assert(!pHeap->pHead);
     327        pHeap->pHead = pHdr;
     328    }
     329    pHeap->pTail = pHdr;
     330}
     331
     332
     333/**
     334 * Unlinks @a pHdr from the heal block list.
     335 *
     336 * @param   pHeap       Heap handle.
     337 * @param   pHdr        The block to unlink.
     338 *
     339 * @note    Caller has locked the heap!
     340 */
     341DECLINLINE(void) mmR3HeapUnlink(PMMHEAP pHeap, PMMHEAPHDR pHdr)
     342{
     343    PMMHEAPHDR const pPrev = pHdr->pPrev;
     344    PMMHEAPHDR const pNext = pHdr->pNext;
     345    if (pPrev)
     346        pPrev->pNext = pNext;
     347    else
     348        pHeap->pHead = pNext;
     349
     350    if (pNext)
     351        pNext->pPrev = pPrev;
     352    else
     353        pHeap->pTail = pHdr->pPrev;
     354}
     355
     356
     357/**
    306358 * Allocate memory from the heap.
    307359 *
     
    373425        RTCritSectLeave(&pHeap->Lock);
    374426#endif
     427        AssertFailed();
    375428        return NULL;
    376429    }
     
    380433     */
    381434    cbSize = RT_ALIGN_Z(cbSize, MMR3HEAP_SIZE_ALIGNMENT) + sizeof(MMHEAPHDR);
    382     PMMHEAPHDR  pHdr = (PMMHEAPHDR)(fZero ? RTMemAllocZ(cbSize) : RTMemAlloc(cbSize));
    383     if (!pHdr)
     435    PMMHEAPHDR const pHdr = (PMMHEAPHDR)(fZero ? RTMemAllocZ(cbSize) : RTMemAlloc(cbSize));
     436    if (pHdr)
     437    { /* likely */ }
     438    else
    384439    {
    385440        AssertMsgFailed(("Failed to allocate heap block %d, enmTag=%x(%.4s).\n", cbSize, enmTag, &enmTag));
     
    394449    Assert(!((uintptr_t)pHdr & (RTMEM_ALIGNMENT - 1)));
    395450
    396     RTCritSectEnter(&pHeap->Lock);
    397 
    398451    /*
    399452     * Init and link in the header.
    400453     */
    401     pHdr->pNext = NULL;
    402     pHdr->pPrev = pHeap->pTail;
    403     if (pHdr->pPrev)
    404         pHdr->pPrev->pNext = pHdr;
    405     else
    406         pHeap->pHead = pHdr;
    407     pHeap->pTail = pHdr;
    408454#ifdef MMR3HEAP_WITH_STATISTICS
    409455    pHdr->pStat  = pStat;
     
    412458#endif
    413459    pHdr->cbSize = cbSize;
     460
     461    RTCritSectEnter(&pHeap->Lock);
     462
     463    mmR3HeapLink(pHeap, pHdr);
    414464
    415465    /*
     
    430480
    431481/**
    432  * Reallocate memory allocated with MMR3HeapAlloc() or MMR3HeapRealloc().
     482 * Reallocate memory allocated with MMR3HeapAlloc(), MMR3HeapAllocZ() or
     483 * MMR3HeapRealloc().
     484 *
     485 * Any additional memory is zeroed (only reliable if the initial allocation was
     486 * also of the zeroing kind).
    433487 *
    434488 * @returns Pointer to reallocated memory.
     
    455509     * Validate header.
    456510     */
    457     PMMHEAPHDR  pHdr = (PMMHEAPHDR)pv - 1;
    458     if (    pHdr->cbSize & (MMR3HEAP_SIZE_ALIGNMENT - 1)
    459         ||  (uintptr_t)pHdr & (RTMEM_ALIGNMENT - 1))
    460     {
    461         AssertMsgFailed(("Invalid heap header! pv=%p, size=%#x\n", pv, pHdr->cbSize));
    462         return NULL;
    463     }
     511    PMMHEAPHDR const pHdr      = (PMMHEAPHDR)pv - 1;
     512    size_t const     cbOldSize = pHdr->cbSize;
     513    AssertMsgReturn(   !(cbOldSize & (MMR3HEAP_SIZE_ALIGNMENT - 1))
     514                    && !((uintptr_t)pHdr & (RTMEM_ALIGNMENT - 1)),
     515                    ("Invalid heap header! pv=%p, size=%#x\n", pv, cbOldSize),
     516                    NULL);
    464517    Assert(pHdr->pStat != NULL);
    465518    Assert(!((uintptr_t)pHdr->pNext & (RTMEM_ALIGNMENT - 1)));
     
    468521    PMMHEAP pHeap = pHdr->pStat->pHeap;
    469522
    470 #ifdef MMR3HEAP_WITH_STATISTICS
     523    /*
     524     * Unlink the header before we reallocate the block.
     525     */
    471526    RTCritSectEnter(&pHeap->Lock);
     527#ifdef MMR3HEAP_WITH_STATISTICS
    472528    pHdr->pStat->cReallocations++;
    473529    pHeap->Stat.cReallocations++;
     530#endif
     531    mmR3HeapUnlink(pHeap, pHdr);
    474532    RTCritSectLeave(&pHeap->Lock);
    475 #endif
    476 
    477     /*
    478      * Reallocate the block.
     533
     534    /*
     535     * Reallocate the block.  Clear added space.
    479536     */
    480537    cbNewSize = RT_ALIGN_Z(cbNewSize, MMR3HEAP_SIZE_ALIGNMENT) + sizeof(MMHEAPHDR);
    481     PMMHEAPHDR pHdrNew = (PMMHEAPHDR)RTMemRealloc(pHdr, cbNewSize);
    482     if (!pHdrNew)
    483     {
    484 #ifdef MMR3HEAP_WITH_STATISTICS
     538    PMMHEAPHDR pHdrNew = (PMMHEAPHDR)RTMemReallocZ(pHdr, cbOldSize, cbNewSize);
     539    if (pHdrNew)
     540        pHdrNew->cbSize = cbNewSize;
     541    else
     542    {
    485543        RTCritSectEnter(&pHeap->Lock);
     544        mmR3HeapLink(pHeap, pHdr);
     545#ifdef MMR3HEAP_WITH_STATISTICS
    486546        pHdr->pStat->cFailures++;
    487547        pHeap->Stat.cFailures++;
     548#endif
    488549        RTCritSectLeave(&pHeap->Lock);
    489 #endif
    490550        return NULL;
    491551    }
    492552
    493     /*
    494      * Update pointers.
    495      */
    496     if (pHdrNew != pHdr)
    497     {
    498         RTCritSectEnter(&pHeap->Lock);
    499         if (pHdrNew->pPrev)
    500             pHdrNew->pPrev->pNext = pHdrNew;
    501         else
    502             pHeap->pHead = pHdrNew;
    503 
    504         if (pHdrNew->pNext)
    505             pHdrNew->pNext->pPrev = pHdrNew;
    506         else
    507             pHeap->pTail = pHdrNew;
    508         RTCritSectLeave(&pHeap->Lock);
    509     }
     553    RTCritSectEnter(&pHeap->Lock);
     554
     555    /*
     556     * Relink the header.
     557     */
     558    mmR3HeapLink(pHeap, pHdrNew);
    510559
    511560    /*
     
    513562     */
    514563#ifdef MMR3HEAP_WITH_STATISTICS
    515     RTCritSectEnter(&pHeap->Lock);
    516564    pHdrNew->pStat->cbAllocated += cbNewSize - pHdrNew->cbSize;
    517565    pHeap->Stat.cbAllocated += cbNewSize - pHdrNew->cbSize;
     566#endif
     567
    518568    RTCritSectLeave(&pHeap->Lock);
    519 #endif
    520 
    521     pHdrNew->cbSize = cbNewSize;
    522569
    523570    return pHdrNew + 1;
     
    650697 * Releases memory allocated with MMR3HeapAlloc() or MMR3HeapRealloc().
    651698 *
     699 * The memory is cleared/filled before freeing to prevent heap spraying, info
     700 * leaks, and help detect use after free trouble.
     701 *
    652702 * @param   pv          Pointer to the memory block to free.
    653703 */
     
    661711     * Validate header.
    662712     */
    663     PMMHEAPHDR  pHdr = (PMMHEAPHDR)pv - 1;
    664     if (    pHdr->cbSize & (MMR3HEAP_SIZE_ALIGNMENT - 1)
    665         ||  (uintptr_t)pHdr & (RTMEM_ALIGNMENT - 1))
    666     {
    667         AssertMsgFailed(("Invalid heap header! pv=%p, size=%#x\n", pv, pHdr->cbSize));
    668         return;
    669     }
    670     Assert(pHdr->pStat != NULL);
     713    PMMHEAPHDR const pHdr         = (PMMHEAPHDR)pv - 1;
     714    size_t const     cbAllocation = pHdr->cbSize;
     715    AssertMsgReturnVoid(   !(pHdr->cbSize & (MMR3HEAP_SIZE_ALIGNMENT - 1))
     716                        && !((uintptr_t)pHdr & (RTMEM_ALIGNMENT - 1)),
     717                        ("Invalid heap header! pv=%p, size=%#x\n", pv, pHdr->cbSize));
     718    AssertPtr(pHdr->pStat);
    671719    Assert(!((uintptr_t)pHdr->pNext & (RTMEM_ALIGNMENT - 1)));
    672720    Assert(!((uintptr_t)pHdr->pPrev & (RTMEM_ALIGNMENT - 1)));
     
    681729    pHdr->pStat->cFrees++;
    682730    pHeap->Stat.cFrees++;
    683     pHdr->pStat->cbFreed            += pHdr->cbSize;
    684     pHeap->Stat.cbFreed             += pHdr->cbSize;
    685     pHdr->pStat->cbCurAllocated     -= pHdr->cbSize;
    686     pHeap->Stat.cbCurAllocated      -= pHdr->cbSize;
     731    pHdr->pStat->cbFreed            += cbAllocation;
     732    pHeap->Stat.cbFreed             += cbAllocation;
     733    pHdr->pStat->cbCurAllocated     -= cbAllocation;
     734    pHeap->Stat.cbCurAllocated      -= cbAllocation;
    687735#endif
    688736
     
    690738     * Unlink it.
    691739     */
    692     if (pHdr->pPrev)
    693         pHdr->pPrev->pNext = pHdr->pNext;
    694     else
    695         pHeap->pHead = pHdr->pNext;
    696 
    697     if (pHdr->pNext)
    698         pHdr->pNext->pPrev = pHdr->pPrev;
    699     else
    700         pHeap->pTail = pHdr->pPrev;
     740    mmR3HeapUnlink(pHeap, pHdr);
    701741
    702742    RTCritSectLeave(&pHeap->Lock);
    703743
    704744    /*
    705      * Free the memory.
    706      */
    707     RTMemFree(pHdr);
    708 }
    709 
     745     * Free the memory.  We clear just to be on the safe size wrt
     746     * heap spraying and leaking sensitive info (also helps detecting
     747     * double freeing).
     748     */
     749    RTMemFreeZ(pHdr, cbAllocation);
     750}
     751
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