[HDAUDBUS] Prevent overflow of the AudioGroups array. CORE-14153 CORE-15465
authorThomas Faber <thomas.faber@reactos.org>
Wed, 27 Feb 2019 09:51:02 +0000 (10:51 +0100)
committerThomas Faber <thomas.faber@reactos.org>
Wed, 27 Feb 2019 10:04:23 +0000 (11:04 +0100)
This protects against crashing in case of faulty/malicious hardware,
but also works around a bug in HDA_SendVerbs that causes it to return
invalid data, thereby suggesting more groups than are actually present.

drivers/wdm/audio/hdaudbus/fdo.cpp
drivers/wdm/audio/hdaudbus/hdaudbus.cpp

index 84686e3..64a0c6a 100644 (file)
@@ -222,6 +222,11 @@ HDA_InitCodec(
         DPRINT1("NodeId %u GroupType %x\n", NodeId, GroupType);
 
         if ((GroupType & FUNCTION_GROUP_NODETYPE_MASK) == FUNCTION_GROUP_NODETYPE_AUDIO) {
+            if (Entry->AudioGroupCount >= HDA_MAX_AUDIO_GROUPS)
+            {
+                DPRINT1("Too many audio groups in node %u. Skipping.\n", NodeId);
+                break;
+            }
 
             AudioGroup = (PHDA_CODEC_AUDIO_GROUP)AllocateItem(NonPagedPool, sizeof(HDA_CODEC_AUDIO_GROUP));
             if (!AudioGroup)
@@ -682,6 +687,7 @@ HDA_FDORemoveDevice(
             continue;
         }
 
+        ASSERT(CodecEntry->AudioGroupCount <= HDA_MAX_AUDIO_GROUPS);
         for (AFGIndex = 0; AFGIndex < CodecEntry->AudioGroupCount; AFGIndex++)
         {
             ChildPDO = CodecEntry->AudioGroups[AFGIndex]->ChildPDO;
@@ -743,6 +749,7 @@ HDA_FDOQueryBusRelations(
             continue;
 
         Codec = DeviceExtension->Codecs[CodecIndex];
+        ASSERT(Codec->AudioGroupCount <= HDA_MAX_AUDIO_GROUPS);
         for (AFGIndex = 0; AFGIndex < Codec->AudioGroupCount; AFGIndex++)
         {
             DeviceRelations->Objects[DeviceRelations->Count] = Codec->AudioGroups[AFGIndex]->ChildPDO;
index 3e1ef9d..aa62a82 100644 (file)
@@ -63,6 +63,7 @@ HDA_FdoPnp(
         {
             CodecEntry = FDODeviceExtension->Codecs[CodecIndex];
 
+            ASSERT(CodecEntry->AudioGroupCount <= HDA_MAX_AUDIO_GROUPS);
             for (AFGIndex = 0; AFGIndex < CodecEntry->AudioGroupCount; AFGIndex++)
             {
                 ChildDeviceExtension = static_cast<PHDA_PDO_DEVICE_EXTENSION>(CodecEntry->AudioGroups[AFGIndex]->ChildPDO->DeviceExtension);