]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
NetworkPkg: Check allocated buffer pointer before use.
[mirror_edk2.git] / NetworkPkg / UefiPxeBcDxe / PxeBcDhcp6.c
index 6a08e9a2de68a56cebf1c71174ec6364af4119bc..327b4cf1cfc5fc0f3e1ef388d51e05e188871756 100644 (file)
@@ -2,7 +2,7 @@
   Functions implementation related with DHCPv6 for UefiPxeBc Driver.\r
 \r
   (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>\r
   Functions implementation related with DHCPv6 for UefiPxeBc Driver.\r
 \r
   (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>\r
-  Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
@@ -93,11 +93,12 @@ PxeBcBuildDhcp6Options (
   // Append client option request option\r
   //\r
   OptList[Index]->OpCode     = HTONS (DHCP6_OPT_ORO);\r
   // Append client option request option\r
   //\r
   OptList[Index]->OpCode     = HTONS (DHCP6_OPT_ORO);\r
-  OptList[Index]->OpLen      = HTONS (6);\r
+  OptList[Index]->OpLen      = HTONS (8);\r
   OptEnt.Oro                 = (PXEBC_DHCP6_OPTION_ORO *) OptList[Index]->Data;\r
   OptEnt.Oro->OpCode[0]      = HTONS(DHCP6_OPT_BOOT_FILE_URL);\r
   OptEnt.Oro->OpCode[1]      = HTONS(DHCP6_OPT_BOOT_FILE_PARAM);\r
   OptEnt.Oro->OpCode[2]      = HTONS(DHCP6_OPT_DNS_SERVERS);\r
   OptEnt.Oro                 = (PXEBC_DHCP6_OPTION_ORO *) OptList[Index]->Data;\r
   OptEnt.Oro->OpCode[0]      = HTONS(DHCP6_OPT_BOOT_FILE_URL);\r
   OptEnt.Oro->OpCode[1]      = HTONS(DHCP6_OPT_BOOT_FILE_PARAM);\r
   OptEnt.Oro->OpCode[2]      = HTONS(DHCP6_OPT_DNS_SERVERS);\r
+  OptEnt.Oro->OpCode[3]      = HTONS(DHCP6_OPT_VENDOR_CLASS);\r
   Index++;\r
   OptList[Index]             = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]);\r
 \r
   Index++;\r
   OptList[Index]             = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]);\r
 \r
