https://git.reactos.org/?p=reactos.git;a=commitdiff;h=111e19f8a49ccfd1a4f50…
commit 111e19f8a49ccfd1a4f5080640921de6729be649
Author:     Vadim Galyant <vgal(a)rambler.ru>
AuthorDate: Mon Mar 19 22:04:17 2018 +0900
Commit:     Hermès BÉLUSCA - MAÏTO <hermes.belusca-maito(a)reactos.org>
CommitDate: Mon Mar 19 14:04:17 2018 +0100
    [NTOSKRNL] Adding IopValidateID() to test characters in PnP IDs (IRP_MN_QUERY_ID).
(#341)
---
 ntoskrnl/io/pnpmgr/pnpmgr.c | 143 +++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 129 insertions(+), 14 deletions(-)
diff --git a/ntoskrnl/io/pnpmgr/pnpmgr.c b/ntoskrnl/io/pnpmgr/pnpmgr.c
index e32c5c3495..dd75f7f947 100644
--- a/ntoskrnl/io/pnpmgr/pnpmgr.c
+++ b/ntoskrnl/io/pnpmgr/pnpmgr.c
@@ -26,6 +26,10 @@ extern ULONG ExpInitializationPhase;
 extern BOOLEAN ExpInTextModeSetup;
 extern BOOLEAN PnpSystemInit;
+#define MAX_DEVICE_ID_LEN          200
+#define MAX_SEPARATORS_INSTANCEID  0
+#define MAX_SEPARATORS_DEVICEID    1
+
 /* DATA **********************************************************************/
 PDRIVER_OBJECT IopRootDriverObject;
@@ -1760,6 +1764,95 @@ cleanup:
     return Status;
 }
+static
+BOOLEAN
+IopValidateID(
+    _In_ PWCHAR Id,
+    _In_ BUS_QUERY_ID_TYPE QueryType)
+{
+    PWCHAR PtrChar;
+    PWCHAR StringEnd;
+    WCHAR Char;
+    ULONG SeparatorsCount = 0;
+    PWCHAR PtrPrevChar = NULL;
+    ULONG MaxSeparators;
+    BOOLEAN IsMultiSz;
+
+    PAGED_CODE();
+
+    switch (QueryType)
+    {
+        case BusQueryDeviceID:
+            MaxSeparators = MAX_SEPARATORS_DEVICEID;
+            IsMultiSz = FALSE;
+            break;
+        case BusQueryInstanceID:
+            MaxSeparators = MAX_SEPARATORS_INSTANCEID;
+            IsMultiSz = FALSE;
+            break;
+
+        case BusQueryHardwareIDs:
+        case BusQueryCompatibleIDs:
+            IsMultiSz = TRUE;
+            break;
+
+        default:
+            DPRINT1("IopValidateID: Not handled QueryType - %x\n", QueryType);
+            return FALSE;
+    }
+
+    StringEnd = Id + MAX_DEVICE_ID_LEN;
+
+    for (PtrChar = Id; PtrChar < StringEnd; PtrChar++)
+    {
+        Char = *PtrChar;
+
+        if (Char == UNICODE_NULL)
+        {
+            if (!IsMultiSz || (PtrPrevChar && PtrChar == PtrPrevChar + 1))
+            {
+                if (MaxSeparators == SeparatorsCount || IsMultiSz)
+                {
+                    return TRUE;
+                }
+
+                DPRINT1("IopValidateID: SeparatorsCount - %lu, MaxSeparators -
%lu\n",
+                        SeparatorsCount, MaxSeparators);
+                goto ErrorExit;
+            }
+
+            StringEnd = PtrChar + MAX_DEVICE_ID_LEN + 1;
+            PtrPrevChar = PtrChar;
+        }
+        else if (Char < ' ' || Char > 0x7F || Char == ',')
+        {
+            DPRINT1("IopValidateID: Invalid character - %04X\n", Char);
+            goto ErrorExit;
+        }
+        else if (Char == ' ')
+        {
+            *PtrChar = '_';
+        }
+        else if (Char == '\\')
+        {
+            SeparatorsCount++;
+
+            if (SeparatorsCount > MaxSeparators)
+            {
+                DPRINT1("IopValidateID: SeparatorsCount - %lu, MaxSeparators -
%lu\n",
+                        SeparatorsCount, MaxSeparators);
+                goto ErrorExit;
+            }
+        }
+    }
+
+    DPRINT1("IopValidateID: Not terminated ID\n");
+
+ErrorExit:
+    // FIXME logging
+    return FALSE;
+}
+
 NTSTATUS
 IopQueryHardwareIds(PDEVICE_NODE DeviceNode,
                     HANDLE InstanceKey)
