--- /dev/null
+From fac297724e6cc343430cd0104e55cd7a96d1151e Mon Sep 17 00:00:00 2001
+From: Doug Flick <dougflick@microsoft.com>
+Date: Fri, 26 Jan 2024 05:54:55 +0800
+Subject: [PATCH] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Patch
+
+REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4540
+
+Bug Details:
+PixieFail Bug #7
+CVE-2023-45235
+CVSS 8.3 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:H
+CWE-119 Improper Restriction of Operations within the Bounds of
+ a Memory Buffer
+
+Buffer overflow when handling Server ID option from a DHCPv6 proxy
+Advertise message
+
+Change Overview:
+
+Performs two checks
+
+1. Checks that the length of the duid is accurate
+> + //
+> + // Check that the minimum and maximum requirements are met
+> + //
+> + if ((OpLen < PXEBC_MIN_SIZE_OF_DUID) ||
+(OpLen > PXEBC_MAX_SIZE_OF_DUID)) {
+> + Status = EFI_INVALID_PARAMETER;
+> + goto ON_ERROR;
+> + }
+
+2. Ensures that the amount of data written to the buffer is tracked and
+never exceeds that
+> + //
+> + // Check that the option length is valid.
+> + //
+> + if ((DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN)
+ > DiscoverLenNeeded) {
+> + Status = EFI_OUT_OF_RESOURCES;
+> + goto ON_ERROR;
+> + }
+
+Additional code clean up and fix for memory leak in case Option was NULL
+
+Cc: Saloni Kasbekar <saloni.kasbekar@intel.com>
+Cc: Zachary Clark-williams <zachary.clark-williams@intel.com>
+
+Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
+Reviewed-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
+
+CVE: CVE-2023-45235
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/fac297724e6cc343430cd0104e55cd7a96d1151e]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c | 77 ++++++++++++++++++++++------
+ NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h | 17 ++++++
+ 2 files changed, 78 insertions(+), 16 deletions(-)
+
+diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
+index 2b2d372889..7fd1281c11 100644
+--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
++++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
+@@ -887,6 +887,7 @@ PxeBcRequestBootService (
+ EFI_STATUS Status;\r
+ EFI_DHCP6_PACKET *IndexOffer;\r
+ UINT8 *Option;\r
++ UINTN DiscoverLenNeeded;\r
+ \r
+ PxeBc = &Private->PxeBc;\r
+ Request = Private->Dhcp6Request;\r
+@@ -899,7 +900,8 @@ PxeBcRequestBootService (
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ \r
+- Discover = AllocateZeroPool (sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET));\r
++ DiscoverLenNeeded = sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET);\r
++ Discover = AllocateZeroPool (DiscoverLenNeeded);\r
+ if (Discover == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+@@ -924,16 +926,34 @@ PxeBcRequestBootService (
+ DHCP6_OPT_SERVER_ID\r
+ );\r
+ if (Option == NULL) {\r
+- return EFI_NOT_FOUND;\r
++ Status = EFI_NOT_FOUND;\r
++ goto ON_ERROR;\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
++ //\r
++ // Check that the minimum and maximum requirements are met\r
++ //\r
++ if ((OpLen < PXEBC_MIN_SIZE_OF_DUID) || (OpLen > PXEBC_MAX_SIZE_OF_DUID)) {\r
++ Status = EFI_INVALID_PARAMETER;\r
++ goto ON_ERROR;\r
++ }\r
++\r
++ //\r
++ // Check that the option length is valid.\r
++ //\r
++ if ((DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN) > DiscoverLenNeeded) {\r
++ Status = EFI_OUT_OF_RESOURCES;\r
++ goto ON_ERROR;\r
++ }\r
++\r
++ CopyMem (DiscoverOpt, Option, OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);\r
++ DiscoverOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);\r
++ DiscoverLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);\r
+ }\r
+ \r
+ while (RequestLen < Request->Length) {\r
+@@ -944,16 +964,24 @@ PxeBcRequestBootService (
+ (OpCode != DHCP6_OPT_SERVER_ID)\r
+ )\r
+ {\r
++ //\r
++ // Check that the option length is valid.\r
++ //\r
++ if (DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN > DiscoverLenNeeded) {\r
++ Status = EFI_OUT_OF_RESOURCES;\r
++ goto ON_ERROR;\r
++ }\r
++\r
+ //\r
+ // Copy all the options except IA option and Server ID\r
+ //\r
+- CopyMem (DiscoverOpt, RequestOpt, OpLen + 4);\r
+- DiscoverOpt += (OpLen + 4);\r
+- DiscoverLen += (OpLen + 4);\r
++ CopyMem (DiscoverOpt, RequestOpt, OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);\r
++ DiscoverOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);\r
++ DiscoverLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);\r
+ }\r
+ \r
+- RequestOpt += (OpLen + 4);\r
+- RequestLen += (OpLen + 4);\r
++ RequestOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);\r
++ RequestLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);\r
+ }\r
+ \r
+ //\r
+@@ -2154,6 +2182,7 @@ PxeBcDhcp6Discover (
+ UINT16 OpLen;\r
+ UINT32 Xid;\r
+ EFI_STATUS Status;\r
++ UINTN DiscoverLenNeeded;\r
+ \r
+ PxeBc = &Private->PxeBc;\r
+ Mode = PxeBc->Mode;\r
+@@ -2169,7 +2198,8 @@ PxeBcDhcp6Discover (
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ \r
+- Discover = AllocateZeroPool (sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET));\r
++ DiscoverLenNeeded = sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET);\r
++ Discover = AllocateZeroPool (DiscoverLenNeeded);\r
+ if (Discover == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+@@ -2185,22 +2215,37 @@ PxeBcDhcp6Discover (
+ DiscoverLen = sizeof (EFI_DHCP6_HEADER);\r
+ RequestLen = DiscoverLen;\r
+ \r
++ //\r
++ // The request packet is generated by the UEFI network stack. In the DHCP4 DORA and DHCP6 SARR sequence,\r
++ // the first (discover in DHCP4 and solicit in DHCP6) and third (request in both DHCP4 and DHCP6) are\r
++ // generated by the DHCP client (the UEFI network stack in this case). By the time this function executes,\r
++ // the DHCP sequence already has been executed once (see UEFI Specification Figures 24.2 and 24.3), with\r
++ // Private->Dhcp6Request being a cached copy of the DHCP6 request packet that UEFI network stack previously\r
++ // generated and sent.\r
++ //\r
++ // Therefore while this code looks like it could overflow, in practice it's not possible.\r
++ //\r
+ while (RequestLen < Request->Length) {\r
+ OpCode = NTOHS (((EFI_DHCP6_PACKET_OPTION *)RequestOpt)->OpCode);\r
+ OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *)RequestOpt)->OpLen);\r
+ if ((OpCode != EFI_DHCP6_IA_TYPE_NA) &&\r
+ (OpCode != EFI_DHCP6_IA_TYPE_TA))\r
+ {\r
++ if (DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN > DiscoverLenNeeded) {\r
++ Status = EFI_OUT_OF_RESOURCES;\r
++ goto ON_ERROR;\r
++ }\r
++\r
+ //\r
+ // Copy all the options except IA option.\r
+ //\r
+- CopyMem (DiscoverOpt, RequestOpt, OpLen + 4);\r
+- DiscoverOpt += (OpLen + 4);\r
+- DiscoverLen += (OpLen + 4);\r
++ CopyMem (DiscoverOpt, RequestOpt, OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);\r
++ DiscoverOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);\r
++ DiscoverLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);\r
+ }\r
+ \r
+- RequestOpt += (OpLen + 4);\r
+- RequestLen += (OpLen + 4);\r
++ RequestOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);\r
++ RequestLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);\r
+ }\r
+ \r
+ Status = PxeBc->UdpWrite (\r
+diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h
+index c86f6d391b..6357d27fae 100644
+--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h
++++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h
+@@ -34,6 +34,23 @@
+ #define PXEBC_ADDR_START_DELIMITER '['\r
+ #define PXEBC_ADDR_END_DELIMITER ']'\r
+ \r
++//\r
++// A DUID consists of a 2-octet type code represented in network byte\r
++// order, followed by a variable number of octets that make up the\r
++// actual identifier. The length of the DUID (not including the type\r
++// code) is at least 1 octet and at most 128 octets.\r
++//\r
++#define PXEBC_MIN_SIZE_OF_DUID (sizeof(UINT16) + 1)\r
++#define PXEBC_MAX_SIZE_OF_DUID (sizeof(UINT16) + 128)\r
++\r
++//\r
++// This define represents the combineds code and length field from\r
++// https://datatracker.ietf.org/doc/html/rfc3315#section-22.1\r
++//\r
++#define PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN \\r
++ (sizeof (((EFI_DHCP6_PACKET_OPTION *)0)->OpCode) + \\r
++ sizeof (((EFI_DHCP6_PACKET_OPTION *)0)->OpLen))\r
++\r
+ #define GET_NEXT_DHCP6_OPTION(Opt) \\r
+ (EFI_DHCP6_PACKET_OPTION *) ((UINT8 *) (Opt) + \\r
+ sizeof (EFI_DHCP6_PACKET_OPTION) + (NTOHS ((Opt)->OpLen)) - 1)\r
+--
+2.40.0
+
--- /dev/null
+From ff2986358f75d8f58ef08a66fe673539c9c48f41 Mon Sep 17 00:00:00 2001
+From: Doug Flick <dougflick@microsoft.com>
+Date: Fri, 26 Jan 2024 05:54:56 +0800
+Subject: [PATCH] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Unit
+ Tests
+
+REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4540
+
+Unit tests to confirm that the bug..
+
+Buffer overflow when handling Server ID option from a DHCPv6 proxy
+Advertise message
+
+..has been patched.
+
+This patch contains unit tests for the following functions:
+PxeBcRequestBootService
+PxeBcDhcp6Discover
+
+Cc: Saloni Kasbekar <saloni.kasbekar@intel.com>
+Cc: Zachary Clark-williams <zachary.clark-williams@intel.com>
+
+Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
+Reviewed-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
+
+CVE: CVE-2023-45235
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/ff2986358f75d8f58ef08a66fe673539c9c48f41]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ .../GoogleTest/PxeBcDhcp6GoogleTest.cpp | 278 +++++++++++++++++-
+ .../GoogleTest/PxeBcDhcp6GoogleTest.h | 18 ++
+ 2 files changed, 294 insertions(+), 2 deletions(-)
+
+diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
+index 8260eeee50..bd423ebadf 100644
+--- a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
+@@ -4,7 +4,9 @@
+ Copyright (c) Microsoft Corporation\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+ **/\r
+-#include <gtest/gtest.h>\r
++#include <Library/GoogleTestLib.h>\r
++#include <GoogleTest/Library/MockUefiLib.h>\r
++#include <GoogleTest/Library/MockUefiRuntimeServicesTableLib.h>\r
+ \r
+ extern "C" {\r
+ #include <Uefi.h>\r
+@@ -19,7 +21,8 @@ extern "C" {
+ // Definitions\r
+ ///////////////////////////////////////////////////////////////////////////////\r
+ \r
+-#define PACKET_SIZE (1500)\r
++#define PACKET_SIZE (1500)\r
++#define REQUEST_OPTION_LENGTH (120)\r
+ \r
+ typedef struct {\r
+ UINT16 OptionCode; // The option code for DHCP6_OPT_SERVER_ID (e.g., 0x03)\r
+@@ -76,6 +79,26 @@ MockConfigure (
+ }\r
+ \r
+ // Needed by PxeBcSupport\r
++EFI_STATUS\r
++PxeBcDns6 (\r
++ IN PXEBC_PRIVATE_DATA *Private,\r
++ IN CHAR16 *HostName,\r
++ OUT EFI_IPv6_ADDRESS *IpAddress\r
++ )\r
++{\r
++ return EFI_SUCCESS;\r
++}\r
++\r
++UINT32\r
++PxeBcBuildDhcp6Options (\r
++ IN PXEBC_PRIVATE_DATA *Private,\r
++ OUT EFI_DHCP6_PACKET_OPTION **OptList,\r
++ IN UINT8 *Buffer\r
++ )\r
++{\r
++ return EFI_SUCCESS;\r
++}\r
++\r
+ EFI_STATUS\r
+ EFIAPI\r
+ QueueDpc (\r
+@@ -159,6 +182,10 @@ TEST_F (PxeBcHandleDhcp6OfferTest, BasicUsageTest) {
+ ASSERT_EQ (PxeBcHandleDhcp6Offer (&(PxeBcHandleDhcp6OfferTest::Private)), EFI_DEVICE_ERROR);\r
+ }\r
+ \r
++///////////////////////////////////////////////////////////////////////////////\r
++// PxeBcCacheDnsServerAddresses Tests\r
++///////////////////////////////////////////////////////////////////////////////\r
++\r
+ class PxeBcCacheDnsServerAddressesTest : public ::testing::Test {\r
+ public:\r
+ PXEBC_PRIVATE_DATA Private = { 0 };\r
+@@ -298,3 +325,250 @@ TEST_F (PxeBcCacheDnsServerAddressesTest, MultipleDnsEntries) {
+ FreePool (Private.DnsServer);\r
+ }\r
+ }\r
++\r
++///////////////////////////////////////////////////////////////////////////////\r
++// PxeBcRequestBootServiceTest Test Cases\r
++///////////////////////////////////////////////////////////////////////////////\r
++\r
++class PxeBcRequestBootServiceTest : public ::testing::Test {\r
++public:\r
++ PXEBC_PRIVATE_DATA Private = { 0 };\r
++ EFI_UDP6_PROTOCOL Udp6Read;\r
++\r
++protected:\r
++ // Add any setup code if needed\r
++ virtual void\r
++ SetUp (\r
++ )\r
++ {\r
++ Private.Dhcp6Request = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE);\r
++\r
++ // Need to setup the EFI_PXE_BASE_CODE_PROTOCOL\r
++ // The function under test really only needs the following:\r
++ // UdpWrite\r
++ // UdpRead\r
++\r
++ Private.PxeBc.UdpWrite = (EFI_PXE_BASE_CODE_UDP_WRITE)MockUdpWrite;\r
++ Private.PxeBc.UdpRead = (EFI_PXE_BASE_CODE_UDP_READ)MockUdpRead;\r
++\r
++ // Need to setup EFI_UDP6_PROTOCOL\r
++ // The function under test really only needs the following:\r
++ // Configure\r
++\r
++ Udp6Read.Configure = (EFI_UDP6_CONFIGURE)MockConfigure;\r
++ Private.Udp6Read = &Udp6Read;\r
++ }\r
++\r
++ // Add any cleanup code if needed\r
++ virtual void\r
++ TearDown (\r
++ )\r
++ {\r
++ if (Private.Dhcp6Request != NULL) {\r
++ FreePool (Private.Dhcp6Request);\r
++ }\r
++\r
++ // Clean up any resources or variables\r
++ }\r
++};\r
++\r
++TEST_F (PxeBcRequestBootServiceTest, ServerDiscoverBasicUsageTest) {\r
++ PxeBcRequestBootServiceTest::Private.OfferBuffer[0].Dhcp6.OfferType = PxeOfferTypeProxyBinl;\r
++\r
++ DHCP6_OPTION_SERVER_ID Server = { 0 };\r
++\r
++ Server.OptionCode = HTONS (DHCP6_OPT_SERVER_ID);\r
++ Server.OptionLen = HTONS (16); // valid length\r
++ UINT8 Index = 0;\r
++\r
++ EFI_DHCP6_PACKET *Packet = (EFI_DHCP6_PACKET *)&Private.OfferBuffer[Index].Dhcp6.Packet.Offer;\r
++\r
++ UINT8 *Cursor = (UINT8 *)(Packet->Dhcp6.Option);\r
++\r
++ CopyMem (Cursor, &Server, sizeof (Server));\r
++ Cursor += sizeof (Server);\r
++\r
++ // Update the packet length\r
++ Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet);\r
++ Packet->Size = PACKET_SIZE;\r
++\r
++ ASSERT_EQ (PxeBcRequestBootService (&(PxeBcRequestBootServiceTest::Private), Index), EFI_SUCCESS);\r
++}\r
++\r
++TEST_F (PxeBcRequestBootServiceTest, AttemptDiscoverOverFlowExpectFailure) {\r
++ PxeBcRequestBootServiceTest::Private.OfferBuffer[0].Dhcp6.OfferType = PxeOfferTypeProxyBinl;\r
++\r
++ DHCP6_OPTION_SERVER_ID Server = { 0 };\r
++\r
++ Server.OptionCode = HTONS (DHCP6_OPT_SERVER_ID);\r
++ Server.OptionLen = HTONS (1500); // This length would overflow without a check\r
++ UINT8 Index = 0;\r
++\r
++ EFI_DHCP6_PACKET *Packet = (EFI_DHCP6_PACKET *)&Private.OfferBuffer[Index].Dhcp6.Packet.Offer;\r
++\r
++ UINT8 *Cursor = (UINT8 *)(Packet->Dhcp6.Option);\r
++\r
++ CopyMem (Cursor, &Server, sizeof (Server));\r
++ Cursor += sizeof (Server);\r
++\r
++ // Update the packet length\r
++ Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet);\r
++ Packet->Size = PACKET_SIZE;\r
++\r
++ // This is going to be stopped by the duid overflow check\r
++ ASSERT_EQ (PxeBcRequestBootService (&(PxeBcRequestBootServiceTest::Private), Index), EFI_INVALID_PARAMETER);\r
++}\r
++\r
++TEST_F (PxeBcRequestBootServiceTest, RequestBasicUsageTest) {\r
++ EFI_DHCP6_PACKET_OPTION RequestOpt = { 0 }; // the data section doesn't really matter\r
++\r
++ RequestOpt.OpCode = HTONS (0x1337);\r
++ RequestOpt.OpLen = 0; // valid length\r
++\r
++ UINT8 Index = 0;\r
++\r
++ EFI_DHCP6_PACKET *Packet = (EFI_DHCP6_PACKET *)&Private.Dhcp6Request[Index];\r
++\r
++ UINT8 *Cursor = (UINT8 *)(Packet->Dhcp6.Option);\r
++\r
++ CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt));\r
++ Cursor += sizeof (RequestOpt);\r
++\r
++ // Update the packet length\r
++ Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet);\r
++ Packet->Size = PACKET_SIZE;\r
++\r
++ ASSERT_EQ (PxeBcRequestBootService (&(PxeBcRequestBootServiceTest::Private), Index), EFI_SUCCESS);\r
++}\r
++\r
++TEST_F (PxeBcRequestBootServiceTest, AttemptRequestOverFlowExpectFailure) {\r
++ EFI_DHCP6_PACKET_OPTION RequestOpt = { 0 }; // the data section doesn't really matter\r
++\r
++ RequestOpt.OpCode = HTONS (0x1337);\r
++ RequestOpt.OpLen = 1500; // this length would overflow without a check\r
++\r
++ UINT8 Index = 0;\r
++\r
++ EFI_DHCP6_PACKET *Packet = (EFI_DHCP6_PACKET *)&Private.Dhcp6Request[Index];\r
++\r
++ UINT8 *Cursor = (UINT8 *)(Packet->Dhcp6.Option);\r
++\r
++ CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt));\r
++ Cursor += sizeof (RequestOpt);\r
++\r
++ // Update the packet length\r
++ Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet);\r
++ Packet->Size = PACKET_SIZE;\r
++\r
++ ASSERT_EQ (PxeBcRequestBootService (&(PxeBcRequestBootServiceTest::Private), Index), EFI_OUT_OF_RESOURCES);\r
++}\r
++\r
++///////////////////////////////////////////////////////////////////////////////\r
++// PxeBcDhcp6Discover Test\r
++///////////////////////////////////////////////////////////////////////////////\r
++\r
++class PxeBcDhcp6DiscoverTest : public ::testing::Test {\r
++public:\r
++ PXEBC_PRIVATE_DATA Private = { 0 };\r
++ EFI_UDP6_PROTOCOL Udp6Read;\r
++\r
++protected:\r
++ MockUefiRuntimeServicesTableLib RtServicesMock;\r
++\r
++ // Add any setup code if needed\r
++ virtual void\r
++ SetUp (\r
++ )\r
++ {\r
++ Private.Dhcp6Request = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE);\r
++\r
++ // Need to setup the EFI_PXE_BASE_CODE_PROTOCOL\r
++ // The function under test really only needs the following:\r
++ // UdpWrite\r
++ // UdpRead\r
++\r
++ Private.PxeBc.UdpWrite = (EFI_PXE_BASE_CODE_UDP_WRITE)MockUdpWrite;\r
++ Private.PxeBc.UdpRead = (EFI_PXE_BASE_CODE_UDP_READ)MockUdpRead;\r
++\r
++ // Need to setup EFI_UDP6_PROTOCOL\r
++ // The function under test really only needs the following:\r
++ // Configure\r
++\r
++ Udp6Read.Configure = (EFI_UDP6_CONFIGURE)MockConfigure;\r
++ Private.Udp6Read = &Udp6Read;\r
++ }\r
++\r
++ // Add any cleanup code if needed\r
++ virtual void\r
++ TearDown (\r
++ )\r
++ {\r
++ if (Private.Dhcp6Request != NULL) {\r
++ FreePool (Private.Dhcp6Request);\r
++ }\r
++\r
++ // Clean up any resources or variables\r
++ }\r
++};\r
++\r
++// Test Description\r
++// This will cause an overflow by an untrusted packet during the option parsing\r
++TEST_F (PxeBcDhcp6DiscoverTest, BasicOverflowTest) {\r
++ EFI_IPv6_ADDRESS DestIp = { 0 };\r
++ EFI_DHCP6_PACKET_OPTION RequestOpt = { 0 }; // the data section doesn't really matter\r
++\r
++ RequestOpt.OpCode = HTONS (0x1337);\r
++ RequestOpt.OpLen = HTONS (0xFFFF); // overflow\r
++\r
++ UINT8 *Cursor = (UINT8 *)(Private.Dhcp6Request->Dhcp6.Option);\r
++\r
++ CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt));\r
++ Cursor += sizeof (RequestOpt);\r
++\r
++ Private.Dhcp6Request->Length = (UINT16)(Cursor - (UINT8 *)Private.Dhcp6Request);\r
++\r
++ EXPECT_CALL (RtServicesMock, gRT_GetTime)\r
++ .WillOnce (::testing::Return (0));\r
++\r
++ ASSERT_EQ (\r
++ PxeBcDhcp6Discover (\r
++ &(PxeBcDhcp6DiscoverTest::Private),\r
++ 0,\r
++ NULL,\r
++ FALSE,\r
++ (EFI_IP_ADDRESS *)&DestIp\r
++ ),\r
++ EFI_OUT_OF_RESOURCES\r
++ );\r
++}\r
++\r
++// Test Description\r
++// This will test that we can handle a packet with a valid option length\r
++TEST_F (PxeBcDhcp6DiscoverTest, BasicUsageTest) {\r
++ EFI_IPv6_ADDRESS DestIp = { 0 };\r
++ EFI_DHCP6_PACKET_OPTION RequestOpt = { 0 }; // the data section doesn't really matter\r
++\r
++ RequestOpt.OpCode = HTONS (0x1337);\r
++ RequestOpt.OpLen = HTONS (0x30);\r
++\r
++ UINT8 *Cursor = (UINT8 *)(Private.Dhcp6Request->Dhcp6.Option);\r
++\r
++ CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt));\r
++ Cursor += sizeof (RequestOpt);\r
++\r
++ Private.Dhcp6Request->Length = (UINT16)(Cursor - (UINT8 *)Private.Dhcp6Request);\r
++\r
++ EXPECT_CALL (RtServicesMock, gRT_GetTime)\r
++ .WillOnce (::testing::Return (0));\r
++\r
++ ASSERT_EQ (\r
++ PxeBcDhcp6Discover (\r
++ &(PxeBcDhcp6DiscoverTest::Private),\r
++ 0,\r
++ NULL,\r
++ FALSE,\r
++ (EFI_IP_ADDRESS *)&DestIp\r
++ ),\r
++ EFI_SUCCESS\r
++ );\r
++}\r
+diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h
+index b17c314791..0d825e4425 100644
+--- a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h
++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h
+@@ -47,4 +47,22 @@ PxeBcCacheDnsServerAddresses (
+ IN PXEBC_DHCP6_PACKET_CACHE *Cache6\r
+ );\r
+ \r
++/**\r
++ Build and send out the request packet for the bootfile, and parse the reply.\r
++\r
++ @param[in] Private The pointer to PxeBc private data.\r
++ @param[in] Index PxeBc option boot item type.\r
++\r
++ @retval EFI_SUCCESS Successfully discovered the boot file.\r
++ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.\r
++ @retval EFI_NOT_FOUND Can't get the PXE reply packet.\r
++ @retval Others Failed to discover the boot file.\r
++\r
++**/\r
++EFI_STATUS\r
++PxeBcRequestBootService (\r
++ IN PXEBC_PRIVATE_DATA *Private,\r
++ IN UINT32 Index\r
++ );\r
++\r
+ #endif // PXE_BC_DHCP6_GOOGLE_TEST_H_\r
+--
+2.40.0
+