VirtualBox

Changeset 98846 in vbox for trunk


Ignore:
Timestamp:
Mar 6, 2023 6:56:23 PM (2 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
156169
Message:

Main/Medium+VirtualBox: If Medium::close() and VirtualBox::i_registerMedium()
are running concurrently they can wrestle over the media tree lock and
end up registering a medium which is in the process of being closed. If
both of the respective threads are operating on the same medium then there
is a window of opportunity when Medium::i_close() drops the media tree
lock before calling Medium::uninit() that VirtualBox::i_registerMedium()
can grab the lock and register the medium. The fix is to check whether
the medium is in the process of being closed inside i_registerMedium()
and bail out if so to maintain media registry consistency. bugref:6447

Location:
trunk/src/VBox/Main
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/include/MediumImpl.h

    r98291 r98846  
    117117    MediumVariant_T i_getVariant() const;
    118118    bool i_isHostDrive() const;
     119    bool i_isClosing() const;
    119120    const Utf8Str& i_getLocationFull() const;
    120121    const Utf8Str& i_getFormat() const;
  • trunk/src/VBox/Main/src-server/MediumImpl.cpp

    r98352 r98846  
    14481448                break;
    14491449            hrc = aVirtualBox->i_registerMedium(pActualMedium, &pActualMedium, mediaTreeLock, true /*fCalledFromMediumInit*/);
    1450             if (FAILED(hrc))
    1451                 break;
    1452 
    1453             if (pActualMedium == pMedium)
     1450            if (SUCCEEDED(hrc) && pActualMedium == pMedium)
    14541451            {
    14551452                /* It is a truly new medium, remember details for cleanup. */
     
    14731470            pMedium.setNull();
    14741471            mediaTreeLock.acquire();
     1472
     1473            if (FAILED(hrc))
     1474                break;
    14751475        }
    14761476
     
    43864386
    43874387/**
     4388 * Internal method which returns true if this medium is in the process of being closed.
     4389 * @return
     4390 */
     4391bool Medium::i_isClosing() const
     4392{
     4393    return m->fClosing;
     4394}
     4395
     4396/**
    43884397 * Internal method to return the medium's full location. Must have caller + locking!
    43894398 * @return
     
    57035712    }
    57045713
    5705     // Keep the locks held until after uninit, as otherwise the consistency
    5706     // of the medium tree cannot be guaranteed.
    57075714    uninit();
    57085715
  • trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp

    r98836 r98846  
    51105110        strLocationFull = pMedium->i_getLocationFull();
    51115111        pParent = pMedium->i_getParent();
     5112
     5113        /*
     5114         * If a separate thread has called Medium::close() for this medium at the same
     5115         * time as this i_registerMedium() call then there is a window of opportunity in
     5116         * Medium::i_close() where the media tree lock is dropped before calling
     5117         * Medium::uninit() (which reacquires the lock) that we can end up here attempting
     5118         * to register a medium which is in the process of being closed.  In addition, if
     5119         * this is a differencing medium and Medium::close() is in progress for one its
     5120         * parent media then we are similarly operating on a media registry in flux.  In
     5121         * either case registering a medium just before calling Medium::uninit() will
     5122         * lead to an inconsistent media registry so bail out here since Medium::close()
     5123         * got to this medium (or one of its parents) first.
     5124         */
     5125        if (devType == DeviceType_HardDisk)
     5126        {
     5127            ComObjPtr<Medium> pTmpMedium = pMedium;
     5128            while (pTmpMedium.isNotNull())
     5129            {
     5130                AutoCaller mediumAC(pTmpMedium);
     5131                if (FAILED(mediumAC.hrc())) return mediumAC.hrc();
     5132                AutoReadLock mlock(pTmpMedium COMMA_LOCKVAL_SRC_POS);
     5133
     5134                if (pTmpMedium->i_isClosing())
     5135                    return setError(E_INVALIDARG,
     5136                                    tr("Cannot register %s '%s' {%RTuuid} because it is in the process of being closed"),
     5137                                    pszDevType,
     5138                                    pTmpMedium->i_getLocationFull().c_str(),
     5139                                    pTmpMedium->i_getId().raw());
     5140
     5141                pTmpMedium = pTmpMedium->i_getParent();
     5142            }
     5143        }
    51125144    }
    51135145
Note: See TracChangeset for help on using the changeset viewer.

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