]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/DnsDxe/DnsImpl.c
NetworkPkg/DnsDxe: [CVE-2018-12178] Check the received packet size before parsing...
[mirror_edk2.git] / NetworkPkg / DnsDxe / DnsImpl.c
index 89ea755cb2b95b094f81e76e352cb771e18a0e44..26a718987cc00451a782898ee2c9fae2b7661aeb 100644 (file)
@@ -1114,6 +1114,7 @@ IsValidDnsResponse (
 \r
   @param  Instance              The DNS instance\r
   @param  RxString              Received buffer.\r
+  @param  Length                Received buffer length.\r
   @param  Completed             Flag to indicate that Dns response is valid.\r
 \r
   @retval EFI_SUCCESS           Parse Dns Response successfully.\r
@@ -1124,12 +1125,14 @@ EFI_STATUS
 ParseDnsResponse (\r
   IN OUT DNS_INSTANCE              *Instance,\r
   IN     UINT8                     *RxString,\r
+  IN     UINT32                    Length,\r
      OUT BOOLEAN                   *Completed\r
   )\r
 {\r
   DNS_HEADER            *DnsHeader;\r
 \r
   CHAR8                 *QueryName;\r
+  UINT32                QueryNameLen;\r
   DNS_QUERY_SECTION     *QuerySection;\r
 \r
   CHAR8                 *AnswerName;\r
@@ -1155,6 +1158,7 @@ ParseDnsResponse (
   DNS6_RESOURCE_RECORD  *Dns6RR;\r
 \r
   EFI_STATUS            Status;\r
+  UINT32                RemainingLength;\r
 \r
   EFI_TPL               OldTpl;\r
 \r
@@ -1178,6 +1182,17 @@ ParseDnsResponse (
 \r
   *Completed       = TRUE;\r
   Status           = EFI_SUCCESS;\r
+  RemainingLength  = Length;\r
+\r
+  //\r
+  // Check whether the remaining packet length is avaiable or not.\r
+  //\r
+  if (RemainingLength <= sizeof (DNS_HEADER)) {\r
+    *Completed = FALSE;\r
+    return EFI_ABORTED;\r
+  } else {\r
+    RemainingLength -= sizeof (DNS_HEADER);\r
+  }\r
 \r
   //\r
   // Get header\r
@@ -1191,22 +1206,38 @@ ParseDnsResponse (
   DnsHeader->AuthorityNum = NTOHS (DnsHeader->AuthorityNum);\r
   DnsHeader->AditionalNum = NTOHS (DnsHeader->AditionalNum);\r
 \r
+  //\r
+  // There is always one QuestionsNum in DNS message. The capability to handle more\r
+  // than one requires to redesign the message format. Currently, it's not supported.\r
+  //\r
+  if (DnsHeader->QuestionsNum > 1) {\r
+    *Completed = FALSE;\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
   //\r
   // Get Query name\r
   //\r
   QueryName = (CHAR8 *) (RxString + sizeof (*DnsHeader));\r
 \r
+  QueryNameLen = (UINT32) AsciiStrLen (QueryName) + 1;\r
+\r
   //\r
-  // Get query section\r
+  // Check whether the remaining packet length is avaiable or not.\r
   //\r
-  QuerySection = (DNS_QUERY_SECTION *) (QueryName + AsciiStrLen (QueryName) + 1);\r
-  QuerySection->Type = NTOHS (QuerySection->Type);\r
-  QuerySection->Class = NTOHS (QuerySection->Class);\r
+  if (RemainingLength <= QueryNameLen + sizeof (DNS_QUERY_SECTION)) {\r
+    *Completed = FALSE;\r
+    return EFI_ABORTED;\r
+  } else {\r
+    RemainingLength -= (QueryNameLen + sizeof (DNS_QUERY_SECTION));\r
+  }\r
 \r
   //\r
-  // Get Answer name\r
+  // Get query section\r
   //\r
-  AnswerName = (CHAR8 *) QuerySection + sizeof (*QuerySection);\r
+  QuerySection = (DNS_QUERY_SECTION *) (QueryName + QueryNameLen);\r
+  QuerySection->Type = NTOHS (QuerySection->Type);\r
+  QuerySection->Class = NTOHS (QuerySection->Class);\r
 \r
   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
 \r
@@ -1341,10 +1372,26 @@ ParseDnsResponse (
 \r
   Status = EFI_NOT_FOUND;\r
 \r
+  //\r
+  // Get Answer name\r
+  //\r
+  AnswerName = (CHAR8 *) QuerySection + sizeof (*QuerySection);\r
+\r
   //\r
   // Processing AnswerSection.\r
   //\r
   while (AnswerSectionNum < DnsHeader->AnswersNum) {\r
+    //\r
+    // Check whether the remaining packet length is avaiable or not.\r
+    //\r
+    if (RemainingLength <= sizeof (UINT16) + sizeof (DNS_ANSWER_SECTION)) {\r
+      *Completed = FALSE;\r
+      Status = EFI_ABORTED;\r
+      goto ON_EXIT;\r
+    } else {\r
+      RemainingLength -= (sizeof (UINT16) + sizeof (DNS_ANSWER_SECTION));\r
+    }\r
+\r
     //\r
     // Answer name should be PTR, else EFI_UNSUPPORTED returned.\r
     //\r
@@ -1362,6 +1409,17 @@ ParseDnsResponse (
     AnswerSection->Ttl = NTOHL (AnswerSection->Ttl);\r
     AnswerSection->DataLength = NTOHS (AnswerSection->DataLength);\r
 \r
+    //\r
+    // Check whether the remaining packet length is avaiable or not.\r
+    //\r
+    if (RemainingLength < AnswerSection->DataLength) {\r
+      *Completed = FALSE;\r
+      Status = EFI_ABORTED;\r
+      goto ON_EXIT;\r
+    } else {\r
+      RemainingLength -= AnswerSection->DataLength;\r
+    }\r
+\r
     //\r
     // Check whether it's the GeneralLookUp querying.\r
     //\r
@@ -1733,6 +1791,7 @@ DnsOnPacketReceived (
   DNS_INSTANCE              *Instance;\r
 \r
   UINT8                     *RcvString;\r
+  UINT32                    Len;\r
 \r
   BOOLEAN                   Completed;\r
 \r
@@ -1748,9 +1807,7 @@ DnsOnPacketReceived (
 \r
   ASSERT (Packet != NULL);\r
 \r
-  if (Packet->TotalSize <= sizeof (DNS_HEADER)) {\r
-    goto ON_EXIT;\r
-  }\r
+  Len = Packet->TotalSize;\r
 \r
   RcvString = NetbufGetByte (Packet, 0, NULL);\r
   ASSERT (RcvString != NULL);\r
@@ -1758,7 +1815,7 @@ DnsOnPacketReceived (
   //\r
   // Parse Dns Response\r
   //\r
-  ParseDnsResponse (Instance, RcvString, &Completed);\r
+  ParseDnsResponse (Instance, RcvString, Len, &Completed);\r
 \r
 ON_EXIT:\r
 \r