@@ -181,17 +182,24 @@ PxeBcBuildDhcp6Options (
   @param[in]  Dst          The pointer to the cache buffer for DHCPv6 packet.\r
   @param[in]  Src          The pointer to the DHCPv6 packet to be cached.\r
 \r
   @param[in]  Dst          The pointer to the cache buffer for DHCPv6 packet.\r
   @param[in]  Src          The pointer to the DHCPv6 packet to be cached.\r
 \r
+  @retval     EFI_SUCCESS                Packet is copied.\r
+  @retval     EFI_BUFFER_TOO_SMALL       Cache buffer is not big enough to hold the packet.\r
+\r
 **/\r
 **/\r
-VOID\r
+EFI_STATUS\r
 PxeBcCacheDhcp6Packet (\r
   IN EFI_DHCP6_PACKET          *Dst,\r
   IN EFI_DHCP6_PACKET          *Src\r
   )\r
 {\r
 PxeBcCacheDhcp6Packet (\r
   IN EFI_DHCP6_PACKET          *Dst,\r
   IN EFI_DHCP6_PACKET          *Src\r
   )\r
 {\r
-  ASSERT (Dst->Size >= Src->Length);\r
+  if (Dst->Size < Src->Length) {\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
 \r
   CopyMem (&Dst->Dhcp6, &Src->Dhcp6, Src->Length);\r
   Dst->Length = Src->Length;\r
 \r
   CopyMem (&Dst->Dhcp6, &Src->Dhcp6, Src->Length);\r
   Dst->Length = Src->Length;\r
+\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 \r
 }\r
 \r
 \r
@@ -749,8 +757,11 @@ PxeBcParseDhcp6Packet (
   @param[in]  Ack                 The pointer to the DHCPv6 ack packet.\r
   @param[in]  Verified            If TRUE, parse the ACK packet and store info into mode data.\r
 \r
   @param[in]  Ack                 The pointer to the DHCPv6 ack packet.\r
   @param[in]  Verified            If TRUE, parse the ACK packet and store info into mode data.\r
 \r
+  @retval     EFI_SUCCESS                Cache and parse the packet successfully.\r
+  @retval     EFI_BUFFER_TOO_SMALL       Cache buffer is not big enough to hold the packet.\r
+\r
 **/\r
 **/\r
-VOID\r
+EFI_STATUS\r
 PxeBcCopyDhcp6Ack (\r
   IN PXEBC_PRIVATE_DATA   *Private,\r
   IN EFI_DHCP6_PACKET     *Ack,\r
 PxeBcCopyDhcp6Ack (\r
   IN PXEBC_PRIVATE_DATA   *Private,\r
   IN EFI_DHCP6_PACKET     *Ack,\r
@@ -758,10 +769,14 @@ PxeBcCopyDhcp6Ack (
   )\r
 {\r
   EFI_PXE_BASE_CODE_MODE  *Mode;\r
   )\r
 {\r
   EFI_PXE_BASE_CODE_MODE  *Mode;\r
+  EFI_STATUS              Status;\r
 \r
   Mode = Private->PxeBc.Mode;\r
 \r
 \r
   Mode = Private->PxeBc.Mode;\r
 \r
-  PxeBcCacheDhcp6Packet (&Private->DhcpAck.Dhcp6.Packet.Ack, Ack);\r
+  Status = PxeBcCacheDhcp6Packet (&Private->DhcpAck.Dhcp6.Packet.Ack, Ack);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
   if (Verified) {\r
     //\r
 \r
   if (Verified) {\r
     //\r
@@ -771,6 +786,8 @@ PxeBcCopyDhcp6Ack (
     CopyMem (&Mode->DhcpAck.Dhcpv6, &Ack->Dhcp6, Ack->Length);\r
     Mode->DhcpAckReceived = TRUE;\r
   }\r
     CopyMem (&Mode->DhcpAck.Dhcpv6, &Ack->Dhcp6, Ack->Length);\r
     Mode->DhcpAckReceived = TRUE;\r
   }\r
+\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 \r
 }\r
 \r
 \r
@@ -780,8 +797,11 @@ PxeBcCopyDhcp6Ack (
   @param[in]  Private               The pointer to PxeBc private data.\r
   @param[in]  OfferIndex            The received order of offer packets.\r
 \r
   @param[in]  Private               The pointer to PxeBc private data.\r
   @param[in]  OfferIndex            The received order of offer packets.\r
 \r
+  @retval     EFI_SUCCESS                Cache and parse the packet successfully.\r
+  @retval     EFI_BUFFER_TOO_SMALL       Cache buffer is not big enough to hold the packet.\r
+\r
 **/\r
 **/\r
-VOID\r
+EFI_STATUS\r
 PxeBcCopyDhcp6Proxy (\r
   IN PXEBC_PRIVATE_DATA     *Private,\r
   IN UINT32                 OfferIndex\r
 PxeBcCopyDhcp6Proxy (\r
   IN PXEBC_PRIVATE_DATA     *Private,\r
   IN UINT32                 OfferIndex\r
@@ -789,6 +809,7 @@ PxeBcCopyDhcp6Proxy (
 {\r
   EFI_PXE_BASE_CODE_MODE    *Mode;\r
   EFI_DHCP6_PACKET          *Offer;\r
 {\r
   EFI_PXE_BASE_CODE_MODE    *Mode;\r
   EFI_DHCP6_PACKET          *Offer;\r
+  EFI_STATUS              Status;\r
 \r
   ASSERT (OfferIndex < Private->OfferNum);\r
   ASSERT (OfferIndex < PXEBC_OFFER_MAX_NUM);\r
 \r
   ASSERT (OfferIndex < Private->OfferNum);\r
   ASSERT (OfferIndex < PXEBC_OFFER_MAX_NUM);\r
@@ -799,7 +820,10 @@ PxeBcCopyDhcp6Proxy (
   //\r
   // Cache the proxy offer packet and parse it.\r
   //\r
   //\r
   // Cache the proxy offer packet and parse it.\r
   //\r
-  PxeBcCacheDhcp6Packet (&Private->ProxyOffer.Dhcp6.Packet.Offer, Offer);\r
+  Status = PxeBcCacheDhcp6Packet (&Private->ProxyOffer.Dhcp6.Packet.Offer, Offer);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
   PxeBcParseDhcp6Packet (&Private->ProxyOffer.Dhcp6);\r
 \r
   //\r
   PxeBcParseDhcp6Packet (&Private->ProxyOffer.Dhcp6);\r
 \r
   //\r
@@ -807,6 +831,8 @@ PxeBcCopyDhcp6Proxy (
   //\r
   CopyMem (&Mode->ProxyOffer.Dhcpv6, &Offer->Dhcp6, Offer->Length);\r
   Mode->ProxyOfferReceived = TRUE;\r
   //\r
   CopyMem (&Mode->ProxyOffer.Dhcpv6, &Offer->Dhcp6, Offer->Length);\r
   Mode->ProxyOfferReceived = TRUE;\r
+\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
@@ -882,12 +908,12 @@ PxeBcRequestBootService (
   UINT16                              OpCode;\r
   UINT16                              OpLen;\r
   EFI_STATUS                          Status;\r
   UINT16                              OpCode;\r
   UINT16                              OpLen;\r
   EFI_STATUS                          Status;\r
-  EFI_DHCP6_PACKET                    *ProxyOffer;\r
+  EFI_DHCP6_PACKET                    *IndexOffer;\r
   UINT8                               *Option;\r
 \r
   PxeBc       = &Private->PxeBc;\r
   Request     = Private->Dhcp6Request;\r
   UINT8                               *Option;\r
 \r
   PxeBc       = &Private->PxeBc;\r
   Request     = Private->Dhcp6Request;\r
-  ProxyOffer = &Private->OfferBuffer[Index].Dhcp6.Packet.Offer;\r
+  IndexOffer  = &Private->OfferBuffer[Index].Dhcp6.Packet.Offer;\r
   SrcPort     = PXEBC_BS_DISCOVER_PORT;\r
   DestPort    = PXEBC_BS_DISCOVER_PORT;\r
   OpFlags     = 0;\r
   SrcPort     = PXEBC_BS_DISCOVER_PORT;\r
   DestPort    = PXEBC_BS_DISCOVER_PORT;\r
   OpFlags     = 0;\r
@@ -904,7 +930,7 @@ PxeBcRequestBootService (
   //\r
   // Build the request packet by the cached request packet before.\r
   //\r
   //\r
   // Build the request packet by the cached request packet before.\r
   //\r
-  Discover->TransactionId = ProxyOffer->Dhcp6.Header.TransactionId;\r
+  Discover->TransactionId = IndexOffer->Dhcp6.Header.TransactionId;\r
   Discover->MessageType   = Request->Dhcp6.Header.MessageType;\r
   RequestOpt              = Request->Dhcp6.Option;\r
   DiscoverOpt             = Discover->DhcpOptions;\r
   Discover->MessageType   = Request->Dhcp6.Header.MessageType;\r
   RequestOpt              = Request->Dhcp6.Option;\r
   DiscoverOpt             = Discover->DhcpOptions;\r
@@ -914,22 +940,24 @@ PxeBcRequestBootService (
   //\r
   // Find Server ID Option from ProxyOffer.\r
   //\r
   //\r
   // Find Server ID Option from ProxyOffer.\r
   //\r
-  Option = PxeBcDhcp6SeekOption (\r
-             ProxyOffer->Dhcp6.Option,\r
-             ProxyOffer->Length - 4,\r
-             DHCP6_OPT_SERVER_ID\r
-             );\r
-  if (Option == NULL) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
+  if (Private->OfferBuffer[Index].Dhcp6.OfferType == PxeOfferTypeProxyBinl) {  \r
+    Option = PxeBcDhcp6SeekOption (\r
+               IndexOffer->Dhcp6.Option,\r
+               IndexOffer->Length - 4,\r
+               DHCP6_OPT_SERVER_ID\r
+               );\r
+    if (Option == NULL) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
   \r
   \r
-  //\r
-  // Add Server ID Option.\r
-  //\r
-  OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *) Option)->OpLen);\r
-  CopyMem (DiscoverOpt, Option, OpLen + 4);\r
-  DiscoverOpt += (OpLen + 4);\r
-  DiscoverLen += (OpLen + 4);\r
+    //\r
+    // Add Server ID Option.\r
+    //\r
+    OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *) Option)->OpLen);\r
+    CopyMem (DiscoverOpt, Option, OpLen + 4);\r
+    DiscoverOpt += (OpLen + 4);\r
+    DiscoverLen += (OpLen + 4);\r
+  }\r
 \r
   while (RequestLen < Request->Length) {\r
     OpCode = NTOHS (((EFI_DHCP6_PACKET_OPTION *) RequestOpt)->OpCode);\r
 \r
   while (RequestLen < Request->Length) {\r
     OpCode = NTOHS (((EFI_DHCP6_PACKET_OPTION *) RequestOpt)->OpCode);\r
@@ -1053,7 +1081,7 @@ PxeBcRetryDhcp6Binl (
   Mode                  = Private->PxeBc.Mode;\r
   Private->IsDoDiscover = FALSE;\r
   Offer                 = &Private->OfferBuffer[Index].Dhcp6;\r
   Mode                  = Private->PxeBc.Mode;\r
   Private->IsDoDiscover = FALSE;\r
   Offer                 = &Private->OfferBuffer[Index].Dhcp6;\r
-  if (Offer->OfferType == PxeOfferTypeDhcpBinl) {\r
+  if (Offer->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL] == NULL) {\r
     //\r
     // There is no BootFileUrl option in dhcp6 offer, so use servers multi-cast address instead.\r
     //\r
     //\r
     // There is no BootFileUrl option in dhcp6 offer, so use servers multi-cast address instead.\r
     //\r
@@ -1121,8 +1149,10 @@ PxeBcRetryDhcp6Binl (
   @param[in]  Private               The pointer to PXEBC_PRIVATE_DATA.\r
   @param[in]  RcvdOffer             The pointer to the received offer packet.\r
 \r
   @param[in]  Private               The pointer to PXEBC_PRIVATE_DATA.\r
   @param[in]  RcvdOffer             The pointer to the received offer packet.\r
 \r
+  @retval     EFI_SUCCESS      Cache and parse the packet successfully.\r
+  @retval     Others           Operation failed.\r
 **/\r
 **/\r
-VOID\r
+EFI_STATUS\r
 PxeBcCacheDhcp6Offer (\r
   IN PXEBC_PRIVATE_DATA     *Private,\r
   IN EFI_DHCP6_PACKET       *RcvdOffer\r
 PxeBcCacheDhcp6Offer (\r
   IN PXEBC_PRIVATE_DATA     *Private,\r
   IN EFI_DHCP6_PACKET       *RcvdOffer\r
@@ -1131,6 +1161,7 @@ PxeBcCacheDhcp6Offer (
   PXEBC_DHCP6_PACKET_CACHE  *Cache6;\r
   EFI_DHCP6_PACKET          *Offer;\r
   PXEBC_OFFER_TYPE          OfferType;\r
   PXEBC_DHCP6_PACKET_CACHE  *Cache6;\r
   EFI_DHCP6_PACKET          *Offer;\r
   PXEBC_OFFER_TYPE          OfferType;\r
+  EFI_STATUS                Status;\r
 \r
   Cache6 = &Private->OfferBuffer[Private->OfferNum].Dhcp6;\r
   Offer  = &Cache6->Packet.Offer;\r
 \r
   Cache6 = &Private->OfferBuffer[Private->OfferNum].Dhcp6;\r
   Offer  = &Cache6->Packet.Offer;\r
@@ -1138,13 +1169,16 @@ PxeBcCacheDhcp6Offer (
   //\r
   // Cache the content of DHCPv6 packet firstly.\r
   //\r
   //\r
   // Cache the content of DHCPv6 packet firstly.\r
   //\r
-  PxeBcCacheDhcp6Packet (Offer, RcvdOffer);\r
+  Status = PxeBcCacheDhcp6Packet (Offer, RcvdOffer);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
   //\r
   // Validate the DHCPv6 packet, and parse the options and offer type.\r
   //\r
   if (EFI_ERROR (PxeBcParseDhcp6Packet (Cache6))) {\r
 \r
   //\r
   // Validate the DHCPv6 packet, and parse the options and offer type.\r
   //\r
   if (EFI_ERROR (PxeBcParseDhcp6Packet (Cache6))) {\r
-    return ;\r
+    return EFI_ABORTED;\r
   }\r
 \r
   //\r
   }\r
 \r
   //\r
@@ -1166,14 +1200,15 @@ PxeBcCacheDhcp6Offer (
       //\r
       Private->OfferIndex[OfferType][Private->OfferCount[OfferType]] = Private->OfferNum;\r
       Private->OfferCount[OfferType]++;\r
       //\r
       Private->OfferIndex[OfferType][Private->OfferCount[OfferType]] = Private->OfferNum;\r
       Private->OfferCount[OfferType]++;\r
-    } else if (Private->OfferCount[OfferType] > 0) {\r
+    } else if ((OfferType == PxeOfferTypeProxyPxe10 || OfferType == PxeOfferTypeProxyWfm11a) && \r
+                 Private->OfferCount[OfferType] < 1) {\r
       //\r
       // Only cache the first PXE10/WFM11a offer, and discard the others.\r
       //\r
       Private->OfferIndex[OfferType][0] = Private->OfferNum;\r
       Private->OfferCount[OfferType]    = 1;\r
     } else {\r
       //\r
       // Only cache the first PXE10/WFM11a offer, and discard the others.\r
       //\r
       Private->OfferIndex[OfferType][0] = Private->OfferNum;\r
       Private->OfferCount[OfferType]    = 1;\r
     } else {\r
-      return;\r
+      return EFI_ABORTED;\r
     }\r
   } else {\r
     //\r
     }\r
   } else {\r
     //\r
@@ -1184,6 +1219,8 @@ PxeBcCacheDhcp6Offer (
   }\r
 \r
   Private->OfferNum++;\r
   }\r
 \r
   Private->OfferNum++;\r
+\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 \r
 }\r
 \r
 \r
@@ -1301,6 +1338,7 @@ PxeBcSelectDhcp6Offer (
   @retval     EFI_SUCCESS           Handled the DHCPv6 offer packet successfully.\r
   @retval     EFI_NO_RESPONSE       No response to the following request packet.\r
   @retval     EFI_OUT_OF_RESOURCES  Failed to allocate resources.\r
   @retval     EFI_SUCCESS           Handled the DHCPv6 offer packet successfully.\r
   @retval     EFI_NO_RESPONSE       No response to the following request packet.\r
   @retval     EFI_OUT_OF_RESOURCES  Failed to allocate resources.\r
+  @retval     EFI_BUFFER_TOO_SMALL  Can't cache the offer pacet.\r
 \r
 **/\r
 EFI_STATUS\r
 \r
 **/\r
 EFI_STATUS\r
@@ -1410,7 +1448,7 @@ PxeBcHandleDhcp6Offer (
         //\r
         // Success to try to request by a ProxyPxe10 or ProxyWfm11a offer, copy and parse it.\r
         //\r
         //\r
         // Success to try to request by a ProxyPxe10 or ProxyWfm11a offer, copy and parse it.\r
         //\r
-        PxeBcCopyDhcp6Proxy (Private, ProxyIndex);\r
+        Status = PxeBcCopyDhcp6Proxy (Private, ProxyIndex);\r
       }\r
     } else {\r
       //\r
       }\r
     } else {\r
       //\r
@@ -1424,7 +1462,7 @@ PxeBcHandleDhcp6Offer (
     //\r
     // All PXE boot information is ready by now.\r
     //\r
     //\r
     // All PXE boot information is ready by now.\r
     //\r
-    PxeBcCopyDhcp6Ack (Private, &Private->DhcpAck.Dhcp6.Packet.Ack, TRUE);\r
+    Status = PxeBcCopyDhcp6Ack (Private, &Private->DhcpAck.Dhcp6.Packet.Ack, TRUE);\r
     Private->PxeBc.Mode->DhcpDiscoverValid = TRUE;\r
   }\r
 \r
     Private->PxeBc.Mode->DhcpDiscoverValid = TRUE;\r
   }\r
 \r
@@ -1992,24 +2030,23 @@ PxeBcDhcp6CallBack (
       SelectAd   = &Private->OfferBuffer[Private->SelectIndex - 1].Dhcp6.Packet.Offer;\r
       *NewPacket = AllocateZeroPool (SelectAd->Size);\r
       ASSERT (*NewPacket != NULL);\r
       SelectAd   = &Private->OfferBuffer[Private->SelectIndex - 1].Dhcp6.Packet.Offer;\r
       *NewPacket = AllocateZeroPool (SelectAd->Size);\r
       ASSERT (*NewPacket != NULL);\r
+      if (*NewPacket == NULL) {\r
+        return EFI_ABORTED;\r
+      }\r
       CopyMem (*NewPacket, SelectAd, SelectAd->Size);\r
     }\r
     break;\r
 \r
   case Dhcp6RcvdReply:\r
       CopyMem (*NewPacket, SelectAd, SelectAd->Size);\r
     }\r
     break;\r
 \r
   case Dhcp6RcvdReply:\r
-    if (Packet->Length > PXEBC_DHCP6_PACKET_MAX_SIZE) {\r
-      //\r
-      // Abort the DHCP if the Peply packet exceeds the maximum length.\r
-      //\r
-         Status = EFI_ABORTED;\r
-      break;\r
-    }\r
     //\r
     // Cache the dhcp ack to Private->Dhcp6Ack, but it's not the final ack in mode data\r
     // without verification.\r
     //\r
     ASSERT (Private->SelectIndex != 0);\r
     //\r
     // Cache the dhcp ack to Private->Dhcp6Ack, but it's not the final ack in mode data\r
     // without verification.\r
     //\r
     ASSERT (Private->SelectIndex != 0);\r
-    PxeBcCopyDhcp6Ack (Private, Packet, FALSE);\r
+    Status = PxeBcCopyDhcp6Ack (Private, Packet, FALSE);\r
+    if (EFI_ERROR (Status)) {\r
+      Status = EFI_ABORTED;\r
+    }\r
     break;\r
 \r
   default:\r
     break;\r
 \r
   default:\r