new file mode 100644
@@ -0,0 +1,360 @@
+From 4df0229ef992d4f2721a8508787ebf9dc81fbd6e Mon Sep 17 00:00:00 2001
+From: Doug Flick <dougflick@microsoft.com>
+Date: Fri, 26 Jan 2024 05:54:50 +0800
+Subject: [PATCH] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Patch
+
+REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4537
+REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4538
+
+Bug Details:
+PixieFail Bug #4
+CVE-2023-45232
+CVSS 7.5 : CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
+CWE-835 Loop with Unreachable Exit Condition ('Infinite Loop')
+
+Infinite loop when parsing unknown options in the Destination Options
+header
+
+PixieFail Bug #5
+CVE-2023-45233
+CVSS 7.5 : CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
+CWE-835 Loop with Unreachable Exit Condition ('Infinite Loop')
+
+Infinite loop when parsing a PadN option in the Destination Options
+header
+
+Change Overview:
+
+Most importantly this change corrects the following incorrect math
+and cleans up the code.
+
+> // It is a PadN option
+> //
+> - Offset = (UINT8)(Offset + *(Option + Offset + 1) + 2);
+> + OptDataLen = ((EFI_IP6_OPTION *)(Option + Offset))->Length;
+> + Offset = IP6_NEXT_OPTION_OFFSET (Offset, OptDataLen);
+
+> case Ip6OptionSkip:
+> - Offset = (UINT8)(Offset + *(Option + Offset + 1));
+> OptDataLen = ((EFI_IP6_OPTION *)(Option + Offset))->Length;
+> Offset = IP6_NEXT_OPTION_OFFSET (Offset, OptDataLen);
+
+Additionally, this change also corrects incorrect math where the calling
+function was calculating the HDR EXT optionLen as a uint8 instead of a
+uint16
+
+> - OptionLen = (UINT8)((*Option + 1) * 8 - 2);
+> + OptionLen = IP6_HDR_EXT_LEN (*Option) -
+IP6_COMBINED_SIZE_OF_NEXT_HDR_AND_LEN;
+
+Additionally this check adds additional logic to santize the incoming
+data
+
+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-45232, CVE-2023-45233
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/4df0229ef992d4f2721a8508787ebf9dc81fbd6e]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ NetworkPkg/Ip6Dxe/Ip6Nd.h | 35 ++++++++++++++++
+ NetworkPkg/Ip6Dxe/Ip6Option.c | 76 ++++++++++++++++++++++++++++++-----
+ NetworkPkg/Ip6Dxe/Ip6Option.h | 71 ++++++++++++++++++++++++++++++++
+ 3 files changed, 171 insertions(+), 11 deletions(-)
+
+diff --git a/NetworkPkg/Ip6Dxe/Ip6Nd.h b/NetworkPkg/Ip6Dxe/Ip6Nd.h
+index 860934a167..bf64e9114e 100644
+--- a/NetworkPkg/Ip6Dxe/Ip6Nd.h
++++ b/NetworkPkg/Ip6Dxe/Ip6Nd.h
+@@ -56,13 +56,48 @@ VOID
+ VOID *Context
+ );
+
++//
++// Per RFC8200 Section 4.2
++//
++// Two of the currently-defined extension headers -- the Hop-by-Hop
++// Options header and the Destination Options header -- carry a variable
++// number of type-length-value (TLV) encoded "options", of the following
++// format:
++//
++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- - - - - - - - -
++// | Option Type | Opt Data Len | Option Data
++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- - - - - - - - -
++//
++// Option Type 8-bit identifier of the type of option.
++//
++// Opt Data Len 8-bit unsigned integer. Length of the Option
++// Data field of this option, in octets.
++//
++// Option Data Variable-length field. Option-Type-specific
++// data.
++//
+ typedef struct _IP6_OPTION_HEADER {
++ ///
++ /// identifier of the type of option.
++ ///
+ UINT8 Type;
++ ///
++ /// Length of the Option Data field of this option, in octets.
++ ///
+ UINT8 Length;
++ ///
++ /// Option-Type-specific data.
++ ///
+ } IP6_OPTION_HEADER;
+
+ STATIC_ASSERT (sizeof (IP6_OPTION_HEADER) == 2, "IP6_OPTION_HEADER is expected to be exactly 2 bytes long.");
+
++#define IP6_NEXT_OPTION_OFFSET(offset, length) (offset + sizeof(IP6_OPTION_HEADER) + length)
++STATIC_ASSERT (
++ IP6_NEXT_OPTION_OFFSET (0, 0) == 2,
++ "The next option is minimally the combined size of the option tag and length"
++ );
++
+ typedef struct _IP6_ETHE_ADDR_OPTION {
+ UINT8 Type;
+ UINT8 Length;
+diff --git a/NetworkPkg/Ip6Dxe/Ip6Option.c b/NetworkPkg/Ip6Dxe/Ip6Option.c
+index 8718d5d875..fd97ce116f 100644
+--- a/NetworkPkg/Ip6Dxe/Ip6Option.c
++++ b/NetworkPkg/Ip6Dxe/Ip6Option.c
+@@ -17,7 +17,8 @@
+ @param[in] IpSb The IP6 service data.
+ @param[in] Packet The to be validated packet.
+ @param[in] Option The first byte of the option.
+- @param[in] OptionLen The length of the whole option.
++ @param[in] OptionLen The length of all options, expressed in byte length of octets.
++ Maximum length is 2046 bytes or ((n + 1) * 8) - 2 where n is 255.
+ @param[in] Pointer Identifies the octet offset within
+ the invoking packet where the error was detected.
+
+@@ -31,12 +32,33 @@ Ip6IsOptionValid (
+ IN IP6_SERVICE *IpSb,
+ IN NET_BUF *Packet,
+ IN UINT8 *Option,
+- IN UINT8 OptionLen,
++ IN UINT16 OptionLen,
+ IN UINT32 Pointer
+ )
+ {
+- UINT8 Offset;
+- UINT8 OptionType;
++ UINT16 Offset;
++ UINT8 OptionType;
++ UINT8 OptDataLen;
++
++ if (Option == NULL) {
++ ASSERT (Option != NULL);
++ return FALSE;
++ }
++
++ if ((OptionLen <= 0) || (OptionLen > IP6_MAX_EXT_DATA_LENGTH)) {
++ ASSERT (OptionLen > 0 && OptionLen <= IP6_MAX_EXT_DATA_LENGTH);
++ return FALSE;
++ }
++
++ if (Packet == NULL) {
++ ASSERT (Packet != NULL);
++ return FALSE;
++ }
++
++ if (IpSb == NULL) {
++ ASSERT (IpSb != NULL);
++ return FALSE;
++ }
+
+ Offset = 0;
+
+@@ -54,7 +76,8 @@ Ip6IsOptionValid (
+ //
+ // It is a PadN option
+ //
+- Offset = (UINT8)(Offset + *(Option + Offset + 1) + 2);
++ OptDataLen = ((IP6_OPTION_HEADER *)(Option + Offset))->Length;
++ Offset = IP6_NEXT_OPTION_OFFSET (Offset, OptDataLen);
+ break;
+ case Ip6OptionRouterAlert:
+ //
+@@ -69,7 +92,8 @@ Ip6IsOptionValid (
+ //
+ switch (OptionType & Ip6OptionMask) {
+ case Ip6OptionSkip:
+- Offset = (UINT8)(Offset + *(Option + Offset + 1));
++ OptDataLen = ((IP6_OPTION_HEADER *)(Option + Offset))->Length;
++ Offset = IP6_NEXT_OPTION_OFFSET (Offset, OptDataLen);
+ break;
+ case Ip6OptionDiscard:
+ return FALSE;
+@@ -308,7 +332,7 @@ Ip6IsExtsValid (
+ UINT32 Pointer;
+ UINT32 Offset;
+ UINT8 *Option;
+- UINT8 OptionLen;
++ UINT16 OptionLen;
+ BOOLEAN Flag;
+ UINT8 CountD;
+ UINT8 CountA;
+@@ -385,6 +409,36 @@ Ip6IsExtsValid (
+ // Fall through
+ //
+ case IP6_DESTINATION:
++ //
++ // See https://www.rfc-editor.org/rfc/rfc2460#section-4.2 page 23
++ //
++ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ // | Next Header | Hdr Ext Len | |
++ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
++ // | |
++ // . .
++ // . Options .
++ // . .
++ // | |
++ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ //
++ //
++ // Next Header 8-bit selector. Identifies the type of header
++ // immediately following the Destination Options
++ // header. Uses the same values as the IPv4
++ // Protocol field [RFC-1700 et seq.].
++ //
++ // Hdr Ext Len 8-bit unsigned integer. Length of the
++ // Destination Options header in 8-octet units, not
++ // including the first 8 octets.
++ //
++ // Options Variable-length field, of length such that the
++ // complete Destination Options header is an
++ // integer multiple of 8 octets long. Contains one
++ // or more TLV-encoded options, as described in
++ // section 4.2.
++ //
++
+ if (*NextHeader == IP6_DESTINATION) {
+ CountD++;
+ }
+@@ -398,7 +452,7 @@ Ip6IsExtsValid (
+
+ Offset++;
+ Option = ExtHdrs + Offset;
+- OptionLen = (UINT8)((*Option + 1) * 8 - 2);
++ OptionLen = IP6_HDR_EXT_LEN (*Option) - sizeof (IP6_EXT_HDR);
+ Option++;
+ Offset++;
+
+@@ -430,7 +484,7 @@ Ip6IsExtsValid (
+ //
+ // Ignore the routing header and proceed to process the next header.
+ //
+- Offset = Offset + (RoutingHead->HeaderLen + 1) * 8;
++ Offset = Offset + IP6_HDR_EXT_LEN (RoutingHead->HeaderLen);
+
+ if (UnFragmentLen != NULL) {
+ *UnFragmentLen = Offset;
+@@ -441,7 +495,7 @@ Ip6IsExtsValid (
+ // to the packet's source address, pointing to the unrecognized routing
+ // type.
+ //
+- Pointer = Offset + 2 + sizeof (EFI_IP6_HEADER);
++ Pointer = Offset + sizeof (IP6_EXT_HDR) + sizeof (EFI_IP6_HEADER);
+ if ((IpSb != NULL) && (Packet != NULL) &&
+ !IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress))
+ {
+@@ -527,7 +581,7 @@ Ip6IsExtsValid (
+ //
+ // RFC2402, Payload length is specified in 32-bit words, minus "2".
+ //
+- OptionLen = (UINT8)((*Option + 2) * 4);
++ OptionLen = ((UINT16)(*Option + 2) * 4);
+ Offset = Offset + OptionLen;
+ break;
+
+diff --git a/NetworkPkg/Ip6Dxe/Ip6Option.h b/NetworkPkg/Ip6Dxe/Ip6Option.h
+index bd8e223c8a..fb07c28f5a 100644
+--- a/NetworkPkg/Ip6Dxe/Ip6Option.h
++++ b/NetworkPkg/Ip6Dxe/Ip6Option.h
+@@ -12,6 +12,77 @@
+
+ #define IP6_FRAGMENT_OFFSET_MASK (~0x3)
+
++//
++// For more information see RFC 8200, Section 4.3, 4.4, and 4.6
++//
++// This example format is from section 4.6
++// This does not apply to fragment headers
++//
++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++// | Next Header | Hdr Ext Len | |
++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
++// | |
++// . .
++// . Header-Specific Data .
++// . .
++// | |
++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++//
++// Next Header 8-bit selector. Identifies the type of
++// header immediately following the extension
++// header. Uses the same values as the IPv4
++// Protocol field [IANA-PN].
++//
++// Hdr Ext Len 8-bit unsigned integer. Length of the
++// Destination Options header in 8-octet units,
++// not including the first 8 octets.
++
++//
++// These defines apply to the following:
++// 1. Hop by Hop
++// 2. Routing
++// 3. Destination
++//
++typedef struct _IP6_EXT_HDR {
++ ///
++ /// The Next Header field identifies the type of header immediately
++ ///
++ UINT8 NextHeader;
++ ///
++ /// The Hdr Ext Len field specifies the length of the Hop-by-Hop Options
++ ///
++ UINT8 HdrExtLen;
++ ///
++ /// Header-Specific Data
++ ///
++} IP6_EXT_HDR;
++
++STATIC_ASSERT (
++ sizeof (IP6_EXT_HDR) == 2,
++ "The combined size of Next Header and Len is two 8 bit fields"
++ );
++
++//
++// IPv6 extension headers contain an 8-bit length field which describes the size of
++// the header. However, the length field only includes the size of the extension
++// header options, not the size of the first 8 bytes of the header. Therefore, in
++// order to calculate the full size of the extension header, we add 1 (to account
++// for the first 8 bytes omitted by the length field reporting) and then multiply
++// by 8 (since the size is represented in 8-byte units).
++//
++// a is the length field of the extension header (UINT8)
++// The result may be up to 2046 octets (UINT16)
++//
++#define IP6_HDR_EXT_LEN(a) (((UINT16)((UINT8)(a)) + 1) * 8)
++
++// This is the maxmimum length permissible by a extension header
++// Length is UINT8 of 8 octets not including the first 8 octets
++#define IP6_MAX_EXT_DATA_LENGTH (IP6_HDR_EXT_LEN (MAX_UINT8) - sizeof(IP6_EXT_HDR))
++STATIC_ASSERT (
++ IP6_MAX_EXT_DATA_LENGTH == 2046,
++ "Maximum data length is ((MAX_UINT8 + 1) * 8) - 2"
++ );
++
+ typedef struct _IP6_FRAGMENT_HEADER {
+ UINT8 NextHeader;
+ UINT8 Reserved;
+--
+2.40.0
+
new file mode 100644
@@ -0,0 +1,417 @@
+From c9c87f08dd6ace36fa843424522c3558a8374cac Mon Sep 17 00:00:00 2001
+From: Doug Flick <dougflick@microsoft.com>
+Date: Fri, 26 Jan 2024 05:54:51 +0800
+Subject: [PATCH] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Unit Tests
+
+REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4537
+REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4538
+
+Unit tests to confirm that..
+
+Infinite loop when parsing unknown options in the Destination Options
+header
+
+and
+
+Infinite loop when parsing a PadN option in the Destination Options
+header
+
+... have been patched
+
+This patch tests the following functions:
+Ip6IsOptionValid
+
+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-45232, CVE-2023-45233
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/c9c87f08dd6ace36fa843424522c3558a8374cac]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ .../Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf | 10 +-
+ .../Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp | 278 ++++++++++++++++++
+ .../Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h | 40 +++
+ 3 files changed, 324 insertions(+), 4 deletions(-)
+ create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h
+
+diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
+index 6e4de0745f..ba29dbabad 100644
+--- a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
++++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
+@@ -1,13 +1,13 @@
+ ## @file
+-# Unit test suite for the Ip6Dxe using Google Test
++# Unit test suite for the Ip6DxeGoogleTest using Google Test
+ #
+ # Copyright (c) Microsoft Corporation.<BR>
+ # SPDX-License-Identifier: BSD-2-Clause-Patent
+ ##
+ [Defines]
+ INF_VERSION = 0x00010017
+- BASE_NAME = Ip6DxeUnitTest
+- FILE_GUID = 4F05D17D-D3E7-4AAE-820C-576D46D2D34A
++ BASE_NAME = Ip6DxeGoogleTest
++ FILE_GUID = AE39981C-B7FE-41A8-A9C2-F41910477CA3
+ VERSION_STRING = 1.0
+ MODULE_TYPE = HOST_APPLICATION
+ #
+@@ -16,9 +16,11 @@
+ # VALID_ARCHITECTURES = IA32 X64 AARCH64
+ #
+ [Sources]
++ ../Ip6Option.c
++ Ip6OptionGoogleTest.h
+ Ip6DxeGoogleTest.cpp
+ Ip6OptionGoogleTest.cpp
+- ../Ip6Option.c
++ Ip6OptionGoogleTest.h
+
+ [Packages]
+ MdePkg/MdePkg.dec
+diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
+index f2cd90e1a9..29f8a4a96e 100644
+--- a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
++++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
+@@ -12,6 +12,7 @@ extern "C" {
+ #include <Library/DebugLib.h>
+ #include "../Ip6Impl.h"
+ #include "../Ip6Option.h"
++ #include "Ip6OptionGoogleTest.h"
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+@@ -127,3 +128,280 @@ TEST_F (Ip6OptionValidationTest, InvalidPrefixInfoOptionLengthShouldReturnFalse)
+
+ EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen));
+ }
++
++////////////////////////////////////////////////////////////////////////
++// Ip6IsOptionValid Tests
++////////////////////////////////////////////////////////////////////////
++
++// Define a fixture for your tests if needed
++class Ip6IsOptionValidTest : public ::testing::Test {
++protected:
++ // Add any setup code if needed
++ virtual void
++ SetUp (
++ )
++ {
++ // Initialize any resources or variables
++ }
++
++ // Add any cleanup code if needed
++ virtual void
++ TearDown (
++ )
++ {
++ // Clean up any resources or variables
++ }
++};
++
++// Test Description
++// Verify that a NULL option is Invalid
++TEST_F (Ip6IsOptionValidTest, NullOptionShouldReturnTrue) {
++ NET_BUF Packet = { 0 };
++ // we need to define enough of the packet to make the function work
++ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
++ IP6_SERVICE *IpSb = NULL;
++
++ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++ EFI_IP6_HEADER Ip6Header = { 0 };
++
++ Ip6Header.SourceAddress = SourceAddress;
++ Ip6Header.DestinationAddress = DestinationAddress;
++ Packet.Ip.Ip6 = &Ip6Header;
++
++ EXPECT_FALSE (Ip6IsOptionValid (IpSb, &Packet, NULL, 0, 0));
++}
++
++// Test Description
++// Verify that an unknown option with a length of 0 and type of <unknown> does not cause an infinite loop
++TEST_F (Ip6IsOptionValidTest, VerifyNoInfiniteLoopOnUnknownOptionLength0) {
++ NET_BUF Packet = { 0 };
++ // we need to define enough of the packet to make the function work
++ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
++ UINT32 DeadCode = 0xDeadC0de;
++ // Don't actually use this pointer, just pass it to the function, nothing will be done with it
++ IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode;
++
++ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++ EFI_IP6_HEADER Ip6Header = { 0 };
++
++ Ip6Header.SourceAddress = SourceAddress;
++ Ip6Header.DestinationAddress = DestinationAddress;
++ Packet.Ip.Ip6 = &Ip6Header;
++
++ IP6_OPTION_HEADER optionHeader;
++
++ optionHeader.Type = 23; // Unknown Option
++ optionHeader.Length = 0; // This will cause an infinite loop if the function is not working correctly
++
++ // This should be a valid option even though the length is 0
++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
++}
++
++// Test Description
++// Verify that an unknown option with a length of 1 and type of <unknown> does not cause an infinite loop
++TEST_F (Ip6IsOptionValidTest, VerifyNoInfiniteLoopOnUnknownOptionLength1) {
++ NET_BUF Packet = { 0 };
++ // we need to define enough of the packet to make the function work
++ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
++ UINT32 DeadCode = 0xDeadC0de;
++ // Don't actually use this pointer, just pass it to the function, nothing will be done with it
++ IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode;
++
++ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++ EFI_IP6_HEADER Ip6Header = { 0 };
++
++ Ip6Header.SourceAddress = SourceAddress;
++ Ip6Header.DestinationAddress = DestinationAddress;
++ Packet.Ip.Ip6 = &Ip6Header;
++
++ IP6_OPTION_HEADER optionHeader;
++
++ optionHeader.Type = 23; // Unknown Option
++ optionHeader.Length = 1; // This will cause an infinite loop if the function is not working correctly
++
++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
++}
++
++// Test Description
++// Verify that an unknown option with a length of 2 and type of <unknown> does not cause an infinite loop
++TEST_F (Ip6IsOptionValidTest, VerifyIpSkipUnknownOption) {
++ NET_BUF Packet = { 0 };
++ // we need to define enough of the packet to make the function work
++ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
++ UINT32 DeadCode = 0xDeadC0de;
++ // Don't actually use this pointer, just pass it to the function, nothing will be done with it
++ IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode;
++
++ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++ EFI_IP6_HEADER Ip6Header = { 0 };
++
++ Ip6Header.SourceAddress = SourceAddress;
++ Ip6Header.DestinationAddress = DestinationAddress;
++ Packet.Ip.Ip6 = &Ip6Header;
++
++ IP6_OPTION_HEADER optionHeader;
++
++ optionHeader.Type = 23; // Unknown Option
++ optionHeader.Length = 2; // Valid length for an unknown option
++
++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
++}
++
++// Test Description
++// Verify that Ip6OptionPad1 is valid with a length of 0
++TEST_F (Ip6IsOptionValidTest, VerifyIp6OptionPad1) {
++ NET_BUF Packet = { 0 };
++ // we need to define enough of the packet to make the function work
++ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
++ UINT32 DeadCode = 0xDeadC0de;
++ // Don't actually use this pointer, just pass it to the function, nothing will be done with it
++ IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode;
++
++ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++ EFI_IP6_HEADER Ip6Header = { 0 };
++
++ Ip6Header.SourceAddress = SourceAddress;
++ Ip6Header.DestinationAddress = DestinationAddress;
++ Packet.Ip.Ip6 = &Ip6Header;
++
++ IP6_OPTION_HEADER optionHeader;
++
++ optionHeader.Type = Ip6OptionPad1;
++ optionHeader.Length = 0;
++
++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
++}
++
++// Test Description
++// Verify that Ip6OptionPadN doesn't overflow with various lengths
++TEST_F (Ip6IsOptionValidTest, VerifyIp6OptionPadN) {
++ NET_BUF Packet = { 0 };
++ // we need to define enough of the packet to make the function work
++ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
++ UINT32 DeadCode = 0xDeadC0de;
++ // Don't actually use this pointer, just pass it to the function, nothing will be done with it
++ IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode;
++
++ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++ EFI_IP6_HEADER Ip6Header = { 0 };
++
++ Ip6Header.SourceAddress = SourceAddress;
++ Ip6Header.DestinationAddress = DestinationAddress;
++ Packet.Ip.Ip6 = &Ip6Header;
++
++ IP6_OPTION_HEADER optionHeader;
++
++ optionHeader.Type = Ip6OptionPadN;
++ optionHeader.Length = 0xFF;
++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
++
++ optionHeader.Length = 0xFE;
++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
++
++ optionHeader.Length = 0xFD;
++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
++
++ optionHeader.Length = 0xFC;
++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
++}
++
++// Test Description
++// Verify an unknown option doesn't cause an infinite loop with various lengths
++TEST_F (Ip6IsOptionValidTest, VerifyNoInfiniteLoopOnUnknownOptionLengthAttemptOverflow) {
++ NET_BUF Packet = { 0 };
++ // we need to define enough of the packet to make the function work
++ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
++ UINT32 DeadCode = 0xDeadC0de;
++ // Don't actually use this pointer, just pass it to the function, nothing will be done with it
++ IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode;
++
++ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++ EFI_IP6_HEADER Ip6Header = { 0 };
++
++ Ip6Header.SourceAddress = SourceAddress;
++ Ip6Header.DestinationAddress = DestinationAddress;
++ Packet.Ip.Ip6 = &Ip6Header;
++
++ IP6_OPTION_HEADER optionHeader;
++
++ optionHeader.Type = 23; // Unknown Option
++ optionHeader.Length = 0xFF;
++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
++
++ optionHeader.Length = 0xFE;
++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
++
++ optionHeader.Length = 0xFD;
++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
++
++ optionHeader.Length = 0xFC;
++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
++}
++
++// Test Description
++// Verify that the function supports multiple options
++TEST_F (Ip6IsOptionValidTest, MultiOptionSupport) {
++ UINT16 HdrLen;
++ NET_BUF Packet = { 0 };
++ // we need to define enough of the packet to make the function work
++ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
++ UINT32 DeadCode = 0xDeadC0de;
++ // Don't actually use this pointer, just pass it to the function, nothing will be done with it
++ IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode;
++
++ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++ EFI_IP6_HEADER Ip6Header = { 0 };
++
++ Ip6Header.SourceAddress = SourceAddress;
++ Ip6Header.DestinationAddress = DestinationAddress;
++ Packet.Ip.Ip6 = &Ip6Header;
++
++ UINT8 ExtHdr[1024] = { 0 };
++ UINT8 *Cursor = ExtHdr;
++ IP6_OPTION_HEADER *Option = (IP6_OPTION_HEADER *)ExtHdr;
++
++ // Let's start chaining options
++
++ Option->Type = 23; // Unknown Option
++ Option->Length = 0xFC;
++
++ Cursor += sizeof (IP6_OPTION_HEADER) + 0xFC;
++
++ Option = (IP6_OPTION_HEADER *)Cursor;
++ Option->Type = Ip6OptionPad1;
++
++ Cursor += sizeof (1);
++
++ // Type and length aren't processed, instead it just moves the pointer forward by 4 bytes
++ Option = (IP6_OPTION_HEADER *)Cursor;
++ Option->Type = Ip6OptionRouterAlert;
++ Option->Length = 4;
++
++ Cursor += sizeof (IP6_OPTION_HEADER) + 4;
++
++ Option = (IP6_OPTION_HEADER *)Cursor;
++ Option->Type = Ip6OptionPadN;
++ Option->Length = 0xFC;
++
++ Cursor += sizeof (IP6_OPTION_HEADER) + 0xFC;
++
++ Option = (IP6_OPTION_HEADER *)Cursor;
++ Option->Type = Ip6OptionRouterAlert;
++ Option->Length = 4;
++
++ Cursor += sizeof (IP6_OPTION_HEADER) + 4;
++
++ // Total 524
++
++ HdrLen = (UINT16)(Cursor - ExtHdr);
++
++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, ExtHdr, HdrLen, 0));
++}
+diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h
+new file mode 100644
+index 0000000000..0509b6ae30
+--- /dev/null
++++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h
+@@ -0,0 +1,40 @@
++/** @file
++ Exposes the functions needed to test the Ip6Option module.
++
++ Copyright (c) Microsoft Corporation
++ SPDX-License-Identifier: BSD-2-Clause-Patent
++**/
++
++#ifndef IP6_OPTION_HEADER_GOOGLE_TEST_H_
++#define IP6_OPTION_HEADER_GOOGLE_TEST_H_
++
++#include <Uefi.h>
++#include "../Ip6Impl.h"
++
++/**
++ Validate the IP6 option format for both the packets we received
++ and that we will transmit. It will compute the ICMPv6 error message fields
++ if the option is malformatted.
++
++ @param[in] IpSb The IP6 service data.
++ @param[in] Packet The to be validated packet.
++ @param[in] Option The first byte of the option.
++ @param[in] OptionLen The length of the whole option.
++ @param[in] Pointer Identifies the octet offset within
++ the invoking packet where the error was detected.
++
++
++ @retval TRUE The option is properly formatted.
++ @retval FALSE The option is malformatted.
++
++**/
++BOOLEAN
++Ip6IsOptionValid (
++ IN IP6_SERVICE *IpSb,
++ IN NET_BUF *Packet,
++ IN UINT8 *Option,
++ IN UINT16 OptionLen,
++ IN UINT32 Pointer
++ );
++
++#endif // __IP6_OPTION_HEADER_GOOGLE_TEST_H__
+--
+2.40.0
+
@@ -37,6 +37,8 @@ SRC_URI = "gitsm://github.com/tianocore/edk2.git;branch=master;protocol=https \
file://CVE-2023-45230-0002.patch \
file://CVE-2023-45231-0001.patch \
file://CVE-2023-45231-0002.patch \
+ file://CVE-2023-45232-CVE-2023-45233-0001.patch \
+ file://CVE-2023-45232-CVE-2023-45233-0002.patch \
"
PV = "edk2-stable202202"