[NTOS:IO]
authorThomas Faber <thomas.faber@reactos.org>
Fri, 24 Oct 2014 10:02:14 +0000 (10:02 +0000)
committerThomas Faber <thomas.faber@reactos.org>
Fri, 24 Oct 2014 10:02:14 +0000 (10:02 +0000)
- Introduce IopDriverLoadResource to protect against concurrent driver loading
CORE-8696 #resolve

svn path=/trunk/; revision=64951

reactos/ntoskrnl/io/iomgr/driver.c
reactos/ntoskrnl/io/iomgr/iomgr.c
reactos/ntoskrnl/io/pnpmgr/pnpmgr.c

index 2954102..9f54c17 100644 (file)
@@ -16,6 +16,8 @@
 
 /* GLOBALS ********************************************************************/
 
+ERESOURCE IopDriverLoadResource;
+
 LIST_ENTRY DriverReinitListHead;
 KSPIN_LOCK DriverReinitListLock;
 PLIST_ENTRY DriverReinitTailEntry;
@@ -113,6 +115,7 @@ IopGetDriverObject(
     DPRINT("IopGetDriverObject(%p '%wZ' %x)\n",
            DriverObject, ServiceName, FileSystem);
 
+    ASSERT(ExIsResourceAcquiredExclusiveLite(&IopDriverLoadResource));
     *DriverObject = NULL;
 
     /* Create ModuleName string */
@@ -313,6 +316,7 @@ IopLoadServiceModule(
     HANDLE CCSKey, ServiceKey;
     PVOID BaseAddress;
 
+    ASSERT(ExIsResourceAcquiredExclusiveLite(&IopDriverLoadResource));
     ASSERT(ServiceName->Length);
     DPRINT("IopLoadServiceModule(%wZ, 0x%p)\n", ServiceName, ModuleObject);
 
@@ -567,6 +571,8 @@ IopAttachFilterDriversCallback(
         ServiceName.MaximumLength =
         ServiceName.Length = (USHORT)wcslen(Filters) * sizeof(WCHAR);
 
+        KeEnterCriticalRegion();
+        ExAcquireResourceExclusiveLite(&IopDriverLoadResource, TRUE);
         Status = IopGetDriverObject(&DriverObject,
                                     &ServiceName,
                                     FALSE);
@@ -575,7 +581,11 @@ IopAttachFilterDriversCallback(
             /* Load and initialize the filter driver */
             Status = IopLoadServiceModule(&ServiceName, &ModuleObject);
             if (!NT_SUCCESS(Status))
+            {
+                ExReleaseResourceLite(&IopDriverLoadResource);
+                KeLeaveCriticalRegion();
                 return Status;
+            }
 
             Status = IopInitializeDriverModule(DeviceNode,
                                                ModuleObject,
@@ -583,9 +593,16 @@ IopAttachFilterDriversCallback(
                                                FALSE,
                                                &DriverObject);
             if (!NT_SUCCESS(Status))
+            {
+                ExReleaseResourceLite(&IopDriverLoadResource);
+                KeLeaveCriticalRegion();
                 return Status;
+            }
         }
 
+        ExReleaseResourceLite(&IopDriverLoadResource);
+        KeLeaveCriticalRegion();
+
         Status = IopInitializeDevice(DeviceNode, DriverObject);
 
         /* Remove extra reference */
@@ -1971,6 +1988,8 @@ IopLoadUnloadDriver(
     DPRINT("FullImagePath: '%wZ'\n", &ImagePath);
     DPRINT("Type: %lx\n", Type);
 
+    KeEnterCriticalRegion();
+    ExAcquireResourceExclusiveLite(&IopDriverLoadResource, TRUE);
     /*
      * Get existing DriverObject pointer (in case the driver
      * has already been loaded and initialized).
@@ -1990,6 +2009,8 @@ IopLoadUnloadDriver(
         if (!NT_SUCCESS(Status))
         {
             DPRINT("MmLoadSystemImage() failed (Status %lx)\n", Status);
+            ExReleaseResourceLite(&IopDriverLoadResource);
+            KeLeaveCriticalRegion();
             return Status;
         }
 
@@ -2000,6 +2021,8 @@ IopLoadUnloadDriver(
         if (!NT_SUCCESS(Status))
         {
             DPRINT1("IopCreateDeviceNode() failed (Status %lx)\n", Status);
+            ExReleaseResourceLite(&IopDriverLoadResource);
+            KeLeaveCriticalRegion();
             MmUnloadSystemImage(ModuleObject);
             return Status;
         }
@@ -2015,16 +2038,24 @@ IopLoadUnloadDriver(
         if (!NT_SUCCESS(Status))
         {
             DPRINT1("IopInitializeDriverModule() failed (Status %lx)\n", Status);
+            ExReleaseResourceLite(&IopDriverLoadResource);
+            KeLeaveCriticalRegion();
             MmUnloadSystemImage(ModuleObject);
             return Status;
         }
 
+        ExReleaseResourceLite(&IopDriverLoadResource);
+        KeLeaveCriticalRegion();
+
         /* Initialize and start device */
         IopInitializeDevice(DeviceNode, *DriverObject);
         Status = IopStartDevice(DeviceNode);
     }
     else
     {
+        ExReleaseResourceLite(&IopDriverLoadResource);
+        KeLeaveCriticalRegion();
+
         DPRINT("DriverObject already exist in ObjectManager\n");
         Status = STATUS_IMAGE_ALREADY_LOADED;
 
index b1d4a13..b61e8e4 100644 (file)
@@ -54,6 +54,7 @@ extern KSPIN_LOCK ShutdownListLock;
 extern POBJECT_TYPE IoAdapterObjectType;
 extern ERESOURCE IopDatabaseResource;
 ERESOURCE IopSecurityResource;
+extern ERESOURCE IopDriverLoadResource;
 extern KGUARDED_MUTEX PnpNotifyListLock;
 extern LIST_ENTRY IopDiskFileSystemQueueHead;
 extern LIST_ENTRY IopCdRomFileSystemQueueHead;
@@ -476,8 +477,9 @@ IoInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
     IopInitLookasideLists();
 
     /* Initialize all locks and lists */
-    ExInitializeResource(&IopDatabaseResource);
-    ExInitializeResource(&IopSecurityResource);
+    ExInitializeResourceLite(&IopDatabaseResource);
+    ExInitializeResourceLite(&IopSecurityResource);
+    ExInitializeResourceLite(&IopDriverLoadResource);
     KeInitializeGuardedMutex(&PnpNotifyListLock);
     InitializeListHead(&IopDiskFileSystemQueueHead);
     InitializeListHead(&IopCdRomFileSystemQueueHead);
index 63d82da..1cdfc5d 100644 (file)
@@ -21,6 +21,7 @@ ERESOURCE PpRegistryDeviceResource;
 KGUARDED_MUTEX PpDeviceReferenceTableLock;
 RTL_AVL_TABLE PpDeviceReferenceTable;
 
+extern ERESOURCE IopDriverLoadResource;
 extern ULONG ExpInitializationPhase;
 extern BOOLEAN ExpInTextModeSetup;
 extern BOOLEAN PnpSystemInit;
@@ -2611,6 +2612,8 @@ IopActionInitChildServices(PDEVICE_NODE DeviceNode,
       PLDR_DATA_TABLE_ENTRY ModuleObject;
       PDRIVER_OBJECT DriverObject;
 
+      KeEnterCriticalRegion();
+      ExAcquireResourceExclusiveLite(&IopDriverLoadResource, TRUE);
       /* Get existing DriverObject pointer (in case the driver has
          already been loaded and initialized) */
       Status = IopGetDriverObject(
@@ -2642,6 +2645,8 @@ IopActionInitChildServices(PDEVICE_NODE DeviceNode,
             if (!BootDrivers) DeviceNode->Problem = CM_PROB_DRIVER_FAILED_LOAD;
          }
       }
+      ExReleaseResourceLite(&IopDriverLoadResource);
+      KeLeaveCriticalRegion();
 
       /* Driver is loaded and initialized at this point */
       if (NT_SUCCESS(Status))