https://git.reactos.org/?p=reactos.git;a=commitdiff;h=daf9743c7bcffb0eab59ab...
commit daf9743c7bcffb0eab59abef342b536489da1610 Author: Pierre Schweitzer pierre@reactos.org AuthorDate: Thu Dec 20 08:49:00 2018 +0100 Commit: Pierre Schweitzer pierre@reactos.org CommitDate: Thu Dec 20 08:50:51 2018 +0100
[NTOSKRNL] Check that caller has the priviliege to unload a driver
Also, probe the service name when unloading a driver if called from user-mode. This will avoid that userland applications can trigger an invalid read in the kernel (and thus, a BSOD).
CORE-15468 --- ntoskrnl/io/iomgr/driver.c | 47 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 6 deletions(-)
diff --git a/ntoskrnl/io/iomgr/driver.c b/ntoskrnl/io/iomgr/driver.c index 4e1814dcab..a1584f5810 100644 --- a/ntoskrnl/io/iomgr/driver.c +++ b/ntoskrnl/io/iomgr/driver.c @@ -1187,17 +1187,43 @@ IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers) NTSTATUS Status; PWSTR Start; BOOLEAN SafeToUnload = TRUE; - - DPRINT("IopUnloadDriver('%wZ', %u)\n", DriverServiceName, UnloadPnpDrivers); + KPROCESSOR_MODE PreviousMode; + UNICODE_STRING CapturedServiceName;
PAGED_CODE();
+ PreviousMode = ExGetPreviousMode(); + + /* Need the appropriate priviliege */ + if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode)) + { + DPRINT1("No unload privilege!\n"); + return STATUS_PRIVILEGE_NOT_HELD; + } + + /* Capture the service name */ + Status = ProbeAndCaptureUnicodeString(&CapturedServiceName, PreviousMode, DriverServiceName); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + DPRINT("IopUnloadDriver('%wZ', %u)\n", &CapturedServiceName, UnloadPnpDrivers); + + + /* We need a service name */ + if (CapturedServiceName.Length == 0) + { + ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode); + return STATUS_INVALID_PARAMETER; + } + /* * Get the service name from the registry key name */ - Start = wcsrchr(DriverServiceName->Buffer, L'\'); + Start = wcsrchr(CapturedServiceName.Buffer, L'\'); if (Start == NULL) - Start = DriverServiceName->Buffer; + Start = CapturedServiceName.Buffer; else Start++;
@@ -1211,7 +1237,11 @@ IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers) ObjectName.Buffer = ExAllocatePoolWithTag(PagedPool, ObjectName.MaximumLength, TAG_IO); - if (!ObjectName.Buffer) return STATUS_INSUFFICIENT_RESOURCES; + if (!ObjectName.Buffer) + { + ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode); + return STATUS_INSUFFICIENT_RESOURCES; + } wcscpy(ObjectName.Buffer, DRIVER_ROOT_NAME); memcpy(ObjectName.Buffer + 8, Start, ObjectName.Length - 8 * sizeof(WCHAR)); ObjectName.Buffer[ObjectName.Length/sizeof(WCHAR)] = UNICODE_NULL; @@ -1232,6 +1262,7 @@ IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers) { DPRINT1("Can't locate driver object for %wZ\n", &ObjectName); ExFreePoolWithTag(ObjectName.Buffer, TAG_IO); + ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode); return Status; }
@@ -1243,6 +1274,7 @@ IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers) { DPRINT1("Driver deletion pending\n"); ObDereferenceObject(DriverObject); + ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode); return STATUS_DELETE_PENDING; }
@@ -1258,11 +1290,14 @@ IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers) QueryTable[0].EntryContext = &ImagePath;
Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, - DriverServiceName->Buffer, + CapturedServiceName.Buffer, QueryTable, NULL, NULL);
+ /* We no longer need service name */ + ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode); + if (!NT_SUCCESS(Status)) { DPRINT1("RtlQueryRegistryValues() failed (Status %x)\n", Status);