[OE-core][kirkstone 07/38] ovmf: Fix CVE-2023-45235

Steve Sakoman
2024-12-04T17:54:35Z

From: Soumya Sambu <soumya.sambu@windriver.com>

EDK2's Network Package is susceptible to a buffer overflow vulnerability
when handling Server ID option from a DHCPv6 proxy Advertise message.
This vulnerability can be exploited by an attacker to gain unauthorized
access and potentially lead to a loss of Confidentiality, Integrity
and/or Availability.

References:
https://nvd.nist.gov/vuln/detail/CVE-2023-45235

Upstream-patches:
https://github.com/tianocore/edk2/commit/fac297724e6cc343430cd0104e55cd7a96d1151e
https://github.com/tianocore/edk2/commit/ff2986358f75d8f58ef08a66fe673539c9c48f41

Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
---
.../ovmf/ovmf/CVE-2023-45235-0001.patch | 243 +++++++++++
.../ovmf/ovmf/CVE-2023-45235-0002.patch | 379 ++++++++++++++++++
meta/recipes-core/ovmf/ovmf_git.bb | 2 +
3 files changed, 624 insertions(+)
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45235-0001.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45235-0002.patch

diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2023-45235-0001.patch b/meta/recipes-core/ovmf/ovmf/CVE-2023-45235-0001.patch
new file mode 100644
index 0000000000..264172f623
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/CVE-2023-45235-0001.patch
@@ -0,0 +1,243 @@
+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;
+ EFI_DHCP6_PACKET *IndexOffer;
+ UINT8 *Option;
++ UINTN DiscoverLenNeeded;
+
+ PxeBc = &Private->PxeBc;
+ Request = Private->Dhcp6Request;
+@@ -899,7 +900,8 @@ PxeBcRequestBootService (
+ return EFI_DEVICE_ERROR;
+ }
+
+- Discover = AllocateZeroPool (sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET));
++ DiscoverLenNeeded = sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET);
++ Discover = AllocateZeroPool (DiscoverLenNeeded);
+ if (Discover == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+@@ -924,16 +926,34 @@ PxeBcRequestBootService (
+ DHCP6_OPT_SERVER_ID
+ );
+ if (Option == NULL) {
+- return EFI_NOT_FOUND;
++ Status = EFI_NOT_FOUND;
++ goto ON_ERROR;
+ }
+
+ //
+ // Add Server ID Option.
+ //
+ OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *)Option)->OpLen);
+- CopyMem (DiscoverOpt, Option, OpLen + 4);
+- DiscoverOpt += (OpLen + 4);
+- DiscoverLen += (OpLen + 4);
++
++ //
++ // 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;
++ }
++
++ //
++ // 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;
++ }
++
++ CopyMem (DiscoverOpt, Option, OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);
++ DiscoverOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);
++ DiscoverLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);
+ }
+
+ while (RequestLen < Request->Length) {
+@@ -944,16 +964,24 @@ PxeBcRequestBootService (
+ (OpCode != DHCP6_OPT_SERVER_ID)
+ )
+ {
++ //
++ // 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;
++ }
++
+ //
+ // Copy all the options except IA option and Server ID
+ //
+- CopyMem (DiscoverOpt, RequestOpt, OpLen + 4);
+- DiscoverOpt += (OpLen + 4);
+- DiscoverLen += (OpLen + 4);
++ CopyMem (DiscoverOpt, RequestOpt, OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);
++ DiscoverOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);
++ DiscoverLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);
+ }
+
+- RequestOpt += (OpLen + 4);
+- RequestLen += (OpLen + 4);
++ RequestOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);
++ RequestLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);
+ }
+
+ //
+@@ -2154,6 +2182,7 @@ PxeBcDhcp6Discover (
+ UINT16 OpLen;
+ UINT32 Xid;
+ EFI_STATUS Status;
++ UINTN DiscoverLenNeeded;
+
+ PxeBc = &Private->PxeBc;
+ Mode = PxeBc->Mode;
+@@ -2169,7 +2198,8 @@ PxeBcDhcp6Discover (
+ return EFI_DEVICE_ERROR;
+ }
+
+- Discover = AllocateZeroPool (sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET));
++ DiscoverLenNeeded = sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET);
++ Discover = AllocateZeroPool (DiscoverLenNeeded);
+ if (Discover == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+@@ -2185,22 +2215,37 @@ PxeBcDhcp6Discover (
+ DiscoverLen = sizeof (EFI_DHCP6_HEADER);
+ RequestLen = DiscoverLen;
+
++ //
++ // The request packet is generated by the UEFI network stack. In the DHCP4 DORA and DHCP6 SARR sequence,
++ // the first (discover in DHCP4 and solicit in DHCP6) and third (request in both DHCP4 and DHCP6) are
++ // generated by the DHCP client (the UEFI network stack in this case). By the time this function executes,
++ // the DHCP sequence already has been executed once (see UEFI Specification Figures 24.2 and 24.3), with
++ // Private->Dhcp6Request being a cached copy of the DHCP6 request packet that UEFI network stack previously
++ // generated and sent.
++ //
++ // Therefore while this code looks like it could overflow, in practice it's not possible.
++ //
+ while (RequestLen < Request->Length) {
+ OpCode = NTOHS (((EFI_DHCP6_PACKET_OPTION *)RequestOpt)->OpCode);
+ OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *)RequestOpt)->OpLen);
+ if ((OpCode != EFI_DHCP6_IA_TYPE_NA) &&
+ (OpCode != EFI_DHCP6_IA_TYPE_TA))
+ {
++ if (DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN > DiscoverLenNeeded) {
++ Status = EFI_OUT_OF_RESOURCES;
++ goto ON_ERROR;
++ }
++
+ //
+ // Copy all the options except IA option.
+ //
+- CopyMem (DiscoverOpt, RequestOpt, OpLen + 4);
+- DiscoverOpt += (OpLen + 4);
+- DiscoverLen += (OpLen + 4);
++ CopyMem (DiscoverOpt, RequestOpt, OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);
++ DiscoverOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);
++ DiscoverLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);
+ }
+
+- RequestOpt += (OpLen + 4);
+- RequestLen += (OpLen + 4);
++ RequestOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);
++ RequestLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);
+ }
+
+ Status = PxeBc->UdpWrite (
+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 '['
+ #define PXEBC_ADDR_END_DELIMITER ']'
+
++//
++// A DUID consists of a 2-octet type code represented in network byte
++// order, followed by a variable number of octets that make up the
++// actual identifier. The length of the DUID (not including the type
++// code) is at least 1 octet and at most 128 octets.
++//
++#define PXEBC_MIN_SIZE_OF_DUID (sizeof(UINT16) + 1)
++#define PXEBC_MAX_SIZE_OF_DUID (sizeof(UINT16) + 128)
++
++//
++// This define represents the combineds code and length field from
++// https://datatracker.ietf.org/doc/html/rfc3315#section-22.1
++//
++#define PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN \
++ (sizeof (((EFI_DHCP6_PACKET_OPTION *)0)->OpCode) + \
++ sizeof (((EFI_DHCP6_PACKET_OPTION *)0)->OpLen))
++
+ #define GET_NEXT_DHCP6_OPTION(Opt) \
+ (EFI_DHCP6_PACKET_OPTION *) ((UINT8 *) (Opt) + \
+ sizeof (EFI_DHCP6_PACKET_OPTION) + (NTOHS ((Opt)->OpLen)) - 1)
+--
+2.40.0
+
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2023-45235-0002.patch b/meta/recipes-core/ovmf/ovmf/CVE-2023-45235-0002.patch
new file mode 100644
index 0000000000..0e814a0212
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/CVE-2023-45235-0002.patch
@@ -0,0 +1,379 @@
+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
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+ **/
+-#include <gtest/gtest.h>
++#include <Library/GoogleTestLib.h>
++#include <GoogleTest/Library/MockUefiLib.h>
++#include <GoogleTest/Library/MockUefiRuntimeServicesTableLib.h>
+
+ extern "C" {
+ #include <Uefi.h>
+@@ -19,7 +21,8 @@ extern "C" {
+ // Definitions
+ ///////////////////////////////////////////////////////////////////////////////
+
+-#define PACKET_SIZE (1500)
++#define PACKET_SIZE (1500)
++#define REQUEST_OPTION_LENGTH (120)
+
+ typedef struct {
+ UINT16 OptionCode; // The option code for DHCP6_OPT_SERVER_ID (e.g., 0x03)
+@@ -76,6 +79,26 @@ MockConfigure (
+ }
+
+ // Needed by PxeBcSupport
++EFI_STATUS
++PxeBcDns6 (
++ IN PXEBC_PRIVATE_DATA *Private,
++ IN CHAR16 *HostName,
++ OUT EFI_IPv6_ADDRESS *IpAddress
++ )
++{
++ return EFI_SUCCESS;
++}
++
++UINT32
++PxeBcBuildDhcp6Options (
++ IN PXEBC_PRIVATE_DATA *Private,
++ OUT EFI_DHCP6_PACKET_OPTION **OptList,
++ IN UINT8 *Buffer
++ )
++{
++ return EFI_SUCCESS;
++}
++
+ EFI_STATUS
+ EFIAPI
+ QueueDpc (
+@@ -159,6 +182,10 @@ TEST_F (PxeBcHandleDhcp6OfferTest, BasicUsageTest) {
+ ASSERT_EQ (PxeBcHandleDhcp6Offer (&(PxeBcHandleDhcp6OfferTest::Private)), EFI_DEVICE_ERROR);
+ }
+
++///////////////////////////////////////////////////////////////////////////////
++// PxeBcCacheDnsServerAddresses Tests
++///////////////////////////////////////////////////////////////////////////////
++
+ class PxeBcCacheDnsServerAddressesTest : public ::testing::Test {
+ public:
+ PXEBC_PRIVATE_DATA Private = { 0 };
+@@ -298,3 +325,250 @@ TEST_F (PxeBcCacheDnsServerAddressesTest, MultipleDnsEntries) {
+ FreePool (Private.DnsServer);
+ }
+ }
++
++///////////////////////////////////////////////////////////////////////////////
++// PxeBcRequestBootServiceTest Test Cases
++///////////////////////////////////////////////////////////////////////////////
++
++class PxeBcRequestBootServiceTest : public ::testing::Test {
++public:
++ PXEBC_PRIVATE_DATA Private = { 0 };
++ EFI_UDP6_PROTOCOL Udp6Read;
++
++protected:
++ // Add any setup code if needed
++ virtual void
++ SetUp (
++ )
++ {
++ Private.Dhcp6Request = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE);
++
++ // Need to setup the EFI_PXE_BASE_CODE_PROTOCOL
++ // The function under test really only needs the following:
++ // UdpWrite
++ // UdpRead
++
++ Private.PxeBc.UdpWrite = (EFI_PXE_BASE_CODE_UDP_WRITE)MockUdpWrite;
++ Private.PxeBc.UdpRead = (EFI_PXE_BASE_CODE_UDP_READ)MockUdpRead;
++
++ // Need to setup EFI_UDP6_PROTOCOL
++ // The function under test really only needs the following:
++ // Configure
++
++ Udp6Read.Configure = (EFI_UDP6_CONFIGURE)MockConfigure;
++ Private.Udp6Read = &Udp6Read;
++ }
++
++ // Add any cleanup code if needed
++ virtual void
++ TearDown (
++ )
++ {
++ if (Private.Dhcp6Request != NULL) {
++ FreePool (Private.Dhcp6Request);
++ }
++
++ // Clean up any resources or variables
++ }
++};
++
++TEST_F (PxeBcRequestBootServiceTest, ServerDiscoverBasicUsageTest) {
++ PxeBcRequestBootServiceTest::Private.OfferBuffer[0].Dhcp6.OfferType = PxeOfferTypeProxyBinl;
++
++ DHCP6_OPTION_SERVER_ID Server = { 0 };
++
++ Server.OptionCode = HTONS (DHCP6_OPT_SERVER_ID);
++ Server.OptionLen = HTONS (16); // valid length
++ UINT8 Index = 0;
++
++ EFI_DHCP6_PACKET *Packet = (EFI_DHCP6_PACKET *)&Private.OfferBuffer[Index].Dhcp6.Packet.Offer;
++
++ UINT8 *Cursor = (UINT8 *)(Packet->Dhcp6.Option);
++
++ CopyMem (Cursor, &Server, sizeof (Server));
++ Cursor += sizeof (Server);
++
++ // Update the packet length
++ Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet);
++ Packet->Size = PACKET_SIZE;
++
++ ASSERT_EQ (PxeBcRequestBootService (&(PxeBcRequestBootServiceTest::Private), Index), EFI_SUCCESS);
++}
++
++TEST_F (PxeBcRequestBootServiceTest, AttemptDiscoverOverFlowExpectFailure) {
++ PxeBcRequestBootServiceTest::Private.OfferBuffer[0].Dhcp6.OfferType = PxeOfferTypeProxyBinl;
++
++ DHCP6_OPTION_SERVER_ID Server = { 0 };
++
++ Server.OptionCode = HTONS (DHCP6_OPT_SERVER_ID);
++ Server.OptionLen = HTONS (1500); // This length would overflow without a check
++ UINT8 Index = 0;
++
++ EFI_DHCP6_PACKET *Packet = (EFI_DHCP6_PACKET *)&Private.OfferBuffer[Index].Dhcp6.Packet.Offer;
++
++ UINT8 *Cursor = (UINT8 *)(Packet->Dhcp6.Option);
++
++ CopyMem (Cursor, &Server, sizeof (Server));
++ Cursor += sizeof (Server);
++
++ // Update the packet length
++ Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet);
++ Packet->Size = PACKET_SIZE;
++
++ // This is going to be stopped by the duid overflow check
++ ASSERT_EQ (PxeBcRequestBootService (&(PxeBcRequestBootServiceTest::Private), Index), EFI_INVALID_PARAMETER);
++}
++
++TEST_F (PxeBcRequestBootServiceTest, RequestBasicUsageTest) {
++ EFI_DHCP6_PACKET_OPTION RequestOpt = { 0 }; // the data section doesn't really matter
++
++ RequestOpt.OpCode = HTONS (0x1337);
++ RequestOpt.OpLen = 0; // valid length
++
++ UINT8 Index = 0;
++
++ EFI_DHCP6_PACKET *Packet = (EFI_DHCP6_PACKET *)&Private.Dhcp6Request[Index];
++
++ UINT8 *Cursor = (UINT8 *)(Packet->Dhcp6.Option);
++
++ CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt));
++ Cursor += sizeof (RequestOpt);
++
++ // Update the packet length
++ Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet);
++ Packet->Size = PACKET_SIZE;
++
++ ASSERT_EQ (PxeBcRequestBootService (&(PxeBcRequestBootServiceTest::Private), Index), EFI_SUCCESS);
++}
++
++TEST_F (PxeBcRequestBootServiceTest, AttemptRequestOverFlowExpectFailure) {
++ EFI_DHCP6_PACKET_OPTION RequestOpt = { 0 }; // the data section doesn't really matter
++
++ RequestOpt.OpCode = HTONS (0x1337);
++ RequestOpt.OpLen = 1500; // this length would overflow without a check
++
++ UINT8 Index = 0;
++
++ EFI_DHCP6_PACKET *Packet = (EFI_DHCP6_PACKET *)&Private.Dhcp6Request[Index];
++
++ UINT8 *Cursor = (UINT8 *)(Packet->Dhcp6.Option);
++
++ CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt));
++ Cursor += sizeof (RequestOpt);
++
++ // Update the packet length
++ Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet);
++ Packet->Size = PACKET_SIZE;
++
++ ASSERT_EQ (PxeBcRequestBootService (&(PxeBcRequestBootServiceTest::Private), Index), EFI_OUT_OF_RESOURCES);
++}
++
++///////////////////////////////////////////////////////////////////////////////
++// PxeBcDhcp6Discover Test
++///////////////////////////////////////////////////////////////////////////////
++
++class PxeBcDhcp6DiscoverTest : public ::testing::Test {
++public:
++ PXEBC_PRIVATE_DATA Private = { 0 };
++ EFI_UDP6_PROTOCOL Udp6Read;
++
++protected:
++ MockUefiRuntimeServicesTableLib RtServicesMock;
++
++ // Add any setup code if needed
++ virtual void
++ SetUp (
++ )
++ {
++ Private.Dhcp6Request = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE);
++
++ // Need to setup the EFI_PXE_BASE_CODE_PROTOCOL
++ // The function under test really only needs the following:
++ // UdpWrite
++ // UdpRead
++
++ Private.PxeBc.UdpWrite = (EFI_PXE_BASE_CODE_UDP_WRITE)MockUdpWrite;
++ Private.PxeBc.UdpRead = (EFI_PXE_BASE_CODE_UDP_READ)MockUdpRead;
++
++ // Need to setup EFI_UDP6_PROTOCOL
++ // The function under test really only needs the following:
++ // Configure
++
++ Udp6Read.Configure = (EFI_UDP6_CONFIGURE)MockConfigure;
++ Private.Udp6Read = &Udp6Read;
++ }
++
++ // Add any cleanup code if needed
++ virtual void
++ TearDown (
++ )
++ {
++ if (Private.Dhcp6Request != NULL) {
++ FreePool (Private.Dhcp6Request);
++ }
++
++ // Clean up any resources or variables
++ }
++};
++
++// Test Description
++// This will cause an overflow by an untrusted packet during the option parsing
++TEST_F (PxeBcDhcp6DiscoverTest, BasicOverflowTest) {
++ EFI_IPv6_ADDRESS DestIp = { 0 };
++ EFI_DHCP6_PACKET_OPTION RequestOpt = { 0 }; // the data section doesn't really matter
++
++ RequestOpt.OpCode = HTONS (0x1337);
++ RequestOpt.OpLen = HTONS (0xFFFF); // overflow
++
++ UINT8 *Cursor = (UINT8 *)(Private.Dhcp6Request->Dhcp6.Option);
++
++ CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt));
++ Cursor += sizeof (RequestOpt);
++
++ Private.Dhcp6Request->Length = (UINT16)(Cursor - (UINT8 *)Private.Dhcp6Request);
++
++ EXPECT_CALL (RtServicesMock, gRT_GetTime)
++ .WillOnce (::testing::Return (0));
++
++ ASSERT_EQ (
++ PxeBcDhcp6Discover (
++ &(PxeBcDhcp6DiscoverTest::Private),
++ 0,
++ NULL,
++ FALSE,
++ (EFI_IP_ADDRESS *)&DestIp
++ ),
++ EFI_OUT_OF_RESOURCES
++ );
++}
++
++// Test Description
++// This will test that we can handle a packet with a valid option length
++TEST_F (PxeBcDhcp6DiscoverTest, BasicUsageTest) {
++ EFI_IPv6_ADDRESS DestIp = { 0 };
++ EFI_DHCP6_PACKET_OPTION RequestOpt = { 0 }; // the data section doesn't really matter
++
++ RequestOpt.OpCode = HTONS (0x1337);
++ RequestOpt.OpLen = HTONS (0x30);
++
++ UINT8 *Cursor = (UINT8 *)(Private.Dhcp6Request->Dhcp6.Option);
++
++ CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt));
++ Cursor += sizeof (RequestOpt);
++
++ Private.Dhcp6Request->Length = (UINT16)(Cursor - (UINT8 *)Private.Dhcp6Request);
++
++ EXPECT_CALL (RtServicesMock, gRT_GetTime)
++ .WillOnce (::testing::Return (0));
++
++ ASSERT_EQ (
++ PxeBcDhcp6Discover (
++ &(PxeBcDhcp6DiscoverTest::Private),
++ 0,
++ NULL,
++ FALSE,
++ (EFI_IP_ADDRESS *)&DestIp
++ ),
++ EFI_SUCCESS
++ );
++}
+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
+ );
+
++/**
++ Build and send out the request packet for the bootfile, and parse the reply.
++
++ @param[in] Private The pointer to PxeBc private data.
++ @param[in] Index PxeBc option boot item type.
++
++ @retval EFI_SUCCESS Successfully discovered the boot file.
++ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
++ @retval EFI_NOT_FOUND Can't get the PXE reply packet.
++ @retval Others Failed to discover the boot file.
++
++**/
++EFI_STATUS
++PxeBcRequestBootService (
++ IN PXEBC_PRIVATE_DATA *Private,
++ IN UINT32 Index
++ );
++
+ #endif // PXE_BC_DHCP6_GOOGLE_TEST_H_
+--
+2.40.0
+
diff --git a/meta/recipes-core/ovmf/ovmf_git.bb b/meta/recipes-core/ovmf/ovmf_git.bb
index ac6a0a40e7..ceebb53438 100644
--- a/meta/recipes-core/ovmf/ovmf_git.bb
+++ b/meta/recipes-core/ovmf/ovmf_git.bb
@@ -41,6 +41,8 @@ SRC_URI = "gitsm://github.com/tianocore/edk2.git;branch=master;protocol=https \
file://CVE-2023-45232-CVE-2023-45233-0002.patch \
file://CVE-2023-45234-0001.patch \
file://CVE-2023-45234-0002.patch \
+ file://CVE-2023-45235-0001.patch \
+ file://CVE-2023-45235-0002.patch \
"

PV = "edk2-stable202202"
--
2.34.1