diff mbox series

[kirkstone,07/11] ovmf: Fix CVE-2023-45235

Message ID 20240711045541.2155076-7-soumya.sambu@windriver.com
State Changes Requested
Delegated to: Steve Sakoman
Headers show
Series [kirkstone,01/11] ovmf: Fix CVE-2022-36763 | expand

Commit Message

ssambu July 11, 2024, 4:55 a.m. UTC
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 mbox series

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"