VirtualBox

Changeset 43785 in vbox for trunk


Ignore:
Timestamp:
Oct 31, 2012 3:01:55 PM (12 years ago)
Author:
vboxsync
Message:

HostServices/HostChannel: callback must not access a client structure directly.

Location:
trunk/src/VBox/HostServices/HostChannel
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostServices/HostChannel/HostChannel.cpp

    r43462 r43785  
    2222#include "HostChannel.h"
    2323
     24
    2425static DECLCALLBACK(void) HostChannelCallbackEvent(void *pvCallbacks, void *pvInstance,
    2526                                                   uint32_t u32Id, const void *pvEvent, uint32_t cbEvent);
     27static DECLCALLBACK(void) HostChannelCallbackDeleted(void *pvCallbacks, void *pvChannel);
    2628
    2729
     
    6365};
    6466
     67/* The channel callbacks context. The provider passes the pointer as a callback parameter.
     68 * Created for the provider and deleted when the provider says so.
     69 */
     70typedef struct VBOXHOSTCHCALLBACKCTX
     71{
     72    RTLISTNODE nodeClient;     /* In the client, for cleanup when a client disconnects. */
     73
     74    VBOXHOSTCHCLIENT *pClient; /* The client which uses the channel, NULL when the client does not exist. */
     75} VBOXHOSTCHCALLBACKCTX;
     76
    6577/* Only one service instance is supported. */
    6678static VBOXHOSTCHCTX g_ctx = { false };
     
    6880static VBOXHOSTCHANNELCALLBACKS g_callbacks =
    6981{
    70     HostChannelCallbackEvent
     82    HostChannelCallbackEvent,
     83    HostChannelCallbackDeleted
    7184};
    7285
     
    340353}
    341354
     355/*
     356 * Channel callback contexts.
     357 */
     358static int vhcCallbackCtxCreate(VBOXHOSTCHCLIENT *pClient, VBOXHOSTCHCALLBACKCTX **ppCallbackCtx)
     359{
     360    int rc = VINF_SUCCESS;
     361
     362    VBOXHOSTCHCALLBACKCTX *pCallbackCtx = (VBOXHOSTCHCALLBACKCTX *)RTMemAllocZ(sizeof(VBOXHOSTCHCALLBACKCTX));
     363
     364    if (pCallbackCtx != NULL)
     365    {
     366        /* The callback context is accessed by the providers threads. */
     367        rc = vboxHostChannelLock();
     368        if (RT_SUCCESS(rc))
     369        {
     370            RTListAppend(&pClient->listContexts, &pCallbackCtx->nodeClient);
     371            pCallbackCtx->pClient = pClient;
     372
     373            vboxHostChannelUnlock();
     374        }
     375        else
     376        {
     377            RTMemFree(pCallbackCtx);
     378        }
     379    }
     380    else
     381    {
     382        rc = VERR_NO_MEMORY;
     383    }
     384
     385    if (RT_SUCCESS(rc))
     386    {
     387        *ppCallbackCtx = pCallbackCtx;
     388    }
     389
     390    return rc;
     391}
     392
     393static int vhcCallbackCtxDelete(VBOXHOSTCHCALLBACKCTX *pCallbackCtx)
     394{
     395    int rc = vboxHostChannelLock();
     396    if (RT_SUCCESS(rc))
     397    {
     398        VBOXHOSTCHCLIENT *pClient = pCallbackCtx->pClient;
     399
     400        if (pClient != NULL)
     401        {
     402            /* The callback is associated with a client.
     403             * Check that the callback is in the list and remove it from the list.
     404             */
     405            bool fFound = false;
     406
     407            VBOXHOSTCHCALLBACKCTX *pIter;
     408            RTListForEach(&pClient->listContexts, pIter, VBOXHOSTCHCALLBACKCTX, nodeClient)
     409            {
     410                if (pIter == pCallbackCtx)
     411                {
     412                    fFound = true;
     413                    break;
     414                }
     415            }
     416
     417            if (fFound)
     418            {
     419                RTListNodeRemove(&pCallbackCtx->nodeClient);
     420            }
     421            else
     422            {
     423                AssertFailed();
     424                rc = VERR_INVALID_PARAMETER;
     425            }
     426        }
     427        else
     428        {
     429            /* It is not in the clients anymore. May be the client has been disconnected.
     430             * Just free the memory.
     431             */
     432        }
     433
     434        vboxHostChannelUnlock();
     435    }
     436
     437    if (RT_SUCCESS(rc))
     438    {
     439        RTMemFree(pCallbackCtx);
     440    }
     441
     442    return rc;
     443}
    342444
    343445/*
     
    383485    RTListInit(&pClient->listChannels);
    384486    RTListInit(&pClient->listEvents);
     487    RTListInit(&pClient->listContexts);
    385488
    386489    return VINF_SUCCESS;
     
    389492void vboxHostChannelClientDisconnect(VBOXHOSTCHCLIENT *pClient)
    390493{
     494    /* Clear the list of contexts. */
     495    int rc = vboxHostChannelLock();
     496    if (RT_SUCCESS(rc))
     497    {
     498        VBOXHOSTCHCALLBACKCTX *pIter;
     499        RTListForEach(&pClient->listContexts, pIter, VBOXHOSTCHCALLBACKCTX, nodeClient)
     500        {
     501            pIter->pClient = NULL;
     502        }
     503
     504        vboxHostChannelUnlock();
     505    }
     506
    391507    /* If there are attached channels, detach them. */
    392508    VBOXHOSTCHINSTANCE *pIter;
     
    418534        if (RT_SUCCESS(rc))
    419535        {
    420             void *pvChannel = NULL;
    421             rc = pProvider->iface.HostChannelAttach(pProvider->iface.pvProvider,
    422                                                     &pvChannel,
    423                                                     u32Flags,
    424                                                     &g_callbacks, pClient);
     536            VBOXHOSTCHCALLBACKCTX *pCallbackCtx = NULL;
     537            rc = vhcCallbackCtxCreate(pClient, &pCallbackCtx);
     538
    425539            if (RT_SUCCESS(rc))
    426540            {
    427                 vhcProviderAddRef(pProvider);
    428                 pInstance->pProvider = pProvider;
    429 
    430                 pInstance->pClient = pClient;
    431                 pInstance->pvChannel = pvChannel;
    432 
    433                 vhcInstanceAddRef(pInstance); /* Referenced by the list client's channels. */
    434                 RTListAppend(&pClient->listChannels, &pInstance->nodeClient);
    435 
    436                 vhcInstanceAddRef(pInstance); /* Referenced by the list of provider's channels. */
    437                 RTListAppend(&pProvider->listChannels, &pInstance->nodeProvider);
    438 
    439                 *pu32Handle = pInstance->u32Handle;
    440 
    441                 HOSTCHLOG(("HostChannel: Attach: (%d) handle %d\n", pClient->u32ClientID, pInstance->u32Handle));
     541                void *pvChannel = NULL;
     542                rc = pProvider->iface.HostChannelAttach(pProvider->iface.pvProvider,
     543                                                        &pvChannel,
     544                                                        u32Flags,
     545                                                        &g_callbacks, pCallbackCtx);
     546
     547                if (RT_SUCCESS(rc))
     548                {
     549                    vhcProviderAddRef(pProvider);
     550                    pInstance->pProvider = pProvider;
     551
     552                    pInstance->pClient = pClient;
     553                    pInstance->pvChannel = pvChannel;
     554
     555                    vhcInstanceAddRef(pInstance); /* Referenced by the list client's channels. */
     556                    RTListAppend(&pClient->listChannels, &pInstance->nodeClient);
     557
     558                    vhcInstanceAddRef(pInstance); /* Referenced by the list of provider's channels. */
     559                    RTListAppend(&pProvider->listChannels, &pInstance->nodeProvider);
     560
     561                    *pu32Handle = pInstance->u32Handle;
     562
     563                    HOSTCHLOG(("HostChannel: Attach: (%d) handle %d\n", pClient->u32ClientID, pInstance->u32Handle));
     564                }
     565
     566                if (RT_FAILURE(rc))
     567                {
     568                    vhcCallbackCtxDelete(pCallbackCtx);
     569                }
    442570            }
    443571
     
    626754}
    627755
     756/* @thread provider */
    628757static DECLCALLBACK(void) HostChannelCallbackEvent(void *pvCallbacks, void *pvChannel,
    629758                                                   uint32_t u32Id, const void *pvEvent, uint32_t cbEvent)
    630759{
    631     VBOXHOSTCHCLIENT *pClient = (VBOXHOSTCHCLIENT *)pvCallbacks;
     760    VBOXHOSTCHCALLBACKCTX *pCallbackCtx = (VBOXHOSTCHCALLBACKCTX *)pvCallbacks;
     761
     762    int rc = vboxHostChannelLock();
     763    if (RT_FAILURE(rc))
     764    {
     765        return;
     766    }
     767
     768    /* Check that the structure is still associated with a client.
     769     * The client can disconnect and will be invalid.
     770     */
     771    VBOXHOSTCHCLIENT *pClient = pCallbackCtx->pClient;
     772
     773    if (pClient == NULL)
     774    {
     775        vboxHostChannelUnlock();
     776
     777        HOSTCHLOG(("HostChannel: CallbackEvent[%p]: client gone.\n"));
     778
     779        /* The client does not exist anymore, skip the event. */
     780        return;
     781    }
     782
     783    bool fFound = false;
     784
     785    VBOXHOSTCHCALLBACKCTX *pIter;
     786    RTListForEach(&pClient->listContexts, pIter, VBOXHOSTCHCALLBACKCTX, nodeClient)
     787    {
     788        if (pIter == pCallbackCtx)
     789        {
     790            fFound = true;
     791            break;
     792        }
     793    }
     794
     795    if (!fFound)
     796    {
     797        AssertFailed();
     798
     799        vboxHostChannelUnlock();
     800
     801        HOSTCHLOG(("HostChannel: CallbackEvent[%p]: client does not have the context.\n"));
     802
     803        /* The context is not in the list of contexts. Skip the event. */
     804        return;
     805    }
    632806
    633807    VBOXHOSTCHINSTANCE *pInstance = vhcInstanceFindByChannelPtr(pClient, pvChannel);
    634808
    635     HOSTCHLOG(("HostChannel: CallbackEvent: (%d) instance %p\n",
    636                pClient->u32ClientID, pInstance));
     809    HOSTCHLOG(("HostChannel: CallbackEvent[%p]: (%d) instance %p\n",
     810               pCallbackCtx, pClient->u32ClientID, pInstance));
    637811
    638812    if (!pInstance)
    639813    {
     814        vboxHostChannelUnlock();
     815
    640816#ifdef DEBUG_sunlover
    641817        AssertFailed();
     
    644820    }
    645821
    646     int rc = vboxHostChannelLock();
    647     if (RT_FAILURE(rc))
    648     {
    649         return;
    650     }
    651 
    652822    uint32_t u32ChannelHandle = pInstance->u32Handle;
    653823
    654824    HOSTCHLOG(("HostChannel: CallbackEvent: (%d) handle %d, async %d, cbEvent %d\n",
    655                     pClient->u32ClientID, u32ChannelHandle, pClient->fAsync, cbEvent));
     825               pClient->u32ClientID, u32ChannelHandle, pClient->fAsync, cbEvent));
    656826
    657827    /* Check whether the event is waited. */
     
    697867
    698868    vboxHostChannelUnlock();
     869}
     870
     871static DECLCALLBACK(void) HostChannelCallbackDeleted(void *pvCallbacks, void *pvChannel)
     872{
     873    vhcCallbackCtxDelete((VBOXHOSTCHCALLBACKCTX *)pvCallbacks);
    699874}
    700875
  • trunk/src/VBox/HostServices/HostChannel/HostChannel.h

    r43462 r43785  
    4545    RTLISTANCHOR listChannels;
    4646    uint32_t volatile u32HandleSrc;
     47
     48    RTLISTANCHOR listContexts; /* Callback contexts. */
    4749
    4850    RTLISTANCHOR listEvents;
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