VirtualBox

Changeset 91625 in vbox


Ignore:
Timestamp:
Oct 7, 2021 9:17:12 PM (3 years ago)
Author:
vboxsync
Message:

SharedClipboard/common: ShClEventSignal must clear pEvent->pPayload if RTSemEventMultiSignal fails, otherwise it the payload could be freed twice. Don't leak semaphores in ShClEventIdGenerateAndRegister failure path. Three longish r=bird comments on the insanity of the event interface. bugref:9437

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/GuestHost/SharedClipboard/clipboard-common.cpp

    r87687 r91625  
    232232    AssertMsgFailed(("Unable to register a new event ID for event source %RU16\n", pSource->uID));
    233233
     234    RTSemEventMultiDestroy(pEvent->hEvtMulSem);
     235    pEvent->hEvtMulSem = NIL_RTSEMEVENTMULTI;
    234236    RTMemFree(pEvent);
    235237    return NIL_SHCLEVENTID;
     
    324326 * @returns VBox status code.
    325327 * @param   pSource             Event source to unregister event for.
    326  * @param   uID                 Event ID to unregister.
     328 * @param   uID                 Event ID to unregister.
     329 * 
     330 * @todo    r=bird: The caller must enter crit sect protecting the event source
     331 *          here, must it?  See explanation in ShClEventWait.
    327332 */
    328333int ShClEventUnregister(PSHCLEVENTSOURCE pSource, SHCLEVENTID uID)
     
    364369 * @param   ppPayload           Where to store the (allocated) event payload on success. Needs to be free'd with
    365370 *                              SharedClipboardPayloadFree(). Optional.
    366  */
    367 int ShClEventWait(PSHCLEVENTSOURCE pSource, SHCLEVENTID uID, RTMSINTERVAL uTimeoutMs,
    368                   PSHCLEVENTPAYLOAD* ppPayload)
     371 *
     372 * @todo    r=bird: Locking protocol is totally buggered here, or at least not
     373 *          explained in any way whatsoever.  We cannot really do shclEventGet
     374 *          and shclEventPayloadDetachInternal w/o holding the critical section
     375 *          protecting that list, otherwise wtf is the point of the locking.
     376 *
     377 *          More to the point, ShClEventSignal is called on the HGCM service
     378 *          thread and would be racing the host clipboard worker thread/whomever
     379 *          sent the request and is making this call closely followed by
     380 *          ShClEventRelease and ShClEventUnregister.  The waiting here might be
     381 *          safe if there can only ever be one single thread making these kind
     382 *          of requests, but the unregistering is _not_ safe w/o holding the
     383 *          lock and that isn't explained anywhere that I can see.
     384 */
     385int ShClEventWait(PSHCLEVENTSOURCE pSource, SHCLEVENTID uID, RTMSINTERVAL uTimeoutMs, PSHCLEVENTPAYLOAD *ppPayload)
    369386{
    370387    AssertPtrReturn(pSource, VERR_INVALID_POINTER);
    371     /** ppPayload is optional. */
    372 
     388    AssertPtrNullReturn(ppPayload, VERR_INVALID_POINTER);
    373389    LogFlowFuncEnter();
    374390
     
    425441 * @param   pSource             Event source of event to release.
    426442 * @param   idEvent             ID of event to release.
     443 *
     444 * @todo    r=bird: The two places this is currently used make my head explode.
     445 *          First you release then you unregister it.  Unregister frees is
     446 *          unconditionally.
     447 *
     448 *          Any sane thinking person would assume that after we've release our
     449 *          reference to the @a idEvent, we cannot touch it any more because we
     450 *          don't have a valid reference any more.  So, when ShClEventUnregister
     451 *          is then called and unconditionally frees the event: Boooooom!
     452 *
     453 *          The locking interface here is generally not sane either, as the
     454 *          locking isn't done on the @a pSource but something the caller needs
     455 *          implements.  Since we don't have access to the lock we cannot verify
     456 *          the locking protocol nor can we implement it (like in
     457 *          ShClEventWait).
     458 *
     459 *          A better interface would return PSHCLEVENT instead of SHCLEVENTID,
     460 *          and then you could work directly on that as an object, rather via a
     461 *          slow object list.  It would eliminate shclEventGet and any though
     462 *          that someone might be updating the list while shclEventGet traverses
     463 *          it.
    427464 */
    428465uint32_t ShClEventRelease(PSHCLEVENTSOURCE pSource, SHCLEVENTID idEvent)
    429466{
    430467    PSHCLEVENT pEvent = shclEventGet(pSource, idEvent);
    431     if (!pEvent)
    432     {
    433         AssertFailed();
    434         return UINT32_MAX;
    435     }
    436 
     468    AssertReturn(pEvent, UINT32_MAX);
    437469    AssertReturn(pEvent->cRefs, UINT32_MAX); /* Sanity. Yeah, not atomic. */
    438470
     
    446478 * @param   pSource             Event source of event to signal.
    447479 * @param   uID                 Event ID to signal.
    448  * @param   pPayload            Event payload to associate. Takes ownership. Optional.
     480 * @param   pPayload            Event payload to associate. Takes ownership on
     481 *                              success. Optional.
    449482 *
    450483 * @note    Caller must enter crit sect protecting the event source!
    451484 */
    452 int ShClEventSignal(PSHCLEVENTSOURCE pSource, SHCLEVENTID uID,
    453                     PSHCLEVENTPAYLOAD pPayload)
     485int ShClEventSignal(PSHCLEVENTSOURCE pSource, SHCLEVENTID uID, PSHCLEVENTPAYLOAD pPayload)
    454486{
    455487    AssertPtrReturn(pSource, VERR_INVALID_POINTER);
     
    467499
    468500        rc = RTSemEventMultiSignal(pEvent->hEvtMulSem);
     501        if (RT_FAILURE(rc))
     502            pEvent->pPayload = NULL; /* (no race condition if consumer also enters the critical section) */
    469503    }
    470504    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