summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta/recipes-core/ovmf/ovmf/CVE-2023-45232-CVE-2023-45233-0001.patch360
-rw-r--r--meta/recipes-core/ovmf/ovmf/CVE-2023-45232-CVE-2023-45233-0002.patch417
-rw-r--r--meta/recipes-core/ovmf/ovmf_git.bb2
3 files changed, 779 insertions, 0 deletions
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2023-45232-CVE-2023-45233-0001.patch b/meta/recipes-core/ovmf/ovmf/CVE-2023-45232-CVE-2023-45233-0001.patch
new file mode 100644
index 0000000000..d43e971d9d
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/CVE-2023-45232-CVE-2023-45233-0001.patch
@@ -0,0 +1,360 @@
1From 4df0229ef992d4f2721a8508787ebf9dc81fbd6e Mon Sep 17 00:00:00 2001
2From: Doug Flick <dougflick@microsoft.com>
3Date: Fri, 26 Jan 2024 05:54:50 +0800
4Subject: [PATCH] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Patch
5
6REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4537
7REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4538
8
9Bug Details:
10PixieFail Bug #4
11CVE-2023-45232
12CVSS 7.5 : CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
13CWE-835 Loop with Unreachable Exit Condition ('Infinite Loop')
14
15Infinite loop when parsing unknown options in the Destination Options
16header
17
18PixieFail Bug #5
19CVE-2023-45233
20CVSS 7.5 : CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
21CWE-835 Loop with Unreachable Exit Condition ('Infinite Loop')
22
23Infinite loop when parsing a PadN option in the Destination Options
24header
25
26Change Overview:
27
28Most importantly this change corrects the following incorrect math
29and cleans up the code.
30
31> // It is a PadN option
32> //
33> - Offset = (UINT8)(Offset + *(Option + Offset + 1) + 2);
34> + OptDataLen = ((EFI_IP6_OPTION *)(Option + Offset))->Length;
35> + Offset = IP6_NEXT_OPTION_OFFSET (Offset, OptDataLen);
36
37> case Ip6OptionSkip:
38> - Offset = (UINT8)(Offset + *(Option + Offset + 1));
39> OptDataLen = ((EFI_IP6_OPTION *)(Option + Offset))->Length;
40> Offset = IP6_NEXT_OPTION_OFFSET (Offset, OptDataLen);
41
42Additionally, this change also corrects incorrect math where the calling
43function was calculating the HDR EXT optionLen as a uint8 instead of a
44uint16
45
46> - OptionLen = (UINT8)((*Option + 1) * 8 - 2);
47> + OptionLen = IP6_HDR_EXT_LEN (*Option) -
48IP6_COMBINED_SIZE_OF_NEXT_HDR_AND_LEN;
49
50Additionally this check adds additional logic to santize the incoming
51data
52
53Cc: Saloni Kasbekar <saloni.kasbekar@intel.com>
54Cc: Zachary Clark-williams <zachary.clark-williams@intel.com>
55
56Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
57Reviewed-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
58
59CVE: CVE-2023-45232, CVE-2023-45233
60
61Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/4df0229ef992d4f2721a8508787ebf9dc81fbd6e]
62
63Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
64---
65 NetworkPkg/Ip6Dxe/Ip6Nd.h | 35 ++++++++++++++++
66 NetworkPkg/Ip6Dxe/Ip6Option.c | 76 ++++++++++++++++++++++++++++++-----
67 NetworkPkg/Ip6Dxe/Ip6Option.h | 71 ++++++++++++++++++++++++++++++++
68 3 files changed, 171 insertions(+), 11 deletions(-)
69
70diff --git a/NetworkPkg/Ip6Dxe/Ip6Nd.h b/NetworkPkg/Ip6Dxe/Ip6Nd.h
71index 860934a167..bf64e9114e 100644
72--- a/NetworkPkg/Ip6Dxe/Ip6Nd.h
73+++ b/NetworkPkg/Ip6Dxe/Ip6Nd.h
74@@ -56,13 +56,48 @@ VOID
75 VOID *Context
76 );
77
78+//
79+// Per RFC8200 Section 4.2
80+//
81+// Two of the currently-defined extension headers -- the Hop-by-Hop
82+// Options header and the Destination Options header -- carry a variable
83+// number of type-length-value (TLV) encoded "options", of the following
84+// format:
85+//
86+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- - - - - - - - -
87+// | Option Type | Opt Data Len | Option Data
88+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- - - - - - - - -
89+//
90+// Option Type 8-bit identifier of the type of option.
91+//
92+// Opt Data Len 8-bit unsigned integer. Length of the Option
93+// Data field of this option, in octets.
94+//
95+// Option Data Variable-length field. Option-Type-specific
96+// data.
97+//
98 typedef struct _IP6_OPTION_HEADER {
99+ ///
100+ /// identifier of the type of option.
101+ ///
102 UINT8 Type;
103+ ///
104+ /// Length of the Option Data field of this option, in octets.
105+ ///
106 UINT8 Length;
107+ ///
108+ /// Option-Type-specific data.
109+ ///
110 } IP6_OPTION_HEADER;
111
112 STATIC_ASSERT (sizeof (IP6_OPTION_HEADER) == 2, "IP6_OPTION_HEADER is expected to be exactly 2 bytes long.");
113
114+#define IP6_NEXT_OPTION_OFFSET(offset, length) (offset + sizeof(IP6_OPTION_HEADER) + length)
115+STATIC_ASSERT (
116+ IP6_NEXT_OPTION_OFFSET (0, 0) == 2,
117+ "The next option is minimally the combined size of the option tag and length"
118+ );
119+
120 typedef struct _IP6_ETHE_ADDR_OPTION {
121 UINT8 Type;
122 UINT8 Length;
123diff --git a/NetworkPkg/Ip6Dxe/Ip6Option.c b/NetworkPkg/Ip6Dxe/Ip6Option.c
124index 8718d5d875..fd97ce116f 100644
125--- a/NetworkPkg/Ip6Dxe/Ip6Option.c
126+++ b/NetworkPkg/Ip6Dxe/Ip6Option.c
127@@ -17,7 +17,8 @@
128 @param[in] IpSb The IP6 service data.
129 @param[in] Packet The to be validated packet.
130 @param[in] Option The first byte of the option.
131- @param[in] OptionLen The length of the whole option.
132+ @param[in] OptionLen The length of all options, expressed in byte length of octets.
133+ Maximum length is 2046 bytes or ((n + 1) * 8) - 2 where n is 255.
134 @param[in] Pointer Identifies the octet offset within
135 the invoking packet where the error was detected.
136
137@@ -31,12 +32,33 @@ Ip6IsOptionValid (
138 IN IP6_SERVICE *IpSb,
139 IN NET_BUF *Packet,
140 IN UINT8 *Option,
141- IN UINT8 OptionLen,
142+ IN UINT16 OptionLen,
143 IN UINT32 Pointer
144 )
145 {
146- UINT8 Offset;
147- UINT8 OptionType;
148+ UINT16 Offset;
149+ UINT8 OptionType;
150+ UINT8 OptDataLen;
151+
152+ if (Option == NULL) {
153+ ASSERT (Option != NULL);
154+ return FALSE;
155+ }
156+
157+ if ((OptionLen <= 0) || (OptionLen > IP6_MAX_EXT_DATA_LENGTH)) {
158+ ASSERT (OptionLen > 0 && OptionLen <= IP6_MAX_EXT_DATA_LENGTH);
159+ return FALSE;
160+ }
161+
162+ if (Packet == NULL) {
163+ ASSERT (Packet != NULL);
164+ return FALSE;
165+ }
166+
167+ if (IpSb == NULL) {
168+ ASSERT (IpSb != NULL);
169+ return FALSE;
170+ }
171
172 Offset = 0;
173
174@@ -54,7 +76,8 @@ Ip6IsOptionValid (
175 //
176 // It is a PadN option
177 //
178- Offset = (UINT8)(Offset + *(Option + Offset + 1) + 2);
179+ OptDataLen = ((IP6_OPTION_HEADER *)(Option + Offset))->Length;
180+ Offset = IP6_NEXT_OPTION_OFFSET (Offset, OptDataLen);
181 break;
182 case Ip6OptionRouterAlert:
183 //
184@@ -69,7 +92,8 @@ Ip6IsOptionValid (
185 //
186 switch (OptionType & Ip6OptionMask) {
187 case Ip6OptionSkip:
188- Offset = (UINT8)(Offset + *(Option + Offset + 1));
189+ OptDataLen = ((IP6_OPTION_HEADER *)(Option + Offset))->Length;
190+ Offset = IP6_NEXT_OPTION_OFFSET (Offset, OptDataLen);
191 break;
192 case Ip6OptionDiscard:
193 return FALSE;
194@@ -308,7 +332,7 @@ Ip6IsExtsValid (
195 UINT32 Pointer;
196 UINT32 Offset;
197 UINT8 *Option;
198- UINT8 OptionLen;
199+ UINT16 OptionLen;
200 BOOLEAN Flag;
201 UINT8 CountD;
202 UINT8 CountA;
203@@ -385,6 +409,36 @@ Ip6IsExtsValid (
204 // Fall through
205 //
206 case IP6_DESTINATION:
207+ //
208+ // See https://www.rfc-editor.org/rfc/rfc2460#section-4.2 page 23
209+ //
210+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
211+ // | Next Header | Hdr Ext Len | |
212+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
213+ // | |
214+ // . .
215+ // . Options .
216+ // . .
217+ // | |
218+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
219+ //
220+ //
221+ // Next Header 8-bit selector. Identifies the type of header
222+ // immediately following the Destination Options
223+ // header. Uses the same values as the IPv4
224+ // Protocol field [RFC-1700 et seq.].
225+ //
226+ // Hdr Ext Len 8-bit unsigned integer. Length of the
227+ // Destination Options header in 8-octet units, not
228+ // including the first 8 octets.
229+ //
230+ // Options Variable-length field, of length such that the
231+ // complete Destination Options header is an
232+ // integer multiple of 8 octets long. Contains one
233+ // or more TLV-encoded options, as described in
234+ // section 4.2.
235+ //
236+
237 if (*NextHeader == IP6_DESTINATION) {
238 CountD++;
239 }
240@@ -398,7 +452,7 @@ Ip6IsExtsValid (
241
242 Offset++;
243 Option = ExtHdrs + Offset;
244- OptionLen = (UINT8)((*Option + 1) * 8 - 2);
245+ OptionLen = IP6_HDR_EXT_LEN (*Option) - sizeof (IP6_EXT_HDR);
246 Option++;
247 Offset++;
248
249@@ -430,7 +484,7 @@ Ip6IsExtsValid (
250 //
251 // Ignore the routing header and proceed to process the next header.
252 //
253- Offset = Offset + (RoutingHead->HeaderLen + 1) * 8;
254+ Offset = Offset + IP6_HDR_EXT_LEN (RoutingHead->HeaderLen);
255
256 if (UnFragmentLen != NULL) {
257 *UnFragmentLen = Offset;
258@@ -441,7 +495,7 @@ Ip6IsExtsValid (
259 // to the packet's source address, pointing to the unrecognized routing
260 // type.
261 //
262- Pointer = Offset + 2 + sizeof (EFI_IP6_HEADER);
263+ Pointer = Offset + sizeof (IP6_EXT_HDR) + sizeof (EFI_IP6_HEADER);
264 if ((IpSb != NULL) && (Packet != NULL) &&
265 !IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress))
266 {
267@@ -527,7 +581,7 @@ Ip6IsExtsValid (
268 //
269 // RFC2402, Payload length is specified in 32-bit words, minus "2".
270 //
271- OptionLen = (UINT8)((*Option + 2) * 4);
272+ OptionLen = ((UINT16)(*Option + 2) * 4);
273 Offset = Offset + OptionLen;
274 break;
275
276diff --git a/NetworkPkg/Ip6Dxe/Ip6Option.h b/NetworkPkg/Ip6Dxe/Ip6Option.h
277index bd8e223c8a..fb07c28f5a 100644
278--- a/NetworkPkg/Ip6Dxe/Ip6Option.h
279+++ b/NetworkPkg/Ip6Dxe/Ip6Option.h
280@@ -12,6 +12,77 @@
281
282 #define IP6_FRAGMENT_OFFSET_MASK (~0x3)
283
284+//
285+// For more information see RFC 8200, Section 4.3, 4.4, and 4.6
286+//
287+// This example format is from section 4.6
288+// This does not apply to fragment headers
289+//
290+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
291+// | Next Header | Hdr Ext Len | |
292+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
293+// | |
294+// . .
295+// . Header-Specific Data .
296+// . .
297+// | |
298+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
299+//
300+// Next Header 8-bit selector. Identifies the type of
301+// header immediately following the extension
302+// header. Uses the same values as the IPv4
303+// Protocol field [IANA-PN].
304+//
305+// Hdr Ext Len 8-bit unsigned integer. Length of the
306+// Destination Options header in 8-octet units,
307+// not including the first 8 octets.
308+
309+//
310+// These defines apply to the following:
311+// 1. Hop by Hop
312+// 2. Routing
313+// 3. Destination
314+//
315+typedef struct _IP6_EXT_HDR {
316+ ///
317+ /// The Next Header field identifies the type of header immediately
318+ ///
319+ UINT8 NextHeader;
320+ ///
321+ /// The Hdr Ext Len field specifies the length of the Hop-by-Hop Options
322+ ///
323+ UINT8 HdrExtLen;
324+ ///
325+ /// Header-Specific Data
326+ ///
327+} IP6_EXT_HDR;
328+
329+STATIC_ASSERT (
330+ sizeof (IP6_EXT_HDR) == 2,
331+ "The combined size of Next Header and Len is two 8 bit fields"
332+ );
333+
334+//
335+// IPv6 extension headers contain an 8-bit length field which describes the size of
336+// the header. However, the length field only includes the size of the extension
337+// header options, not the size of the first 8 bytes of the header. Therefore, in
338+// order to calculate the full size of the extension header, we add 1 (to account
339+// for the first 8 bytes omitted by the length field reporting) and then multiply
340+// by 8 (since the size is represented in 8-byte units).
341+//
342+// a is the length field of the extension header (UINT8)
343+// The result may be up to 2046 octets (UINT16)
344+//
345+#define IP6_HDR_EXT_LEN(a) (((UINT16)((UINT8)(a)) + 1) * 8)
346+
347+// This is the maxmimum length permissible by a extension header
348+// Length is UINT8 of 8 octets not including the first 8 octets
349+#define IP6_MAX_EXT_DATA_LENGTH (IP6_HDR_EXT_LEN (MAX_UINT8) - sizeof(IP6_EXT_HDR))
350+STATIC_ASSERT (
351+ IP6_MAX_EXT_DATA_LENGTH == 2046,
352+ "Maximum data length is ((MAX_UINT8 + 1) * 8) - 2"
353+ );
354+
355 typedef struct _IP6_FRAGMENT_HEADER {
356 UINT8 NextHeader;
357 UINT8 Reserved;
358--
3592.40.0
360
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2023-45232-CVE-2023-45233-0002.patch b/meta/recipes-core/ovmf/ovmf/CVE-2023-45232-CVE-2023-45233-0002.patch
new file mode 100644
index 0000000000..c6834a852e
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/CVE-2023-45232-CVE-2023-45233-0002.patch
@@ -0,0 +1,417 @@
1From c9c87f08dd6ace36fa843424522c3558a8374cac Mon Sep 17 00:00:00 2001
2From: Doug Flick <dougflick@microsoft.com>
3Date: Fri, 26 Jan 2024 05:54:51 +0800
4Subject: [PATCH] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Unit Tests
5
6REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4537
7REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4538
8
9Unit tests to confirm that..
10
11Infinite loop when parsing unknown options in the Destination Options
12header
13
14and
15
16Infinite loop when parsing a PadN option in the Destination Options
17header
18
19... have been patched
20
21This patch tests the following functions:
22Ip6IsOptionValid
23
24Cc: Saloni Kasbekar <saloni.kasbekar@intel.com>
25Cc: Zachary Clark-williams <zachary.clark-williams@intel.com>
26
27Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
28Reviewed-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
29
30CVE: CVE-2023-45232, CVE-2023-45233
31
32Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/c9c87f08dd6ace36fa843424522c3558a8374cac]
33
34Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
35---
36 .../Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf | 10 +-
37 .../Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp | 278 ++++++++++++++++++
38 .../Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h | 40 +++
39 3 files changed, 324 insertions(+), 4 deletions(-)
40 create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h
41
42diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
43index 6e4de0745f..ba29dbabad 100644
44--- a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
45+++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
46@@ -1,13 +1,13 @@
47 ## @file
48-# Unit test suite for the Ip6Dxe using Google Test
49+# Unit test suite for the Ip6DxeGoogleTest using Google Test
50 #
51 # Copyright (c) Microsoft Corporation.<BR>
52 # SPDX-License-Identifier: BSD-2-Clause-Patent
53 ##
54 [Defines]
55 INF_VERSION = 0x00010017
56- BASE_NAME = Ip6DxeUnitTest
57- FILE_GUID = 4F05D17D-D3E7-4AAE-820C-576D46D2D34A
58+ BASE_NAME = Ip6DxeGoogleTest
59+ FILE_GUID = AE39981C-B7FE-41A8-A9C2-F41910477CA3
60 VERSION_STRING = 1.0
61 MODULE_TYPE = HOST_APPLICATION
62 #
63@@ -16,9 +16,11 @@
64 # VALID_ARCHITECTURES = IA32 X64 AARCH64
65 #
66 [Sources]
67+ ../Ip6Option.c
68+ Ip6OptionGoogleTest.h
69 Ip6DxeGoogleTest.cpp
70 Ip6OptionGoogleTest.cpp
71- ../Ip6Option.c
72+ Ip6OptionGoogleTest.h
73
74 [Packages]
75 MdePkg/MdePkg.dec
76diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
77index f2cd90e1a9..29f8a4a96e 100644
78--- a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
79+++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
80@@ -12,6 +12,7 @@ extern "C" {
81 #include <Library/DebugLib.h>
82 #include "../Ip6Impl.h"
83 #include "../Ip6Option.h"
84+ #include "Ip6OptionGoogleTest.h"
85 }
86
87 /////////////////////////////////////////////////////////////////////////
88@@ -127,3 +128,280 @@ TEST_F (Ip6OptionValidationTest, InvalidPrefixInfoOptionLengthShouldReturnFalse)
89
90 EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen));
91 }
92+
93+////////////////////////////////////////////////////////////////////////
94+// Ip6IsOptionValid Tests
95+////////////////////////////////////////////////////////////////////////
96+
97+// Define a fixture for your tests if needed
98+class Ip6IsOptionValidTest : public ::testing::Test {
99+protected:
100+ // Add any setup code if needed
101+ virtual void
102+ SetUp (
103+ )
104+ {
105+ // Initialize any resources or variables
106+ }
107+
108+ // Add any cleanup code if needed
109+ virtual void
110+ TearDown (
111+ )
112+ {
113+ // Clean up any resources or variables
114+ }
115+};
116+
117+// Test Description
118+// Verify that a NULL option is Invalid
119+TEST_F (Ip6IsOptionValidTest, NullOptionShouldReturnTrue) {
120+ NET_BUF Packet = { 0 };
121+ // we need to define enough of the packet to make the function work
122+ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
123+ IP6_SERVICE *IpSb = NULL;
124+
125+ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
126+ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
127+ EFI_IP6_HEADER Ip6Header = { 0 };
128+
129+ Ip6Header.SourceAddress = SourceAddress;
130+ Ip6Header.DestinationAddress = DestinationAddress;
131+ Packet.Ip.Ip6 = &Ip6Header;
132+
133+ EXPECT_FALSE (Ip6IsOptionValid (IpSb, &Packet, NULL, 0, 0));
134+}
135+
136+// Test Description
137+// Verify that an unknown option with a length of 0 and type of <unknown> does not cause an infinite loop
138+TEST_F (Ip6IsOptionValidTest, VerifyNoInfiniteLoopOnUnknownOptionLength0) {
139+ NET_BUF Packet = { 0 };
140+ // we need to define enough of the packet to make the function work
141+ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
142+ UINT32 DeadCode = 0xDeadC0de;
143+ // Don't actually use this pointer, just pass it to the function, nothing will be done with it
144+ IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode;
145+
146+ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
147+ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
148+ EFI_IP6_HEADER Ip6Header = { 0 };
149+
150+ Ip6Header.SourceAddress = SourceAddress;
151+ Ip6Header.DestinationAddress = DestinationAddress;
152+ Packet.Ip.Ip6 = &Ip6Header;
153+
154+ IP6_OPTION_HEADER optionHeader;
155+
156+ optionHeader.Type = 23; // Unknown Option
157+ optionHeader.Length = 0; // This will cause an infinite loop if the function is not working correctly
158+
159+ // This should be a valid option even though the length is 0
160+ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
161+}
162+
163+// Test Description
164+// Verify that an unknown option with a length of 1 and type of <unknown> does not cause an infinite loop
165+TEST_F (Ip6IsOptionValidTest, VerifyNoInfiniteLoopOnUnknownOptionLength1) {
166+ NET_BUF Packet = { 0 };
167+ // we need to define enough of the packet to make the function work
168+ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
169+ UINT32 DeadCode = 0xDeadC0de;
170+ // Don't actually use this pointer, just pass it to the function, nothing will be done with it
171+ IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode;
172+
173+ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
174+ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
175+ EFI_IP6_HEADER Ip6Header = { 0 };
176+
177+ Ip6Header.SourceAddress = SourceAddress;
178+ Ip6Header.DestinationAddress = DestinationAddress;
179+ Packet.Ip.Ip6 = &Ip6Header;
180+
181+ IP6_OPTION_HEADER optionHeader;
182+
183+ optionHeader.Type = 23; // Unknown Option
184+ optionHeader.Length = 1; // This will cause an infinite loop if the function is not working correctly
185+
186+ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
187+}
188+
189+// Test Description
190+// Verify that an unknown option with a length of 2 and type of <unknown> does not cause an infinite loop
191+TEST_F (Ip6IsOptionValidTest, VerifyIpSkipUnknownOption) {
192+ NET_BUF Packet = { 0 };
193+ // we need to define enough of the packet to make the function work
194+ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
195+ UINT32 DeadCode = 0xDeadC0de;
196+ // Don't actually use this pointer, just pass it to the function, nothing will be done with it
197+ IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode;
198+
199+ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
200+ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
201+ EFI_IP6_HEADER Ip6Header = { 0 };
202+
203+ Ip6Header.SourceAddress = SourceAddress;
204+ Ip6Header.DestinationAddress = DestinationAddress;
205+ Packet.Ip.Ip6 = &Ip6Header;
206+
207+ IP6_OPTION_HEADER optionHeader;
208+
209+ optionHeader.Type = 23; // Unknown Option
210+ optionHeader.Length = 2; // Valid length for an unknown option
211+
212+ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
213+}
214+
215+// Test Description
216+// Verify that Ip6OptionPad1 is valid with a length of 0
217+TEST_F (Ip6IsOptionValidTest, VerifyIp6OptionPad1) {
218+ NET_BUF Packet = { 0 };
219+ // we need to define enough of the packet to make the function work
220+ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
221+ UINT32 DeadCode = 0xDeadC0de;
222+ // Don't actually use this pointer, just pass it to the function, nothing will be done with it
223+ IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode;
224+
225+ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
226+ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
227+ EFI_IP6_HEADER Ip6Header = { 0 };
228+
229+ Ip6Header.SourceAddress = SourceAddress;
230+ Ip6Header.DestinationAddress = DestinationAddress;
231+ Packet.Ip.Ip6 = &Ip6Header;
232+
233+ IP6_OPTION_HEADER optionHeader;
234+
235+ optionHeader.Type = Ip6OptionPad1;
236+ optionHeader.Length = 0;
237+
238+ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
239+}
240+
241+// Test Description
242+// Verify that Ip6OptionPadN doesn't overflow with various lengths
243+TEST_F (Ip6IsOptionValidTest, VerifyIp6OptionPadN) {
244+ NET_BUF Packet = { 0 };
245+ // we need to define enough of the packet to make the function work
246+ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
247+ UINT32 DeadCode = 0xDeadC0de;
248+ // Don't actually use this pointer, just pass it to the function, nothing will be done with it
249+ IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode;
250+
251+ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
252+ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
253+ EFI_IP6_HEADER Ip6Header = { 0 };
254+
255+ Ip6Header.SourceAddress = SourceAddress;
256+ Ip6Header.DestinationAddress = DestinationAddress;
257+ Packet.Ip.Ip6 = &Ip6Header;
258+
259+ IP6_OPTION_HEADER optionHeader;
260+
261+ optionHeader.Type = Ip6OptionPadN;
262+ optionHeader.Length = 0xFF;
263+ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
264+
265+ optionHeader.Length = 0xFE;
266+ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
267+
268+ optionHeader.Length = 0xFD;
269+ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
270+
271+ optionHeader.Length = 0xFC;
272+ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
273+}
274+
275+// Test Description
276+// Verify an unknown option doesn't cause an infinite loop with various lengths
277+TEST_F (Ip6IsOptionValidTest, VerifyNoInfiniteLoopOnUnknownOptionLengthAttemptOverflow) {
278+ NET_BUF Packet = { 0 };
279+ // we need to define enough of the packet to make the function work
280+ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
281+ UINT32 DeadCode = 0xDeadC0de;
282+ // Don't actually use this pointer, just pass it to the function, nothing will be done with it
283+ IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode;
284+
285+ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
286+ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
287+ EFI_IP6_HEADER Ip6Header = { 0 };
288+
289+ Ip6Header.SourceAddress = SourceAddress;
290+ Ip6Header.DestinationAddress = DestinationAddress;
291+ Packet.Ip.Ip6 = &Ip6Header;
292+
293+ IP6_OPTION_HEADER optionHeader;
294+
295+ optionHeader.Type = 23; // Unknown Option
296+ optionHeader.Length = 0xFF;
297+ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
298+
299+ optionHeader.Length = 0xFE;
300+ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
301+
302+ optionHeader.Length = 0xFD;
303+ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
304+
305+ optionHeader.Length = 0xFC;
306+ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
307+}
308+
309+// Test Description
310+// Verify that the function supports multiple options
311+TEST_F (Ip6IsOptionValidTest, MultiOptionSupport) {
312+ UINT16 HdrLen;
313+ NET_BUF Packet = { 0 };
314+ // we need to define enough of the packet to make the function work
315+ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
316+ UINT32 DeadCode = 0xDeadC0de;
317+ // Don't actually use this pointer, just pass it to the function, nothing will be done with it
318+ IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode;
319+
320+ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
321+ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
322+ EFI_IP6_HEADER Ip6Header = { 0 };
323+
324+ Ip6Header.SourceAddress = SourceAddress;
325+ Ip6Header.DestinationAddress = DestinationAddress;
326+ Packet.Ip.Ip6 = &Ip6Header;
327+
328+ UINT8 ExtHdr[1024] = { 0 };
329+ UINT8 *Cursor = ExtHdr;
330+ IP6_OPTION_HEADER *Option = (IP6_OPTION_HEADER *)ExtHdr;
331+
332+ // Let's start chaining options
333+
334+ Option->Type = 23; // Unknown Option
335+ Option->Length = 0xFC;
336+
337+ Cursor += sizeof (IP6_OPTION_HEADER) + 0xFC;
338+
339+ Option = (IP6_OPTION_HEADER *)Cursor;
340+ Option->Type = Ip6OptionPad1;
341+
342+ Cursor += sizeof (1);
343+
344+ // Type and length aren't processed, instead it just moves the pointer forward by 4 bytes
345+ Option = (IP6_OPTION_HEADER *)Cursor;
346+ Option->Type = Ip6OptionRouterAlert;
347+ Option->Length = 4;
348+
349+ Cursor += sizeof (IP6_OPTION_HEADER) + 4;
350+
351+ Option = (IP6_OPTION_HEADER *)Cursor;
352+ Option->Type = Ip6OptionPadN;
353+ Option->Length = 0xFC;
354+
355+ Cursor += sizeof (IP6_OPTION_HEADER) + 0xFC;
356+
357+ Option = (IP6_OPTION_HEADER *)Cursor;
358+ Option->Type = Ip6OptionRouterAlert;
359+ Option->Length = 4;
360+
361+ Cursor += sizeof (IP6_OPTION_HEADER) + 4;
362+
363+ // Total 524
364+
365+ HdrLen = (UINT16)(Cursor - ExtHdr);
366+
367+ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, ExtHdr, HdrLen, 0));
368+}
369diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h
370new file mode 100644
371index 0000000000..0509b6ae30
372--- /dev/null
373+++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h
374@@ -0,0 +1,40 @@
375+/** @file
376+ Exposes the functions needed to test the Ip6Option module.
377+
378+ Copyright (c) Microsoft Corporation
379+ SPDX-License-Identifier: BSD-2-Clause-Patent
380+**/
381+
382+#ifndef IP6_OPTION_HEADER_GOOGLE_TEST_H_
383+#define IP6_OPTION_HEADER_GOOGLE_TEST_H_
384+
385+#include <Uefi.h>
386+#include "../Ip6Impl.h"
387+
388+/**
389+ Validate the IP6 option format for both the packets we received
390+ and that we will transmit. It will compute the ICMPv6 error message fields
391+ if the option is malformatted.
392+
393+ @param[in] IpSb The IP6 service data.
394+ @param[in] Packet The to be validated packet.
395+ @param[in] Option The first byte of the option.
396+ @param[in] OptionLen The length of the whole option.
397+ @param[in] Pointer Identifies the octet offset within
398+ the invoking packet where the error was detected.
399+
400+
401+ @retval TRUE The option is properly formatted.
402+ @retval FALSE The option is malformatted.
403+
404+**/
405+BOOLEAN
406+Ip6IsOptionValid (
407+ IN IP6_SERVICE *IpSb,
408+ IN NET_BUF *Packet,
409+ IN UINT8 *Option,
410+ IN UINT16 OptionLen,
411+ IN UINT32 Pointer
412+ );
413+
414+#endif // __IP6_OPTION_HEADER_GOOGLE_TEST_H__
415--
4162.40.0
417
diff --git a/meta/recipes-core/ovmf/ovmf_git.bb b/meta/recipes-core/ovmf/ovmf_git.bb
index e46b3ddebe..fc87cdf441 100644
--- a/meta/recipes-core/ovmf/ovmf_git.bb
+++ b/meta/recipes-core/ovmf/ovmf_git.bb
@@ -37,6 +37,8 @@ SRC_URI = "gitsm://github.com/tianocore/edk2.git;branch=master;protocol=https \
37 file://CVE-2023-45230-0002.patch \ 37 file://CVE-2023-45230-0002.patch \
38 file://CVE-2023-45231-0001.patch \ 38 file://CVE-2023-45231-0001.patch \
39 file://CVE-2023-45231-0002.patch \ 39 file://CVE-2023-45231-0002.patch \
40 file://CVE-2023-45232-CVE-2023-45233-0001.patch \
41 file://CVE-2023-45232-CVE-2023-45233-0002.patch \
40 " 42 "
41 43
42PV = "edk2-stable202202" 44PV = "edk2-stable202202"