VirtualBox

Changeset 70287 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Dec 21, 2017 3:52:26 PM (7 years ago)
Author:
vboxsync
Message:

VBoxGuest-win.cpp: Snuffed out race between idle checking and session creation.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-win.cpp

    r70284 r70287  
    3838#include <iprt/asm.h>
    3939#include <iprt/asm-amd64-x86.h>
     40#include <iprt/critsect.h>
    4041#include <iprt/dbg.h>
    4142#include <iprt/initterm.h>
     
    135136     *  in a DPC callback and not the ISR. */
    136137    KSPIN_LOCK              MouseEventAccessSpinLock;
     138
     139    /** Read/write critical section for handling race between checking for idle
     140     * driver (in IRP_MN_QUERY_REMOVE_DEVICE & IRP_MN_QUERY_STOP_DEVICE) and
     141     * creating new sessions.  The session creation code enteres the critical
     142     * section in  read (shared) access mode, whereas the idle checking code
     143     * enteres is in write (exclusive) access mode.  */
     144    RTCRITSECTRW            SessionCreateCritSect;
    137145} VBOXGUESTDEVEXTWIN;
    138146typedef VBOXGUESTDEVEXTWIN *PVBOXGUESTDEVEXTWIN;
     
    449457
    450458
     459/**
     460 * Does the fundamental device extension initialization.
     461 *
     462 * @returns NT status.
     463 * @param   pDevExt             The device extension.
     464 * @param   pDevObj             The device object.
     465 */
     466static NTSTATUS vgdrvNtInitDevExtFundament(PVBOXGUESTDEVEXTWIN pDevExt, PDEVICE_OBJECT pDevObj)
     467{
     468    RT_ZERO(*pDevExt);
     469
     470    KeInitializeSpinLock(&pDevExt->MouseEventAccessSpinLock);
     471    pDevExt->pDeviceObject   = pDevObj;
     472    pDevExt->enmPrevDevState = VGDRVNTDEVSTATE_STOPPED;
     473    pDevExt->enmDevState     = VGDRVNTDEVSTATE_STOPPED;
     474
     475    int rc = RTCritSectRwInit(&pDevExt->SessionCreateCritSect);
     476    if (RT_SUCCESS(rc))
     477    {
     478        rc = VGDrvCommonInitDevExtFundament(&pDevExt->Core);
     479        if (RT_SUCCESS(rc))
     480        {
     481            LogFlow(("vgdrvNtInitDevExtFundament: returning success\n"));
     482            return STATUS_SUCCESS;
     483        }
     484
     485        RTCritSectRwDelete(&pDevExt->SessionCreateCritSect);
     486    }
     487    Log(("vgdrvNtInitDevExtFundament: failed: rc=%Rrc\n", rc));
     488    return STATUS_UNSUCCESSFUL;
     489}
     490
     491
     492/**
     493 * Counter part to vgdrvNtInitDevExtFundament.
     494 *
     495 * @param   pDevExt             The device extension.
     496 */
     497static void vgdrvNtDeleteDevExtFundament(PVBOXGUESTDEVEXTWIN pDevExt)
     498{
     499    LogFlow(("vgdrvNtDeleteDevExtFundament:\n"));
     500    VGDrvCommonDeleteDevExtFundament(&pDevExt->Core);
     501    RTCritSectRwDelete(&pDevExt->SessionCreateCritSect);
     502}
     503
     504
    451505#ifdef LOG_ENABLED
    452506/**
     
    9861040            Log(("vgdrvNt4CreateDevice: Setting up device extension ...\n"));
    9871041            PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDeviceObject->DeviceExtension;
    988             RT_ZERO(*pDevExt);
    989 
    990             /* Store a reference to ourself. */
    991             pDevExt->pDeviceObject = pDeviceObject;
    992 
    993             /* Store bus and slot number we've queried before. */
    994             pDevExt->uBus  = uBus;
    995             pDevExt->uSlot = uSlot.u.AsULONG;
    996 
    997             /* Initialize common bits. */
    998             int vrc = VGDrvCommonInitDevExtFundament(&pDevExt->Core);
     1042            int vrc = vgdrvNtInitDevExtFundament(pDevExt, pDeviceObject);
    9991043            if (RT_SUCCESS(vrc))
    10001044            {
     1045                /* Store bus and slot number we've queried before. */
     1046                pDevExt->uBus  = uBus;
     1047                pDevExt->uSlot = uSlot.u.AsULONG;
     1048
    10011049                Log(("vgdrvNt4CreateDevice: Device extension created\n"));
    10021050
     
    10101058
    10111059                /* bail out */
    1012                 VGDrvCommonDeleteDevExtFundament(&pDevExt->Core);
     1060                vgdrvNtDeleteDevExtFundament(pDevExt);
    10131061            }
    10141062            IoDeleteSymbolicLink(&DosName);
     
    10601108             */
    10611109            PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDeviceObject->DeviceExtension;
    1062             RT_ZERO(*pDevExt);
    1063 
    1064             KeInitializeSpinLock(&pDevExt->MouseEventAccessSpinLock);
    1065             pDevExt->pDeviceObject   = pDeviceObject;
    1066             pDevExt->enmPrevDevState = VGDRVNTDEVSTATE_STOPPED;
    1067             pDevExt->enmDevState     = VGDRVNTDEVSTATE_STOPPED;
    1068 
    1069             int vrc = VGDrvCommonInitDevExtFundament(&pDevExt->Core);
    1070             if (RT_SUCCESS(vrc))
     1110            rcNt = vgdrvNtInitDevExtFundament(pDevExt, pDeviceObject);
     1111            if (NT_SUCCESS(rcNt))
    10711112            {
    10721113                pDevExt->pNextLowerDriver = IoAttachDeviceToDeviceStack(pDeviceObject, pDevObj);
     
    10811122                    return rcNt;
    10821123                }
    1083 
    10841124                LogFunc(("IoAttachDeviceToDeviceStack did not give a nextLowerDriver!\n"));
    10851125                rcNt = STATUS_DEVICE_NOT_CONNECTED;
    1086                 VGDrvCommonDeleteDevExtFundament(&pDevExt->Core);
     1126                vgdrvNtDeleteDevExtFundament(pDevExt);
    10871127            }
    1088             else
    1089                 rcNt = STATUS_UNSUCCESSFUL;
    1090 
    1091             /* bail out */
     1128
    10921129            IoDeleteSymbolicLink(&DosName);
    10931130        }
     
    11691206        pDevExt->pInterruptObject = NULL;
    11701207    }
     1208    pDevExt->pPowerStateRequest = NULL; /* Will be deleted by the following call. */
    11711209    if (pDevExt->Core.uInitState == VBOXGUESTDEVEXT_INIT_STATE_RESOURCES)
    11721210        VGDrvCommonDeleteDevExtResources(&pDevExt->Core);
     
    11891227     * Delete the remainder of the device extension.
    11901228     */
    1191     pDevExt->pPowerStateRequest = NULL; /* Will be deleted by the following call. */
    1192     VGDrvCommonDeleteDevExtFundament(&pDevExt->Core);
     1229    vgdrvNtDeleteDevExtFundament(pDevExt);
    11931230
    11941231    /*
     
    13091346            Log(("vgdrvNtNt5PlusPnP: QUERY_REMOVE_DEVICE\n"));
    13101347
     1348            RTCritSectRwEnterExcl(&pDevExt->SessionCreateCritSect);
    13111349#ifdef VBOX_REBOOT_ON_UNINSTALL
    13121350            Log(("vgdrvNtNt5PlusPnP: QUERY_REMOVE_DEVICE: Device cannot be removed without a reboot.\n"));
     
    13181356            {
    13191357                pDevExt->enmDevState = VGDRVNTDEVSTATE_PENDINGREMOVE;
     1358                RTCritSectRwLeaveExcl(&pDevExt->SessionCreateCritSect);
    13201359
    13211360                /* This IRP passed down to lower driver. */
     
    13321371            else
    13331372            {
     1373                RTCritSectRwLeaveExcl(&pDevExt->SessionCreateCritSect);
    13341374                pIrp->IoStatus.Status = rc;
    13351375                IoCompleteRequest(pIrp, IO_NO_INCREMENT);
     
    14291469        {
    14301470            Log(("vgdrvNtNt5PlusPnP: QUERY_STOP_DEVICE\n"));
     1471            RTCritSectRwEnterExcl(&pDevExt->SessionCreateCritSect);
    14311472            rc = vgdrvNtCheckIdle(pDevExt, "QUERY_STOP_DEVICE");
    14321473            if (NT_SUCCESS(rc))
     
    14341475                pDevExt->enmPrevDevState = pDevExt->enmDevState;
    14351476                pDevExt->enmDevState = VGDRVNTDEVSTATE_PENDINGSTOP;
     1477                RTCritSectRwLeaveExcl(&pDevExt->SessionCreateCritSect);
    14361478
    14371479                /* This IRP passed down to lower driver. */
     
    14491491            else
    14501492            {
     1493                RTCritSectRwLeaveExcl(&pDevExt->SessionCreateCritSect);
    14511494                pIrp->IoStatus.Status = rc;
    14521495                IoCompleteRequest(pIrp, IO_NO_INCREMENT);
     
    18361879    /*
    18371880     * We are not remotely similar to a directory...
    1838      * (But this is possible.)
    18391881     */
    1840     if (pStack->Parameters.Create.Options & FILE_DIRECTORY_FILE)
     1882    NTSTATUS rcNt;
     1883    if (!(pStack->Parameters.Create.Options & FILE_DIRECTORY_FILE))
     1884    {
     1885        /*
     1886         * Check the device state.  We enter the critsect in shared mode to
     1887         * prevent race with PnP system requests checking whether we're idle.
     1888         */
     1889        RTCritSectRwEnterShared(&pDevExt->SessionCreateCritSect);
     1890        VGDRVNTDEVSTATE const enmDevState = pDevExt->enmDevState;
     1891        if (enmDevState == VGDRVNTDEVSTATE_OPERATIONAL)
     1892        {
     1893            /*
     1894             * Create a client session.
     1895             */
     1896            int                 rc;
     1897            PVBOXGUESTSESSION   pSession;
     1898            if (pIrp->RequestorMode == KernelMode)
     1899                rc = VGDrvCommonCreateKernelSession(&pDevExt->Core, &pSession);
     1900            else
     1901                rc = VGDrvCommonCreateUserSession(&pDevExt->Core, &pSession);
     1902            RTCritSectRwLeaveShared(&pDevExt->SessionCreateCritSect);
     1903            if (RT_SUCCESS(rc))
     1904            {
     1905                pFileObj->FsContext = pSession;
     1906                Log(("vgdrvNtCreate: Successfully created %s session %p\n",
     1907                     pIrp->RequestorMode == KernelMode ? "kernel" : "user", pSession));
     1908
     1909                return vgdrvNtCompleteRequestEx(STATUS_SUCCESS, FILE_OPENED, pIrp);
     1910            }
     1911
     1912            /* Note. the IoStatus is completely ignored on error. */
     1913            Log(("vgdrvNtCreate: Failed to create session: rc=%Rrc\n", rc));
     1914            if (rc == VERR_NO_MEMORY)
     1915                rcNt = STATUS_NO_MEMORY;
     1916            else
     1917                rcNt = STATUS_UNSUCCESSFUL;
     1918        }
     1919        else
     1920        {
     1921            RTCritSectRwLeaveShared(&pDevExt->SessionCreateCritSect);
     1922            LogFlow(("vgdrvNtCreate: Failed. Device is not in 'working' state: %d\n", enmDevState));
     1923            rcNt = STATUS_DEVICE_NOT_READY;
     1924        }
     1925    }
     1926    else
    18411927    {
    18421928        LogFlow(("vgdrvNtCreate: Failed. FILE_DIRECTORY_FILE set\n"));
    1843         return vgdrvNtCompleteRequest(STATUS_NOT_A_DIRECTORY, pIrp);
    1844     }
    1845 
    1846     /*
    1847      * Check the device state.
    1848      */
    1849     if (pDevExt->enmDevState != VGDRVNTDEVSTATE_OPERATIONAL)
    1850     {
    1851         LogFlow(("vgdrvNtCreate: Failed. Device is not in 'working' state: %d\n", pDevExt->enmDevState));
    1852         return vgdrvNtCompleteRequest(STATUS_DEVICE_NOT_READY, pIrp);
    1853     }
    1854 
    1855     /*
    1856      * Create a client session.
    1857      */
    1858     int                 rc;
    1859     PVBOXGUESTSESSION   pSession;
    1860     if (pIrp->RequestorMode == KernelMode)
    1861         rc = VGDrvCommonCreateKernelSession(&pDevExt->Core, &pSession);
    1862     else
    1863         rc = VGDrvCommonCreateUserSession(&pDevExt->Core, &pSession);
    1864     if (RT_SUCCESS(rc))
    1865     {
    1866         pFileObj->FsContext = pSession;
    1867         Log(("vgdrvNtCreate: Successfully created %s session %p\n",
    1868              pIrp->RequestorMode == KernelMode ? "kernel" : "user", pSession));
    1869         return vgdrvNtCompleteRequestEx(STATUS_SUCCESS, FILE_OPENED, pIrp);
    1870     }
    1871 
    1872     Log(("vgdrvNtCreate: Failed to create session: rc=%Rrc\n", rc));
    1873     /* Note. the IoStatus is completely ignored on error. */
    1874     if (rc == VERR_NO_MEMORY)
    1875         return vgdrvNtCompleteRequest(STATUS_NO_MEMORY, pIrp);
    1876     return vgdrvNtCompleteRequest(STATUS_UNSUCCESSFUL, pIrp);
     1929        rcNt = STATUS_NOT_A_DIRECTORY;
     1930    }
     1931    return vgdrvNtCompleteRequest(rcNt, pIrp);
    18771932}
    18781933
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