@@ -1770,6 +1863,7 @@ IopQueryHardwareIds(PDEVICE_NODE DeviceNode,
    UNICODE_STRING ValueName;
    NTSTATUS Status;
    ULONG Length, TotalLength;
+   BOOLEAN IsValidID;
    DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
@@ -1781,11 +1875,15 @@ IopQueryHardwareIds(PDEVICE_NODE DeviceNode,
                               &Stack);
    if (NT_SUCCESS(Status))
    {
-      /*
-       * FIXME: Check for valid characters, if there is invalid characters
-       * then bugcheck.
-       */
+      IsValidID = IopValidateID((PWCHAR)IoStatusBlock.Information, BusQueryHardwareIDs);
+
+      if (!IsValidID)
+      {
+         DPRINT1("Invalid HardwareIDs. DeviceNode - %p\n", DeviceNode);
+      }
+
       TotalLength = 0;
+
       Ptr = (PWSTR)IoStatusBlock.Information;
       DPRINT("Hardware IDs:\n");
       while (*Ptr)
@@ -1829,6 +1927,7 @@ IopQueryCompatibleIds(PDEVICE_NODE DeviceNode,
    UNICODE_STRING ValueName;
    NTSTATUS Status;
    ULONG Length, TotalLength;
+   BOOLEAN IsValidID;
    DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
@@ -1841,11 +1940,15 @@ IopQueryCompatibleIds(PDEVICE_NODE DeviceNode,
       &Stack);
    if (NT_SUCCESS(Status) && IoStatusBlock.Information)
    {
-      /*
-      * FIXME: Check for valid characters, if there is invalid characters
-      * then bugcheck.
-      */
+      IsValidID = IopValidateID((PWCHAR)IoStatusBlock.Information,
BusQueryCompatibleIDs);
+
+      if (!IsValidID)
+      {
+         DPRINT1("Invalid CompatibleIDs. DeviceNode - %p\n", DeviceNode);
+      }
+
       TotalLength = 0;
+
       Ptr = (PWSTR)IoStatusBlock.Information;
       DPRINT("Compatible IDs:\n");
       while (*Ptr)
@@ -1891,6 +1994,7 @@ IopCreateDeviceInstancePath(
     NTSTATUS Status;
     UNICODE_STRING ParentIdPrefix = { 0, 0, NULL };
     DEVICE_CAPABILITIES DeviceCapabilities;
+    BOOLEAN IsValidID;
     DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
@@ -1905,14 +2009,16 @@ IopCreateDeviceInstancePath(
         return Status;
     }
+    IsValidID = IopValidateID((PWCHAR)IoStatusBlock.Information, BusQueryDeviceID);
+
+    if (!IsValidID)
+    {
+        DPRINT1("Invalid DeviceID. DeviceNode - %p\n", DeviceNode);
+    }
+
     /* Save the device id string */
     RtlInitUnicodeString(&DeviceId, (PWSTR)IoStatusBlock.Information);
-    /*
-     * FIXME: Check for valid characters, if there is invalid characters
-     * then bugcheck.
-     */
-
     DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after
enumeration)\n");
     Status = IopQueryDeviceCapabilities(DeviceNode, &DeviceCapabilities);
@@ -1962,6 +2068,16 @@ IopCreateDeviceInstancePath(
         ASSERT(IoStatusBlock.Information == 0);
     }
+    if (IoStatusBlock.Information)
+    {
+        IsValidID = IopValidateID((PWCHAR)IoStatusBlock.Information, BusQueryInstanceID);
+
+        if (!IsValidID)
+        {
+            DPRINT1("Invalid InstanceID. DeviceNode - %p\n", DeviceNode);
+        }
+    }
+
     RtlInitUnicodeString(&InstanceId,
                          (PWSTR)IoStatusBlock.Information);
@@ -2012,7 +2128,6 @@ IopCreateDeviceInstancePath(
     return STATUS_SUCCESS;
 }
-
 /*
  * IopActionInterrogateDeviceStack
  *