https://git.reactos.org/?p=reactos.git;a=commitdiff;h=daf9743c7bcffb0eab59a…
commit daf9743c7bcffb0eab59abef342b536489da1610
Author: Pierre Schweitzer <pierre(a)reactos.org>
AuthorDate: Thu Dec 20 08:49:00 2018 +0100
Commit: Pierre Schweitzer <pierre(a)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);