VirtualBox

Ignore:
Timestamp:
Oct 5, 2021 8:28:55 AM (3 years ago)
Author:
vboxsync
Message:

SUPDrv/win: Added mapping of NT security IDs to 32-bit UID values - not enabled yet. bugref:10093

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp

    r90780 r91559  
    9090#define VBOXDRV_WITH_FAST_IO
    9191
     92/** Enables generating UID from NT SIDs so the GMM can share free memory
     93 *  among VMs running as the same user. */
     94//#define VBOXDRV_WITH_SID_TO_UID_MAPPING
     95
    9296/* Missing if we're compiling against older WDKs. */
    9397#ifndef NonPagedPoolNx
     
    99103*   Structures and Typedefs                                                                                                      *
    100104*********************************************************************************************************************************/
     105#ifdef VBOXDRV_WITH_SID_TO_UID_MAPPING
     106/**
     107 * SID to User ID mapping.
     108 *
     109 * This is used to generate a RTUID value for a NT security identifier.
     110 * Normally, the UID is the hash of the SID string, but due to collisions it may
     111 * differ.  See g_NtUserIdHashTree and g_NtUserIdUidTree.
     112 */
     113typedef struct SUPDRVNTUSERID
     114{
     115    /** Hash tree node, key: RTStrHash1 of szSid. */
     116    AVLLU32NODECORE     HashCore;
     117    /** UID three node, key: The UID. */
     118    AVLU32NODECORE      UidCore;
     119    /** Reference counter. */
     120    uint32_t volatile   cRefs;
     121    /** The length of the SID string. */
     122    uint16_t            cchSid;
     123    /** The SID string for the user. */
     124    char                szSid[RT_FLEXIBLE_ARRAY];
     125} SUPDRVNTUSERID;
     126/** Pointer to a SID to UID mapping. */
     127typedef SUPDRVNTUSERID *PSUPDRVNTUSERID;
     128#endif
     129
    101130/**
    102131 * Device extension used by VBoxDrvU.
     
    404433static PFNKEGETPROCESSORNUMBERFROMINDEX g_pfnKeGetProcessorNumberFromIndex = NULL;
    405434
     435#ifdef VBOXDRV_WITH_SID_TO_UID_MAPPING
     436/** Spinlock protecting g_NtUserIdHashTree and g_NtUserIdUidTree. */
     437static RTSPINLOCK                   g_hNtUserIdLock     = NIL_RTSPINLOCK;
     438/** AVL tree of SUPDRVNTUSERID structures by hash value. */
     439static PAVLLU32NODECORE             g_NtUserIdHashTree  = NULL;
     440/** AVL tree of SUPDRVNTUSERID structures by UID. */
     441static PAVLU32NODECORE              g_NtUserIdUidTree   = NULL;
     442#endif
     443
    406444#ifdef VBOX_WITH_HARDENING
    407445/** Pointer to the stub device instance. */
     
    657695#endif
    658696        {
     697#ifdef VBOXDRV_WITH_SID_TO_UID_MAPPING
    659698            /*
    660              * Create device.
    661              * (That means creating a device object and a symbolic link so the DOS
    662              * subsystems (OS/2, win32, ++) can access the device.)
     699             * Create the spinlock for the SID -> UID mappings.
    663700             */
    664             rcNt = vboxdrvNtCreateDevices(pDrvObj);
    665             if (NT_SUCCESS(rcNt))
     701            vrc = RTSpinlockCreate(&g_hNtUserIdLock, RTSPINLOCK_FLAGS_INTERRUPT_UNSAFE, "NtUserId");
     702            if (RT_SUCCESS(vrc))
     703#endif
    666704            {
    667705                /*
    668                  * Initialize the device extension.
     706                 * Create device.
     707                 * (That means creating a device object and a symbolic link so the DOS
     708                 * subsystems (OS/2, win32, ++) can access the device.)
    669709                 */
    670                 PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)g_pDevObjSys->DeviceExtension;
    671                 memset(pDevExt, 0, sizeof(*pDevExt));
    672 
    673                 vrc = supdrvInitDevExt(pDevExt, sizeof(SUPDRVSESSION));
    674                 if (!vrc)
     710                rcNt = vboxdrvNtCreateDevices(pDrvObj);
     711                if (NT_SUCCESS(rcNt))
    675712                {
    676713                    /*
    677                      * Setup the driver entry points in pDrvObj.
     714                     * Initialize the device extension.
    678715                     */
    679                     pDrvObj->DriverUnload                                   = VBoxDrvNtUnload;
    680                     pDrvObj->MajorFunction[IRP_MJ_CREATE]                   = VBoxDrvNtCreate;
    681                     pDrvObj->MajorFunction[IRP_MJ_CLEANUP]                  = VBoxDrvNtCleanup;
    682                     pDrvObj->MajorFunction[IRP_MJ_CLOSE]                    = VBoxDrvNtClose;
    683                     pDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL]           = VBoxDrvNtDeviceControl;
    684                     pDrvObj->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL]  = VBoxDrvNtInternalDeviceControl;
    685                     pDrvObj->MajorFunction[IRP_MJ_READ]                     = VBoxDrvNtRead;
    686                     pDrvObj->MajorFunction[IRP_MJ_WRITE]                    = VBoxDrvNtNotSupportedStub;
     716                    PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)g_pDevObjSys->DeviceExtension;
     717                    memset(pDevExt, 0, sizeof(*pDevExt));
     718
     719                    vrc = supdrvInitDevExt(pDevExt, sizeof(SUPDRVSESSION));
     720                    if (!vrc)
     721                    {
     722                        /*
     723                         * Setup the driver entry points in pDrvObj.
     724                         */
     725                        pDrvObj->DriverUnload                                   = VBoxDrvNtUnload;
     726                        pDrvObj->MajorFunction[IRP_MJ_CREATE]                   = VBoxDrvNtCreate;
     727                        pDrvObj->MajorFunction[IRP_MJ_CLEANUP]                  = VBoxDrvNtCleanup;
     728                        pDrvObj->MajorFunction[IRP_MJ_CLOSE]                    = VBoxDrvNtClose;
     729                        pDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL]           = VBoxDrvNtDeviceControl;
     730                        pDrvObj->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL]  = VBoxDrvNtInternalDeviceControl;
     731                        pDrvObj->MajorFunction[IRP_MJ_READ]                     = VBoxDrvNtRead;
     732                        pDrvObj->MajorFunction[IRP_MJ_WRITE]                    = VBoxDrvNtNotSupportedStub;
    687733
    688734#ifdef VBOXDRV_WITH_FAST_IO
    689                     /* Fast I/O to speed up guest execution roundtrips. */
    690                     pDrvObj->FastIoDispatch = (PFAST_IO_DISPATCH)&g_VBoxDrvFastIoDispatch;
     735                        /* Fast I/O to speed up guest execution roundtrips. */
     736                        pDrvObj->FastIoDispatch = (PFAST_IO_DISPATCH)&g_VBoxDrvFastIoDispatch;
    691737#endif
    692738
     739                        /*
     740                         * Register ourselves for power state changes.  We don't
     741                         * currently care if this fails.
     742                         */
     743                        UNICODE_STRING      CallbackName;
     744                        RtlInitUnicodeString(&CallbackName, L"\\Callback\\PowerState");
     745
     746                        OBJECT_ATTRIBUTES   Attr;
     747                        InitializeObjectAttributes(&Attr, &CallbackName, OBJ_CASE_INSENSITIVE, NULL, NULL);
     748
     749                        rcNt = ExCreateCallback(&pDevExt->pObjPowerCallback, &Attr, TRUE, TRUE);
     750                        if (rcNt == STATUS_SUCCESS)
     751                            pDevExt->hPowerCallback = ExRegisterCallback(pDevExt->pObjPowerCallback,
     752                                                                         VBoxPowerDispatchCallback,
     753                                                                         g_pDevObjSys);
     754
     755                        /*
     756                         * Done! Returning success!
     757                         */
     758                        Log(("VBoxDrv::DriverEntry returning STATUS_SUCCESS\n"));
     759                        return STATUS_SUCCESS;
     760                    }
     761
    693762                    /*
    694                      * Register ourselves for power state changes.  We don't
    695                      * currently care if this fails.
     763                     * Failed. Clean up.
    696764                     */
    697                     UNICODE_STRING      CallbackName;
    698                     RtlInitUnicodeString(&CallbackName, L"\\Callback\\PowerState");
    699 
    700                     OBJECT_ATTRIBUTES   Attr;
    701                     InitializeObjectAttributes(&Attr, &CallbackName, OBJ_CASE_INSENSITIVE, NULL, NULL);
    702 
    703                     rcNt = ExCreateCallback(&pDevExt->pObjPowerCallback, &Attr, TRUE, TRUE);
    704                     if (rcNt == STATUS_SUCCESS)
    705                         pDevExt->hPowerCallback = ExRegisterCallback(pDevExt->pObjPowerCallback,
    706                                                                      VBoxPowerDispatchCallback,
    707                                                                      g_pDevObjSys);
    708 
    709                     /*
    710                      * Done! Returning success!
    711                      */
    712                     Log(("VBoxDrv::DriverEntry returning STATUS_SUCCESS\n"));
    713                     return STATUS_SUCCESS;
     765                    Log(("supdrvInitDevExit failed with vrc=%d!\n", vrc));
     766                    rcNt = VBoxDrvNtErr2NtStatus(vrc);
     767
     768                    vboxdrvNtDestroyDevices();
    714769                }
    715 
    716                 Log(("supdrvInitDevExit failed with vrc=%d!\n", vrc));
     770#ifdef VBOXDRV_WITH_SID_TO_UID_MAPPING
     771                RTSpinlockDestroy(g_hNtUserIdLock);
     772                g_hNtUserIdLock = NIL_RTSPINLOCK;
     773#endif
     774            }
     775#ifdef VBOXDRV_WITH_SID_TO_UID_MAPPING
     776            else
    717777                rcNt = VBoxDrvNtErr2NtStatus(vrc);
    718 
    719                 vboxdrvNtDestroyDevices();
    720             }
     778#endif
    721779#ifdef VBOX_WITH_HARDENING
    722780            supdrvNtProtectTerm();
     
    758816     */
    759817    supdrvDeleteDevExt(pDevExt);
     818#ifdef VBOXDRV_WITH_SID_TO_UID_MAPPING
     819    RTSpinlockDestroy(g_hNtUserIdLock);
     820    g_hNtUserIdLock = NIL_RTSPINLOCK;
     821#endif
    760822#ifdef VBOX_WITH_HARDENING
    761823    supdrvNtProtectTerm();
     
    768830}
    769831
     832#ifdef VBOXDRV_WITH_SID_TO_UID_MAPPING
     833
     834/**
     835 * Worker for supdrvNtUserIdMakeForSession.
     836 */
     837static bool supdrvNtUserIdMakeUid(PSUPDRVNTUSERID pNtUserId)
     838{
     839    pNtUserId->UidCore.Key = pNtUserId->HashCore.Key;
     840    for (uint32_t cTries = 0; cTries < _4K; cTries++)
     841    {
     842        bool fRc = RTAvlU32Insert(&g_NtUserIdUidTree, &pNtUserId->UidCore);
     843        if (fRc)
     844            return true;
     845        pNtUserId->UidCore.Key += pNtUserId->cchSid | 1;
     846    }
     847    return false;
     848}
     849
     850
     851/**
     852 * Try create a RTUID value for the session.
     853 *
     854 * @returns VBox status code.
     855 * @param   pSession    The session to try set SUPDRVSESSION::Uid for.
     856 */
     857static int supdrvNtUserIdMakeForSession(PSUPDRVSESSION pSession)
     858{
     859    /*
     860     * Get the current security context and query the User SID for it.
     861     */
     862    SECURITY_SUBJECT_CONTEXT Ctx = { NULL, SecurityIdentification, NULL, NULL };
     863    SeCaptureSubjectContext(&Ctx);
     864
     865    int         rc;
     866    TOKEN_USER *pTokenUser = NULL;
     867    NTSTATUS    rcNt = SeQueryInformationToken(SeQuerySubjectContextToken(&Ctx) /* or always PrimaryToken?*/,
     868                                               TokenUser, (PVOID *)&pTokenUser);
     869    if (NT_SUCCESS(rcNt))
     870    {
     871        /*
     872         * Convert the user SID to a string to make it easier to handle, then prepare
     873         * a user ID entry for it as that way we can combine lookup and insertion and
     874         * avoid needing to deal with races.
     875         */
     876        UNICODE_STRING UniStr = RTNT_NULL_UNISTR();
     877        rcNt = RtlConvertSidToUnicodeString(&UniStr, &pTokenUser->User.Sid, TRUE /*AllocateDesitnationString*/);
     878        if (NT_SUCCESS(rcNt))
     879        {
     880            size_t cchSid = 0;
     881            rc = RTUtf16CalcUtf8LenEx(UniStr.Buffer, UniStr.Length / sizeof(RTUTF16), &cchSid);
     882            if (RT_SUCCESS(rc))
     883            {
     884                PSUPDRVNTUSERID const pNtUserIdNew = (PSUPDRVNTUSERID)RTMemAlloc(RT_UOFFSETOF_DYN(SUPDRVNTUSERID, szSid[cchSid + 1]));
     885                if (pNtUserIdNew)
     886                {
     887                    char *pszSid = pNtUserIdNew->szSid;
     888                    rc = RTUtf16ToUtf8Ex(UniStr.Buffer, UniStr.Length / sizeof(RTUTF16), &pszSid, cchSid + 1, NULL);
     889                    if (RT_SUCCESS(rc))
     890                    {
     891                        pNtUserIdNew->HashCore.Key = RTStrHash1(pNtUserIdNew->szSid);
     892                        pNtUserIdNew->cchSid       = (uint16_t)cchSid;
     893                        pNtUserIdNew->cRefs        = 1;
     894
     895                        /*
     896                         * Do the lookup / insert.
     897                         */
     898                        RTSpinlockAcquire(g_hNtUserIdLock);
     899                        AssertCompileMemberOffset(SUPDRVNTUSERID, HashCore, 0);
     900                        PSUPDRVNTUSERID pNtUserId = (PSUPDRVNTUSERID)RTAvllU32Get(&g_NtUserIdHashTree, pNtUserIdNew->HashCore.Key);
     901                        if (pNtUserId)
     902                        {
     903                            /* Match the strings till we reach the end of the collision list. */
     904                            PSUPDRVNTUSERID const pNtUserIdHead = pNtUserId;
     905                            while (   pNtUserId
     906                                   && (   pNtUserId->cchSid != cchSid
     907                                       || memcmp(pNtUserId->szSid, pNtUserId->szSid, cchSid) != 0))
     908                                pNtUserId = (PSUPDRVNTUSERID)pNtUserId->HashCore.pList;
     909                            if (pNtUserId)
     910                            {
     911                                /* Found matching: Retain reference and free the new entry we prepared. */
     912                                uint32_t cRefs = ASMAtomicIncU32(&pNtUserId->cRefs);
     913                                Assert(cRefs < _16K);
     914                                RTSpinlockRelease(g_hNtUserIdLock);
     915                            }
     916                            else
     917                            {
     918                                /* No match: Try insert prepared entry after the head node. */
     919                                if (supdrvNtUserIdMakeUid(pNtUserIdNew))
     920                                {
     921                                    pNtUserIdNew->HashCore.pList  = pNtUserIdHead->HashCore.pList;
     922                                    pNtUserIdHead->HashCore.pList = &pNtUserIdNew->HashCore;
     923                                    pNtUserId = pNtUserIdNew;
     924                                }
     925                                RTSpinlockRelease(g_hNtUserIdLock);
     926                            }
     927                        }
     928                        else
     929                        {
     930                            /* No matching hash: Try insert the prepared entry. */
     931                            pNtUserIdNew->UidCore.Key = pNtUserIdNew->HashCore.Key;
     932                            if (supdrvNtUserIdMakeUid(pNtUserIdNew))
     933                            {
     934                                RTAvllU32Insert(&g_NtUserIdHashTree, &pNtUserIdNew->HashCore);
     935                                pNtUserId = pNtUserIdNew;
     936                            }
     937                            RTSpinlockRelease(g_hNtUserIdLock);
     938                        }
     939
     940                        if (pNtUserId != pNtUserIdNew)
     941                            RTMemFree(pNtUserIdNew);
     942
     943                        /*
     944                         * Update the session info.
     945                         */
     946                        pSession->pNtUserId = pNtUserId;
     947                        pSession->Uid       = pNtUserId ? (RTUID)pNtUserId->UidCore.Key : NIL_RTUID;
     948                    }
     949                    else
     950                        RTMemFree(pNtUserIdNew);
     951                }
     952                else
     953                    rc = VERR_NO_MEMORY;
     954            }
     955            RtlFreeUnicodeString(&UniStr);
     956        }
     957        else
     958            rc = RTErrConvertFromNtStatus(rcNt);
     959        ExFreePool(pTokenUser);
     960    }
     961    else
     962        rc = RTErrConvertFromNtStatus(rcNt);
     963
     964    SeReleaseSubjectContext(&Ctx);
     965    return rc;
     966}
     967
     968
     969/**
     970 * Releases a reference to @a pNtUserId.
     971 *
     972 * @param   pNtUserId   The NT user ID entry to release.
     973 */
     974static void supdrvNtUserIdRelease(PSUPDRVNTUSERID pNtUserId)
     975{
     976    if (pNtUserId)
     977    {
     978        uint32_t cRefs = ASMAtomicDecU32(&pNtUserId->cRefs);
     979        Assert(cRefs < _8K);
     980        if (cRefs == 0)
     981        {
     982            RTSpinlockAcquire(g_hNtUserIdLock);
     983            if (pNtUserId->cRefs == 0)
     984            {
     985                PAVLLU32NODECORE pAssert1 = RTAvllU32RemoveNode(&g_NtUserIdHashTree, &pNtUserId->HashCore);
     986                PAVLU32NODECORE  pAssert2 = RTAvlU32Remove(&g_NtUserIdUidTree, pNtUserId->UidCore.Key);
     987
     988                RTSpinlockRelease(g_hNtUserIdLock);
     989
     990                Assert(pAssert1 == &pNtUserId->HashCore);
     991                Assert(pAssert2 == &pNtUserId->UidCore);
     992                RT_NOREF(pAssert1, pAssert2);
     993
     994                RTMemFree(pNtUserId);
     995            }
     996            else
     997                RTSpinlockRelease(g_hNtUserIdLock);
     998        }
     999    }
     1000}
     1001
     1002#endif /* VBOXDRV_WITH_SID_TO_UID_MAPPING */
    7701003
    7711004/**
     
    9121145                            if (RT_SUCCESS(rc))
    9131146                            {
    914                                 rc = supdrvSessionHashTabInsert(pDevExt, pSession, (PSUPDRVSESSION *)&pFileObj->FsContext, NULL);
     1147#ifdef VBOXDRV_WITH_SID_TO_UID_MAPPING
     1148                                rc = supdrvNtUserIdMakeForSession(pSession);
     1149                                if (RT_SUCCESS(rc))
     1150#endif
     1151                                    rc = supdrvSessionHashTabInsert(pDevExt, pSession, (PSUPDRVSESSION *)&pFileObj->FsContext, NULL);
    9151152                                supdrvSessionRelease(pSession);
    9161153                                if (RT_SUCCESS(rc))
     
    9571194                if (RT_SUCCESS(rc))
    9581195                {
    959                     rc = supdrvSessionHashTabInsert(pDevExt, pSession, (PSUPDRVSESSION *)&pFileObj->FsContext, NULL);
     1196#ifdef VBOXDRV_WITH_SID_TO_UID_MAPPING
     1197                    rc = supdrvNtUserIdMakeForSession(pSession);
     1198                    if (RT_SUCCESS(rc))
     1199#endif
     1200                        rc = supdrvSessionHashTabInsert(pDevExt, pSession, (PSUPDRVSESSION *)&pFileObj->FsContext, NULL);
    9601201                    supdrvSessionRelease(pSession);
    9611202                    if (RT_SUCCESS(rc))
     
    9771218            if (RT_SUCCESS(rc))
    9781219            {
    979                 rc = supdrvSessionHashTabInsert(pDevExt, pSession, (PSUPDRVSESSION *)&pFileObj->FsContext, NULL);
     1220# ifdef VBOXDRV_WITH_SID_TO_UID_MAPPING
     1221                rc = supdrvNtUserIdMakeForSession(pSession);
     1222                if (RT_SUCCESS(rc))
     1223# endif
     1224                    rc = supdrvSessionHashTabInsert(pDevExt, pSession, (PSUPDRVSESSION *)&pFileObj->FsContext, NULL);
    9801225                supdrvSessionRelease(pSession);
    9811226                if (RT_SUCCESS(rc))
     
    17251970    RT_NOREF2(pDevExt, pSession);
    17261971#endif
     1972#ifdef VBOXDRV_WITH_SID_TO_UID_MAPPING
     1973    if (pSession->pNtUserId)
     1974    {
     1975        supdrvNtUserIdRelease(pSession->pNtUserId);
     1976        pSession->pNtUserId = NULL;
     1977    }
     1978#endif
    17271979}
    17281980
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