[NTOS:IO]

- Introduce IopDriverLoadResource to protect against concurrent driver loading
CORE-8696 #resolve

svn path=/trunk/; revision=64951
This commit is contained in:
Thomas Faber 2014-10-24 10:02:14 +00:00
parent 2c91c440f1
commit fcae57435c
3 changed files with 40 additions and 2 deletions

View file

@ -16,6 +16,8 @@
/* GLOBALS ********************************************************************/ /* GLOBALS ********************************************************************/
ERESOURCE IopDriverLoadResource;
LIST_ENTRY DriverReinitListHead; LIST_ENTRY DriverReinitListHead;
KSPIN_LOCK DriverReinitListLock; KSPIN_LOCK DriverReinitListLock;
PLIST_ENTRY DriverReinitTailEntry; PLIST_ENTRY DriverReinitTailEntry;
@ -113,6 +115,7 @@ IopGetDriverObject(
DPRINT("IopGetDriverObject(%p '%wZ' %x)\n", DPRINT("IopGetDriverObject(%p '%wZ' %x)\n",
DriverObject, ServiceName, FileSystem); DriverObject, ServiceName, FileSystem);
ASSERT(ExIsResourceAcquiredExclusiveLite(&IopDriverLoadResource));
*DriverObject = NULL; *DriverObject = NULL;
/* Create ModuleName string */ /* Create ModuleName string */
@ -313,6 +316,7 @@ IopLoadServiceModule(
HANDLE CCSKey, ServiceKey; HANDLE CCSKey, ServiceKey;
PVOID BaseAddress; PVOID BaseAddress;
ASSERT(ExIsResourceAcquiredExclusiveLite(&IopDriverLoadResource));
ASSERT(ServiceName->Length); ASSERT(ServiceName->Length);
DPRINT("IopLoadServiceModule(%wZ, 0x%p)\n", ServiceName, ModuleObject); DPRINT("IopLoadServiceModule(%wZ, 0x%p)\n", ServiceName, ModuleObject);
@ -567,6 +571,8 @@ IopAttachFilterDriversCallback(
ServiceName.MaximumLength = ServiceName.MaximumLength =
ServiceName.Length = (USHORT)wcslen(Filters) * sizeof(WCHAR); ServiceName.Length = (USHORT)wcslen(Filters) * sizeof(WCHAR);
KeEnterCriticalRegion();
ExAcquireResourceExclusiveLite(&IopDriverLoadResource, TRUE);
Status = IopGetDriverObject(&DriverObject, Status = IopGetDriverObject(&DriverObject,
&ServiceName, &ServiceName,
FALSE); FALSE);
@ -575,7 +581,11 @@ IopAttachFilterDriversCallback(
/* Load and initialize the filter driver */ /* Load and initialize the filter driver */
Status = IopLoadServiceModule(&ServiceName, &ModuleObject); Status = IopLoadServiceModule(&ServiceName, &ModuleObject);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{
ExReleaseResourceLite(&IopDriverLoadResource);
KeLeaveCriticalRegion();
return Status; return Status;
}
Status = IopInitializeDriverModule(DeviceNode, Status = IopInitializeDriverModule(DeviceNode,
ModuleObject, ModuleObject,
@ -583,9 +593,16 @@ IopAttachFilterDriversCallback(
FALSE, FALSE,
&DriverObject); &DriverObject);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{
ExReleaseResourceLite(&IopDriverLoadResource);
KeLeaveCriticalRegion();
return Status; return Status;
}
} }
ExReleaseResourceLite(&IopDriverLoadResource);
KeLeaveCriticalRegion();
Status = IopInitializeDevice(DeviceNode, DriverObject); Status = IopInitializeDevice(DeviceNode, DriverObject);
/* Remove extra reference */ /* Remove extra reference */
@ -1971,6 +1988,8 @@ IopLoadUnloadDriver(
DPRINT("FullImagePath: '%wZ'\n", &ImagePath); DPRINT("FullImagePath: '%wZ'\n", &ImagePath);
DPRINT("Type: %lx\n", Type); DPRINT("Type: %lx\n", Type);
KeEnterCriticalRegion();
ExAcquireResourceExclusiveLite(&IopDriverLoadResource, TRUE);
/* /*
* Get existing DriverObject pointer (in case the driver * Get existing DriverObject pointer (in case the driver
* has already been loaded and initialized). * has already been loaded and initialized).
@ -1990,6 +2009,8 @@ IopLoadUnloadDriver(
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT("MmLoadSystemImage() failed (Status %lx)\n", Status); DPRINT("MmLoadSystemImage() failed (Status %lx)\n", Status);
ExReleaseResourceLite(&IopDriverLoadResource);
KeLeaveCriticalRegion();
return Status; return Status;
} }
@ -2000,6 +2021,8 @@ IopLoadUnloadDriver(
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("IopCreateDeviceNode() failed (Status %lx)\n", Status); DPRINT1("IopCreateDeviceNode() failed (Status %lx)\n", Status);
ExReleaseResourceLite(&IopDriverLoadResource);
KeLeaveCriticalRegion();
MmUnloadSystemImage(ModuleObject); MmUnloadSystemImage(ModuleObject);
return Status; return Status;
} }
@ -2015,16 +2038,24 @@ IopLoadUnloadDriver(
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("IopInitializeDriverModule() failed (Status %lx)\n", Status); DPRINT1("IopInitializeDriverModule() failed (Status %lx)\n", Status);
ExReleaseResourceLite(&IopDriverLoadResource);
KeLeaveCriticalRegion();
MmUnloadSystemImage(ModuleObject); MmUnloadSystemImage(ModuleObject);
return Status; return Status;
} }
ExReleaseResourceLite(&IopDriverLoadResource);
KeLeaveCriticalRegion();
/* Initialize and start device */ /* Initialize and start device */
IopInitializeDevice(DeviceNode, *DriverObject); IopInitializeDevice(DeviceNode, *DriverObject);
Status = IopStartDevice(DeviceNode); Status = IopStartDevice(DeviceNode);
} }
else else
{ {
ExReleaseResourceLite(&IopDriverLoadResource);
KeLeaveCriticalRegion();
DPRINT("DriverObject already exist in ObjectManager\n"); DPRINT("DriverObject already exist in ObjectManager\n");
Status = STATUS_IMAGE_ALREADY_LOADED; Status = STATUS_IMAGE_ALREADY_LOADED;

View file

@ -54,6 +54,7 @@ extern KSPIN_LOCK ShutdownListLock;
extern POBJECT_TYPE IoAdapterObjectType; extern POBJECT_TYPE IoAdapterObjectType;
extern ERESOURCE IopDatabaseResource; extern ERESOURCE IopDatabaseResource;
ERESOURCE IopSecurityResource; ERESOURCE IopSecurityResource;
extern ERESOURCE IopDriverLoadResource;
extern KGUARDED_MUTEX PnpNotifyListLock; extern KGUARDED_MUTEX PnpNotifyListLock;
extern LIST_ENTRY IopDiskFileSystemQueueHead; extern LIST_ENTRY IopDiskFileSystemQueueHead;
extern LIST_ENTRY IopCdRomFileSystemQueueHead; extern LIST_ENTRY IopCdRomFileSystemQueueHead;
@ -476,8 +477,9 @@ IoInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
IopInitLookasideLists(); IopInitLookasideLists();
/* Initialize all locks and lists */ /* Initialize all locks and lists */
ExInitializeResource(&IopDatabaseResource); ExInitializeResourceLite(&IopDatabaseResource);
ExInitializeResource(&IopSecurityResource); ExInitializeResourceLite(&IopSecurityResource);
ExInitializeResourceLite(&IopDriverLoadResource);
KeInitializeGuardedMutex(&PnpNotifyListLock); KeInitializeGuardedMutex(&PnpNotifyListLock);
InitializeListHead(&IopDiskFileSystemQueueHead); InitializeListHead(&IopDiskFileSystemQueueHead);
InitializeListHead(&IopCdRomFileSystemQueueHead); InitializeListHead(&IopCdRomFileSystemQueueHead);

View file

@ -21,6 +21,7 @@ ERESOURCE PpRegistryDeviceResource;
KGUARDED_MUTEX PpDeviceReferenceTableLock; KGUARDED_MUTEX PpDeviceReferenceTableLock;
RTL_AVL_TABLE PpDeviceReferenceTable; RTL_AVL_TABLE PpDeviceReferenceTable;
extern ERESOURCE IopDriverLoadResource;
extern ULONG ExpInitializationPhase; extern ULONG ExpInitializationPhase;
extern BOOLEAN ExpInTextModeSetup; extern BOOLEAN ExpInTextModeSetup;
extern BOOLEAN PnpSystemInit; extern BOOLEAN PnpSystemInit;
@ -2611,6 +2612,8 @@ IopActionInitChildServices(PDEVICE_NODE DeviceNode,
PLDR_DATA_TABLE_ENTRY ModuleObject; PLDR_DATA_TABLE_ENTRY ModuleObject;
PDRIVER_OBJECT DriverObject; PDRIVER_OBJECT DriverObject;
KeEnterCriticalRegion();
ExAcquireResourceExclusiveLite(&IopDriverLoadResource, TRUE);
/* Get existing DriverObject pointer (in case the driver has /* Get existing DriverObject pointer (in case the driver has
already been loaded and initialized) */ already been loaded and initialized) */
Status = IopGetDriverObject( Status = IopGetDriverObject(
@ -2642,6 +2645,8 @@ IopActionInitChildServices(PDEVICE_NODE DeviceNode,
if (!BootDrivers) DeviceNode->Problem = CM_PROB_DRIVER_FAILED_LOAD; if (!BootDrivers) DeviceNode->Problem = CM_PROB_DRIVER_FAILED_LOAD;
} }
} }
ExReleaseResourceLite(&IopDriverLoadResource);
KeLeaveCriticalRegion();
/* Driver is loaded and initialized at this point */ /* Driver is loaded and initialized at this point */
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))