* [OE-core][kirkstone 00/38] Patch review
@ 2024-12-04 17:53 Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 01/38] ovmf: Fix CVE-2022-36763 Steve Sakoman
` (37 more replies)
0 siblings, 38 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
Please review this set of changes for kirkstone and have comments back by
end of day Friday, December 6
Passed a-full on autobuilder:
https://valkyrie.yoctoproject.org/#/builders/29/builds/581
The following changes since commit 13b13b81b91f618c13cf972067c47bd810de852f:
gstreamer1.0: improve test reliability (2024-11-27 06:57:56 -0800)
are available in the Git repository at:
https://git.openembedded.org/openembedded-core-contrib stable/kirkstone-nut
https://git.openembedded.org/openembedded-core-contrib/log/?h=stable/kirkstone-nut
Changqing Li (2):
libsoup: fix CVE-2024-52531
rxvt-unicode.inc: disable the terminfo installation by setting TIC to
:
Divya Chellam (1):
qemu: fix CVE-2024-3446
Hongxu Jia (3):
ovmf: fix CVE-2024-38796
ovmf: fix CVE-2024-1298
python3-zipp: fix CVE-2024-5569
Jiaying Song (1):
diffoscope: fix CVE-2024-25711
Peter Marko (6):
cpio: ignore CVE-2023-7216
gnupg: ignore CVE-2022-3515
qemu: ignore CVE-2022-36648
grub: ignore CVE-2024-1048 and CVE-2023-4001
pixman: ignore CVE-2023-37769
qemu: patch CVE-2024-6505
Richard Purdie (12):
do_package/sstate/sstatesig: Change timestamp clamping to hash output
only
selftest/reproducible: Drop rawlogs
selftest/reproducible: Clean up pathnames
resulttool: Allow store to filter to specific revisions
resulttool: Use single space indentation in json output
oeqa/utils/gitarchive: Return tag name and improve exclude handling
resulttool: Fix passthrough of --all files in store mode
resulttool: Add --logfile-archive option to store mode
resulttool: Handle ltp rawlogs as well as ptest
resulttool: Clean up repoducible build logs
resulttool: Trim the precision of duration information
resulttool: Improve repo layout for oeselftest results
Soumya Sambu (11):
ovmf: Fix CVE-2022-36763
ovmf: Fix CVE-2022-36764
ovmf: Fix CVE-2023-45230
ovmf: Fix CVE-2023-45231
ovmf: Fix CVE-2023-45232, CVE-2023-45233
ovmf: Fix CVE-2023-45234
ovmf: Fix CVE-2023-45235
ovmf: Fix CVE-2023-45229
ovmf: Fix CVE-2023-45237
ovmf: Fix CVE-2023-45236
ovmf: Fix CVE-2022-36765
Vijay Anusuri (1):
libsoup-2.4: Backport fix for CVE-2024-52531
Yogita Urade (1):
qemu: fix CVE-2024-3447
meta/classes/sstate.bbclass | 16 -
meta/lib/oe/sstatesig.py | 7 +-
meta/lib/oeqa/core/runner.py | 2 +-
meta/lib/oeqa/selftest/cases/reproducible.py | 8 +-
meta/lib/oeqa/utils/gitarchive.py | 4 +-
meta/recipes-bsp/grub/grub2.inc | 2 +
...ential-UINT32-overflow-in-S3-ResumeC.patch | 51 +
...-Fix-overflow-issue-in-BasePeCoffLib.patch | 37 +
.../ovmf/ovmf/CVE-2022-36763-0001.patch | 985 ++++++++++
.../ovmf/ovmf/CVE-2022-36763-0002.patch | 889 +++++++++
.../ovmf/ovmf/CVE-2022-36763-0003.patch | 55 +
.../ovmf/ovmf/CVE-2022-36764-0001.patch | 271 +++
.../ovmf/ovmf/CVE-2022-36764-0002.patch | 281 +++
.../ovmf/ovmf/CVE-2022-36764-0003.patch | 48 +
.../ovmf/ovmf/CVE-2022-36765-0001.patch | 179 ++
.../ovmf/ovmf/CVE-2022-36765-0002.patch | 157 ++
.../ovmf/ovmf/CVE-2022-36765-0003.patch | 135 ++
.../ovmf/ovmf/CVE-2023-45229-0001.patch | 604 ++++++
.../ovmf/ovmf/CVE-2023-45229-0002.patch | 539 ++++++
.../ovmf/ovmf/CVE-2023-45229-0003.patch | 244 +++
.../ovmf/ovmf/CVE-2023-45229-0004.patch | 157 ++
.../ovmf/ovmf/CVE-2023-45230-0001.patch | 1617 +++++++++++++++++
.../ovmf/ovmf/CVE-2023-45230-0002.patch | 604 ++++++
.../ovmf/ovmf/CVE-2023-45231-0001.patch | 65 +
.../ovmf/ovmf/CVE-2023-45231-0002.patch | 250 +++
.../CVE-2023-45232-CVE-2023-45233-0001.patch | 360 ++++
.../CVE-2023-45232-CVE-2023-45233-0002.patch | 417 +++++
.../ovmf/ovmf/CVE-2023-45234-0001.patch | 154 ++
.../ovmf/ovmf/CVE-2023-45234-0002.patch | 485 +++++
.../ovmf/ovmf/CVE-2023-45235-0001.patch | 243 +++
.../ovmf/ovmf/CVE-2023-45235-0002.patch | 379 ++++
.../ovmf/ovmf/CVE-2023-45236.patch | 829 +++++++++
.../ovmf/ovmf/CVE-2023-45237-0001.patch | 78 +
.../ovmf/ovmf/CVE-2023-45237-0002.patch | 1288 +++++++++++++
meta/recipes-core/ovmf/ovmf_git.bb | 28 +
.../0001-Add-SanitizedNames-mixin.patch | 89 +
...Names-in-CompleteDirs.-Fixes-broken-.patch | 30 +
.../0003-Removed-SanitizedNames.patch | 95 +
...-loop-when-zipfile-begins-with-more-.patch | 48 +
...ath.rstrip-to-consolidate-checks-for.patch | 30 +
.../python/python3-zipp_3.7.0.bb | 8 +
meta/recipes-devtools/qemu/qemu.inc | 13 +
.../qemu/qemu/CVE-2024-3446-0001.patch | 218 +++
.../qemu/qemu/CVE-2024-3446-0002.patch | 427 +++++
.../qemu/qemu/CVE-2024-3446-0003.patch | 68 +
.../qemu/qemu/CVE-2024-3446-0004.patch | 144 ++
.../qemu/qemu/CVE-2024-3446-0005.patch | 42 +
.../qemu/qemu/CVE-2024-3446-0006.patch | 43 +
.../qemu/qemu/CVE-2024-3447.patch | 137 ++
.../qemu/qemu/CVE-2024-6505.patch | 40 +
meta/recipes-extended/cpio/cpio_2.14.bb | 2 +
.../xorg-lib/pixman_0.40.0.bb | 3 +
.../rxvt-unicode/rxvt-unicode.inc | 3 +-
.../diffoscope/CVE-2024-25711.patch | 116 ++
.../diffoscope/diffoscope_208.bb | 1 +
meta/recipes-support/gnupg/gnupg_2.3.7.bb | 2 +
.../libsoup-2.4/CVE-2024-52531-1.patch | 131 ++
.../libsoup-2.4/CVE-2024-52531-2.patch | 36 +
.../libsoup/libsoup-2.4_2.74.2.bb | 2 +
.../libsoup/libsoup/CVE-2024-52531-1.patch | 116 ++
.../libsoup/libsoup/CVE-2024-52531-2.patch | 40 +
.../libsoup/libsoup/CVE-2024-52531-3.patch | 136 ++
meta/recipes-support/libsoup/libsoup_3.0.7.bb | 3 +
scripts/lib/resulttool/manualexecution.py | 2 +-
scripts/lib/resulttool/report.py | 2 +-
scripts/lib/resulttool/resultutils.py | 76 +-
scripts/lib/resulttool/store.py | 26 +-
67 files changed, 13550 insertions(+), 47 deletions(-)
create mode 100644 meta/recipes-core/ovmf/ovmf/0001-MdeModulePkg-Potential-UINT32-overflow-in-S3-ResumeC.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/0001-MdePkg-Fix-overflow-issue-in-BasePeCoffLib.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0001.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0002.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0003.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2022-36764-0001.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2022-36764-0002.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2022-36764-0003.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2022-36765-0001.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2022-36765-0002.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2022-36765-0003.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45229-0001.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45229-0002.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45229-0003.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45229-0004.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45230-0001.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45230-0002.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45231-0001.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45231-0002.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45232-CVE-2023-45233-0001.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45232-CVE-2023-45233-0002.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45234-0001.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45234-0002.patch
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
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45236.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45237-0001.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45237-0002.patch
create mode 100644 meta/recipes-devtools/python/python3-zipp/0001-Add-SanitizedNames-mixin.patch
create mode 100644 meta/recipes-devtools/python/python3-zipp/0002-Employ-SanitizedNames-in-CompleteDirs.-Fixes-broken-.patch
create mode 100644 meta/recipes-devtools/python/python3-zipp/0003-Removed-SanitizedNames.patch
create mode 100644 meta/recipes-devtools/python/python3-zipp/0004-Address-infinite-loop-when-zipfile-begins-with-more-.patch
create mode 100644 meta/recipes-devtools/python/python3-zipp/0005-Prefer-simpler-path.rstrip-to-consolidate-checks-for.patch
create mode 100644 meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0001.patch
create mode 100644 meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0002.patch
create mode 100644 meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0003.patch
create mode 100644 meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0004.patch
create mode 100644 meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0005.patch
create mode 100644 meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0006.patch
create mode 100644 meta/recipes-devtools/qemu/qemu/CVE-2024-3447.patch
create mode 100644 meta/recipes-devtools/qemu/qemu/CVE-2024-6505.patch
create mode 100644 meta/recipes-support/diffoscope/diffoscope/CVE-2024-25711.patch
create mode 100644 meta/recipes-support/libsoup/libsoup-2.4/CVE-2024-52531-1.patch
create mode 100644 meta/recipes-support/libsoup/libsoup-2.4/CVE-2024-52531-2.patch
create mode 100644 meta/recipes-support/libsoup/libsoup/CVE-2024-52531-1.patch
create mode 100644 meta/recipes-support/libsoup/libsoup/CVE-2024-52531-2.patch
create mode 100644 meta/recipes-support/libsoup/libsoup/CVE-2024-52531-3.patch
--
2.34.1
^ permalink raw reply [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 01/38] ovmf: Fix CVE-2022-36763
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 02/38] ovmf: Fix CVE-2022-36764 Steve Sakoman
` (36 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Soumya Sambu <soumya.sambu@windriver.com>
EDK2 is susceptible to a vulnerability in the Tcg2MeasureGptTable()
function, allowing a user to trigger a heap buffer overflow via a local
network. Successful exploitation of this vulnerability may result in a
compromise of confidentiality, integrity, and/or availability.
References:
https://nvd.nist.gov/vuln/detail/CVE-2022-36763
Upstream-patches:
https://github.com/tianocore/edk2/commit/224446543206450ddb5830e6abd026d61d3c7f4b
https://github.com/tianocore/edk2/commit/4776a1b39ee08fc45c70c1eab5a0195f325000d3
https://github.com/tianocore/edk2/commit/1ddcb9fc6b4164e882687b031e8beacfcf7df29e
Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
---
.../ovmf/ovmf/CVE-2022-36763-0001.patch | 985 ++++++++++++++++++
.../ovmf/ovmf/CVE-2022-36763-0002.patch | 889 ++++++++++++++++
.../ovmf/ovmf/CVE-2022-36763-0003.patch | 55 +
meta/recipes-core/ovmf/ovmf_git.bb | 3 +
4 files changed, 1932 insertions(+)
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0001.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0002.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0003.patch
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0001.patch b/meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0001.patch
new file mode 100644
index 0000000000..93cefe7740
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0001.patch
@@ -0,0 +1,985 @@
+From 224446543206450ddb5830e6abd026d61d3c7f4b Mon Sep 17 00:00:00 2001
+From: "Douglas Flick [MSFT]" <doug.edk2@gmail.com>
+Date: Fri, 12 Jan 2024 02:16:01 +0800
+Subject: [PATCH] SecurityPkg: DxeTpm2MeasureBootLib: SECURITY PATCH 4117 - CVE
+ 2022-36763
+
+This commit contains the patch files and tests for DxeTpm2MeasureBootLib
+CVE 2022-36763.
+
+Cc: Jiewen Yao <jiewen.yao@intel.com>
+
+Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
+
+CVE: CVE-2022-36763
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/224446543206450ddb5830e6abd026d61d3c7f4b]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ .../DxeTpm2MeasureBootLib.c | 69 ++--
+ .../DxeTpm2MeasureBootLib.inf | 4 +-
+ .../DxeTpm2MeasureBootLibSanitization.c | 275 ++++++++++++++++
+ .../DxeTpm2MeasureBootLibSanitization.h | 113 +++++++
+ .../DxeTpm2MeasureBootLibSanitizationTest.c | 303 ++++++++++++++++++
+ ...Tpm2MeasureBootLibSanitizationTestHost.inf | 28 ++
+ SecurityPkg/SecurityPkg.ci.yaml | 1 +
+ 7 files changed, 763 insertions(+), 30 deletions(-)
+ create mode 100644 SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c
+ create mode 100644 SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h
+ create mode 100644 SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c
+ create mode 100644 SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTestHost.inf
+
+diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c
+index 36a256a7af..0475103d6e 100644
+--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c
++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c
+@@ -20,6 +20,8 @@ Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
++Copyright (c) Microsoft Corporation.<BR>
++SPDX-License-Identifier: BSD-2-Clause-Patent
+ **/
+
+ #include <PiDxe.h>
+@@ -44,6 +46,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
+ #include <Library/HobLib.h>
+ #include <Protocol/CcMeasurement.h>
+
++#include "DxeTpm2MeasureBootLibSanitization.h"
++
+ typedef struct {
+ EFI_TCG2_PROTOCOL *Tcg2Protocol;
+ EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol;
+@@ -144,10 +148,11 @@ Tcg2MeasureGptTable (
+ EFI_TCG2_EVENT *Tcg2Event;
+ EFI_CC_EVENT *CcEvent;
+ EFI_GPT_DATA *GptData;
+- UINT32 EventSize;
++ UINT32 TcgEventSize;
+ EFI_TCG2_PROTOCOL *Tcg2Protocol;
+ EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol;
+ EFI_CC_MR_INDEX MrIndex;
++ UINT32 AllocSize;
+
+ if (mTcg2MeasureGptCount > 0) {
+ return EFI_SUCCESS;
+@@ -195,25 +200,22 @@ Tcg2MeasureGptTable (
+ BlockIo->Media->BlockSize,
+ (UINT8 *)PrimaryHeader
+ );
+- if (EFI_ERROR (Status)) {
+- DEBUG ((DEBUG_ERROR, "Failed to Read Partition Table Header!\n"));
++ if (EFI_ERROR (Status) || EFI_ERROR (SanitizeEfiPartitionTableHeader (PrimaryHeader, BlockIo))) {
++ DEBUG ((DEBUG_ERROR, "Failed to read Partition Table Header or invalid Partition Table Header!\n"));
+ FreePool (PrimaryHeader);
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+- // PrimaryHeader->SizeOfPartitionEntry should not be zero
++ // Read the partition entry.
+ //
+- if (PrimaryHeader->SizeOfPartitionEntry == 0) {
+- DEBUG ((DEBUG_ERROR, "SizeOfPartitionEntry should not be zero!\n"));
++ Status = SanitizePrimaryHeaderAllocationSize (PrimaryHeader, &AllocSize);
++ if (EFI_ERROR (Status)) {
+ FreePool (PrimaryHeader);
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+- //
+- // Read the partition entry.
+- //
+- EntryPtr = (UINT8 *)AllocatePool (PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry);
++ EntryPtr = (UINT8 *)AllocatePool (AllocSize);
+ if (EntryPtr == NULL) {
+ FreePool (PrimaryHeader);
+ return EFI_OUT_OF_RESOURCES;
+@@ -223,7 +225,7 @@ Tcg2MeasureGptTable (
+ DiskIo,
+ BlockIo->Media->MediaId,
+ MultU64x32 (PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),
+- PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry,
++ AllocSize,
+ EntryPtr
+ );
+ if (EFI_ERROR (Status)) {
+@@ -248,16 +250,21 @@ Tcg2MeasureGptTable (
+ //
+ // Prepare Data for Measurement (CcProtocol and Tcg2Protocol)
+ //
+- EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions)
+- + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry);
+- EventPtr = (UINT8 *)AllocateZeroPool (EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event));
++ Status = SanitizePrimaryHeaderGptEventSize (PrimaryHeader, NumberOfPartition, &TcgEventSize);
++ if (EFI_ERROR (Status)) {
++ FreePool (PrimaryHeader);
++ FreePool (EntryPtr);
++ return EFI_DEVICE_ERROR;
++ }
++
++ EventPtr = (UINT8 *)AllocateZeroPool (TcgEventSize);
+ if (EventPtr == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ Tcg2Event = (EFI_TCG2_EVENT *)EventPtr;
+- Tcg2Event->Size = EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event);
++ Tcg2Event->Size = TcgEventSize;
+ Tcg2Event->Header.HeaderSize = sizeof (EFI_TCG2_EVENT_HEADER);
+ Tcg2Event->Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION;
+ Tcg2Event->Header.PCRIndex = 5;
+@@ -310,7 +317,7 @@ Tcg2MeasureGptTable (
+ CcProtocol,
+ 0,
+ (EFI_PHYSICAL_ADDRESS)(UINTN)(VOID *)GptData,
+- (UINT64)EventSize,
++ (UINT64)TcgEventSize - OFFSET_OF (EFI_TCG2_EVENT, Event),
+ CcEvent
+ );
+ if (!EFI_ERROR (Status)) {
+@@ -326,7 +333,7 @@ Tcg2MeasureGptTable (
+ Tcg2Protocol,
+ 0,
+ (EFI_PHYSICAL_ADDRESS)(UINTN)(VOID *)GptData,
+- (UINT64)EventSize,
++ (UINT64)TcgEventSize - OFFSET_OF (EFI_TCG2_EVENT, Event),
+ Tcg2Event
+ );
+ if (!EFI_ERROR (Status)) {
+@@ -443,11 +450,13 @@ Tcg2MeasurePeImage (
+ Tcg2Event->Header.PCRIndex = 2;
+ break;
+ default:
+- DEBUG ((
+- DEBUG_ERROR,
+- "Tcg2MeasurePeImage: Unknown subsystem type %d",
+- ImageType
+- ));
++ DEBUG (
++ (
++ DEBUG_ERROR,
++ "Tcg2MeasurePeImage: Unknown subsystem type %d",
++ ImageType
++ )
++ );
+ goto Finish;
+ }
+
+@@ -515,7 +524,7 @@ Finish:
+
+ @param MeasureBootProtocols Pointer to the located measure boot protocol instances.
+
+- @retval EFI_SUCCESS Sucessfully locate the measure boot protocol instances (at least one instance).
++ @retval EFI_SUCCESS Successfully locate the measure boot protocol instances (at least one instance).
+ @retval EFI_UNSUPPORTED Measure boot is not supported.
+ **/
+ EFI_STATUS
+@@ -646,12 +655,14 @@ DxeTpm2MeasureBootHandler (
+ return EFI_SUCCESS;
+ }
+
+- DEBUG ((
+- DEBUG_INFO,
+- "Tcg2Protocol = %p, CcMeasurementProtocol = %p\n",
+- MeasureBootProtocols.Tcg2Protocol,
+- MeasureBootProtocols.CcProtocol
+- ));
++ DEBUG (
++ (
++ DEBUG_INFO,
++ "Tcg2Protocol = %p, CcMeasurementProtocol = %p\n",
++ MeasureBootProtocols.Tcg2Protocol,
++ MeasureBootProtocols.CcProtocol
++ )
++ );
+
+ //
+ // Copy File Device Path
+diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf
+index 6dca79a20c..28995f438d 100644
+--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf
++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf
+@@ -37,6 +37,8 @@
+
+ [Sources]
+ DxeTpm2MeasureBootLib.c
++ DxeTpm2MeasureBootLibSanitization.c
++ DxeTpm2MeasureBootLibSanitization.h
+
+ [Packages]
+ MdePkg/MdePkg.dec
+@@ -46,6 +48,7 @@
+
+ [LibraryClasses]
+ BaseMemoryLib
++ SafeIntLib
+ DebugLib
+ MemoryAllocationLib
+ DevicePathLib
+@@ -65,4 +68,3 @@
+ gEfiFirmwareVolumeBlockProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiBlockIoProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiDiskIoProtocolGuid ## SOMETIMES_CONSUMES
+-
+diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c
+new file mode 100644
+index 0000000000..e2309655d3
+--- /dev/null
++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c
+@@ -0,0 +1,275 @@
++/** @file
++ The library instance provides security service of TPM2 measure boot and
++ Confidential Computing (CC) measure boot.
++
++ Caution: This file requires additional review when modified.
++ This library will have external input - PE/COFF image and GPT partition.
++ This external input must be validated carefully to avoid security issue like
++ buffer overflow, integer overflow.
++
++ This file will pull out the validation logic from the following functions, in an
++ attempt to validate the untrusted input in the form of unit tests
++
++ These are those functions:
++
++ DxeTpm2MeasureBootLibImageRead() function will make sure the PE/COFF image content
++ read is within the image buffer.
++
++ Tcg2MeasureGptTable() function will receive untrusted GPT partition table, and parse
++ partition data carefully.
++
++ Copyright (c) Microsoft Corporation.<BR>
++ SPDX-License-Identifier: BSD-2-Clause-Patent
++**/
++#include <Uefi.h>
++#include <Uefi/UefiSpec.h>
++#include <Library/SafeIntLib.h>
++#include <Library/UefiLib.h>
++#include <Library/DebugLib.h>
++#include <Library/BaseLib.h>
++#include <IndustryStandard/UefiTcgPlatform.h>
++#include <Protocol/BlockIo.h>
++#include <Library/MemoryAllocationLib.h>
++
++#include "DxeTpm2MeasureBootLibSanitization.h"
++
++#define GPT_HEADER_REVISION_V1 0x00010000
++
++/**
++ This function will validate the EFI_PARTITION_TABLE_HEADER structure is safe to parse
++ However this function will not attempt to verify the validity of the GPT partition
++ It will check the following:
++ - Signature
++ - Revision
++ - AlternateLBA
++ - FirstUsableLBA
++ - LastUsableLBA
++ - PartitionEntryLBA
++ - NumberOfPartitionEntries
++ - SizeOfPartitionEntry
++ - BlockIo
++
++ @param[in] PrimaryHeader
++ Pointer to the EFI_PARTITION_TABLE_HEADER structure.
++
++ @param[in] BlockIo
++ Pointer to the EFI_BLOCK_IO_PROTOCOL structure.
++
++ @retval EFI_SUCCESS
++ The EFI_PARTITION_TABLE_HEADER structure is valid.
++
++ @retval EFI_INVALID_PARAMETER
++ The EFI_PARTITION_TABLE_HEADER structure is invalid.
++**/
++EFI_STATUS
++EFIAPI
++SanitizeEfiPartitionTableHeader (
++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader,
++ IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo
++ )
++{
++ //
++ // Verify that the input parameters are safe to use
++ //
++ if (PrimaryHeader == NULL) {
++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header!\n"));
++ return EFI_INVALID_PARAMETER;
++ }
++
++ if ((BlockIo == NULL) || (BlockIo->Media == NULL)) {
++ DEBUG ((DEBUG_ERROR, "Invalid BlockIo!\n"));
++ return EFI_INVALID_PARAMETER;
++ }
++
++ //
++ // The signature must be EFI_PTAB_HEADER_ID ("EFI PART" in ASCII)
++ //
++ if (PrimaryHeader->Header.Signature != EFI_PTAB_HEADER_ID) {
++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header!\n"));
++ return EFI_DEVICE_ERROR;
++ }
++
++ //
++ // The version must be GPT_HEADER_REVISION_V1 (0x00010000)
++ //
++ if (PrimaryHeader->Header.Revision != GPT_HEADER_REVISION_V1) {
++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header Revision!\n"));
++ return EFI_DEVICE_ERROR;
++ }
++
++ //
++ // The HeaderSize must be greater than or equal to 92 and must be less than or equal to the logical block size
++ //
++ if ((PrimaryHeader->Header.HeaderSize < sizeof (EFI_PARTITION_TABLE_HEADER)) || (PrimaryHeader->Header.HeaderSize > BlockIo->Media->BlockSize)) {
++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header HeaderSize!\n"));
++ return EFI_DEVICE_ERROR;
++ }
++
++ //
++ // The partition entries should all be before the first usable block
++ //
++ if (PrimaryHeader->FirstUsableLBA <= PrimaryHeader->PartitionEntryLBA) {
++ DEBUG ((DEBUG_ERROR, "GPT PartitionEntryLBA is not less than FirstUsableLBA!\n"));
++ return EFI_DEVICE_ERROR;
++ }
++
++ //
++ // Check that the PartitionEntryLBA greater than the Max LBA
++ // This will be used later for multiplication
++ //
++ if (PrimaryHeader->PartitionEntryLBA > DivU64x32 (MAX_UINT64, BlockIo->Media->BlockSize)) {
++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header PartitionEntryLBA!\n"));
++ return EFI_DEVICE_ERROR;
++ }
++
++ //
++ // Check that the number of partition entries is greater than zero
++ //
++ if (PrimaryHeader->NumberOfPartitionEntries == 0) {
++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header NumberOfPartitionEntries!\n"));
++ return EFI_DEVICE_ERROR;
++ }
++
++ //
++ // SizeOfPartitionEntry must be 128, 256, 512... improper size may lead to accessing uninitialized memory
++ //
++ if ((PrimaryHeader->SizeOfPartitionEntry < 128) || ((PrimaryHeader->SizeOfPartitionEntry & (PrimaryHeader->SizeOfPartitionEntry - 1)) != 0)) {
++ DEBUG ((DEBUG_ERROR, "SizeOfPartitionEntry shall be set to a value of 128 x 2^n where n is an integer greater than or equal to zero (e.g., 128, 256, 512, etc.)!\n"));
++ return EFI_DEVICE_ERROR;
++ }
++
++ //
++ // This check is to prevent overflow when calculating the allocation size for the partition entries
++ // This check will be used later for multiplication
++ //
++ if (PrimaryHeader->NumberOfPartitionEntries > DivU64x32 (MAX_UINT64, PrimaryHeader->SizeOfPartitionEntry)) {
++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header NumberOfPartitionEntries!\n"));
++ return EFI_DEVICE_ERROR;
++ }
++
++ return EFI_SUCCESS;
++}
++
++/**
++ This function will validate that the allocation size from the primary header is sane
++ It will check the following:
++ - AllocationSize does not overflow
++
++ @param[in] PrimaryHeader
++ Pointer to the EFI_PARTITION_TABLE_HEADER structure.
++
++ @param[out] AllocationSize
++ Pointer to the allocation size.
++
++ @retval EFI_SUCCESS
++ The allocation size is valid.
++
++ @retval EFI_OUT_OF_RESOURCES
++ The allocation size is invalid.
++**/
++EFI_STATUS
++EFIAPI
++SanitizePrimaryHeaderAllocationSize (
++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader,
++ OUT UINT32 *AllocationSize
++ )
++{
++ EFI_STATUS Status;
++
++ if (PrimaryHeader == NULL) {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ if (AllocationSize == NULL) {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ //
++ // Replacing logic:
++ // PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry;
++ //
++ Status = SafeUint32Mult (PrimaryHeader->NumberOfPartitionEntries, PrimaryHeader->SizeOfPartitionEntry, AllocationSize);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "Allocation Size would have overflowed!\n"));
++ return EFI_BAD_BUFFER_SIZE;
++ }
++
++ return EFI_SUCCESS;
++}
++
++/**
++ This function will validate that the Gpt Event Size calculated from the primary header is sane
++ It will check the following:
++ - EventSize does not overflow
++
++ Important: This function includes the entire length of the allocated space, including
++ (sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event)) . When hashing the buffer allocated with this
++ size, the caller must subtract the size of the (sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event))
++ from the size of the buffer before hashing.
++
++ @param[in] PrimaryHeader - Pointer to the EFI_PARTITION_TABLE_HEADER structure.
++ @param[in] NumberOfPartition - Number of partitions.
++ @param[out] EventSize - Pointer to the event size.
++
++ @retval EFI_SUCCESS
++ The event size is valid.
++
++ @retval EFI_OUT_OF_RESOURCES
++ Overflow would have occurred.
++
++ @retval EFI_INVALID_PARAMETER
++ One of the passed parameters was invalid.
++**/
++EFI_STATUS
++SanitizePrimaryHeaderGptEventSize (
++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader,
++ IN UINTN NumberOfPartition,
++ OUT UINT32 *EventSize
++ )
++{
++ EFI_STATUS Status;
++ UINT32 SafeNumberOfPartitions;
++
++ if (PrimaryHeader == NULL) {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ if (EventSize == NULL) {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ //
++ // We shouldn't even attempt to perform the multiplication if the number of partitions is greater than the maximum value of UINT32
++ //
++ Status = SafeUintnToUint32 (NumberOfPartition, &SafeNumberOfPartitions);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "NumberOfPartition would have overflowed!\n"));
++ return EFI_INVALID_PARAMETER;
++ }
++
++ //
++ // Replacing logic:
++ // (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions) + NumberOfPartition * PrimaryHeader.SizeOfPartitionEntry);
++ //
++ Status = SafeUint32Mult (SafeNumberOfPartitions, PrimaryHeader->SizeOfPartitionEntry, EventSize);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "Event Size would have overflowed!\n"));
++ return EFI_BAD_BUFFER_SIZE;
++ }
++
++ //
++ // Replacing logic:
++ // *EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event);
++ //
++ Status = SafeUint32Add (
++ OFFSET_OF (EFI_TCG2_EVENT, Event) + OFFSET_OF (EFI_GPT_DATA, Partitions),
++ *EventSize,
++ EventSize
++ );
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "Event Size would have overflowed because of GPTData!\n"));
++ return EFI_BAD_BUFFER_SIZE;
++ }
++
++ return EFI_SUCCESS;
++}
+diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h
+new file mode 100644
+index 0000000000..048b738987
+--- /dev/null
++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h
+@@ -0,0 +1,113 @@
++/** @file
++ This file includes the function prototypes for the sanitization functions.
++
++ These are those functions:
++
++ DxeTpm2MeasureBootLibImageRead() function will make sure the PE/COFF image content
++ read is within the image buffer.
++
++ Tcg2MeasureGptTable() function will receive untrusted GPT partition table, and parse
++ partition data carefully.
++
++ Copyright (c) Microsoft Corporation.<BR>
++ SPDX-License-Identifier: BSD-2-Clause-Patent
++
++**/
++
++#ifndef DXE_TPM2_MEASURE_BOOT_LIB_SANITATION_
++#define DXE_TPM2_MEASURE_BOOT_LIB_SANITATION_
++
++#include <Uefi.h>
++#include <Uefi/UefiSpec.h>
++#include <Protocol/BlockIo.h>
++#include <IndustryStandard/UefiTcgPlatform.h>
++#include <Protocol/Tcg2Protocol.h>
++
++/**
++ This function will validate the EFI_PARTITION_TABLE_HEADER structure is safe to parse
++ However this function will not attempt to verify the validity of the GPT partition
++ It will check the following:
++ - Signature
++ - Revision
++ - AlternateLBA
++ - FirstUsableLBA
++ - LastUsableLBA
++ - PartitionEntryLBA
++ - NumberOfPartitionEntries
++ - SizeOfPartitionEntry
++ - BlockIo
++
++ @param[in] PrimaryHeader
++ Pointer to the EFI_PARTITION_TABLE_HEADER structure.
++
++ @param[in] BlockIo
++ Pointer to the EFI_BLOCK_IO_PROTOCOL structure.
++
++ @retval EFI_SUCCESS
++ The EFI_PARTITION_TABLE_HEADER structure is valid.
++
++ @retval EFI_INVALID_PARAMETER
++ The EFI_PARTITION_TABLE_HEADER structure is invalid.
++**/
++EFI_STATUS
++EFIAPI
++SanitizeEfiPartitionTableHeader (
++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader,
++ IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo
++ );
++
++/**
++ This function will validate that the allocation size from the primary header is sane
++ It will check the following:
++ - AllocationSize does not overflow
++
++ @param[in] PrimaryHeader
++ Pointer to the EFI_PARTITION_TABLE_HEADER structure.
++
++ @param[out] AllocationSize
++ Pointer to the allocation size.
++
++ @retval EFI_SUCCESS
++ The allocation size is valid.
++
++ @retval EFI_OUT_OF_RESOURCES
++ The allocation size is invalid.
++**/
++EFI_STATUS
++EFIAPI
++SanitizePrimaryHeaderAllocationSize (
++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader,
++ OUT UINT32 *AllocationSize
++ );
++
++/**
++ This function will validate that the Gpt Event Size calculated from the primary header is sane
++ It will check the following:
++ - EventSize does not overflow
++
++ Important: This function includes the entire length of the allocated space, including
++ (sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event)) . When hashing the buffer allocated with this
++ size, the caller must subtract the size of the (sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event))
++ from the size of the buffer before hashing.
++
++ @param[in] PrimaryHeader - Pointer to the EFI_PARTITION_TABLE_HEADER structure.
++ @param[in] NumberOfPartition - Number of partitions.
++ @param[out] EventSize - Pointer to the event size.
++
++ @retval EFI_SUCCESS
++ The event size is valid.
++
++ @retval EFI_OUT_OF_RESOURCES
++ Overflow would have occurred.
++
++ @retval EFI_INVALID_PARAMETER
++ One of the passed parameters was invalid.
++**/
++EFI_STATUS
++SanitizePrimaryHeaderGptEventSize (
++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader,
++ IN UINTN NumberOfPartition,
++ OUT UINT32 *EventSize
++ );
++
++#endif // DXE_TPM2_MEASURE_BOOT_LIB_SANITATION_
+diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c
+new file mode 100644
+index 0000000000..3eb9763e3c
+--- /dev/null
++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c
+@@ -0,0 +1,303 @@
++/** @file
++ This file includes the unit test cases for the DxeTpm2MeasureBootLibSanitizationTest.c.
++
++ Copyright (c) Microsoft Corporation.<BR>
++ SPDX-License-Identifier: BSD-2-Clause-Patent
++**/
++
++#include <Uefi.h>
++#include <Library/UefiLib.h>
++#include <Library/DebugLib.h>
++#include <Library/UnitTestLib.h>
++#include <Protocol/BlockIo.h>
++#include <Library/MemoryAllocationLib.h>
++#include <Library/BaseMemoryLib.h>
++#include <IndustryStandard/UefiTcgPlatform.h>
++#include <Protocol/Tcg2Protocol.h>
++
++#include "../DxeTpm2MeasureBootLibSanitization.h"
++
++#define UNIT_TEST_NAME "DxeTpm2MeasureBootLibSanitizationTest"
++#define UNIT_TEST_VERSION "1.0"
++
++#define DEFAULT_PRIMARY_TABLE_HEADER_REVISION 0x00010000
++#define DEFAULT_PRIMARY_TABLE_HEADER_NUMBER_OF_PARTITION_ENTRIES 1
++#define DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY 128
++
++/**
++ This function tests the SanitizeEfiPartitionTableHeader function.
++ It's intent is to test that a malicious EFI_PARTITION_TABLE_HEADER
++ structure will not cause undefined or unexpected behavior.
++
++ In general the TPM should still be able to measure the data, but
++ be the header should be sanitized to prevent any unexpected behavior.
++
++ @param[in] Context The unit test context.
++
++ @retval UNIT_TEST_PASSED The test passed.
++ @retval UNIT_TEST_ERROR_TEST_FAILED The test failed.
++**/
++UNIT_TEST_STATUS
++EFIAPI
++TestSanitizeEfiPartitionTableHeader (
++ IN UNIT_TEST_CONTEXT Context
++ )
++{
++ EFI_STATUS Status;
++ EFI_PARTITION_TABLE_HEADER PrimaryHeader;
++ EFI_BLOCK_IO_PROTOCOL BlockIo;
++ EFI_BLOCK_IO_MEDIA BlockMedia;
++
++ // Generate EFI_BLOCK_IO_MEDIA test data
++ BlockMedia.MediaId = 1;
++ BlockMedia.RemovableMedia = FALSE;
++ BlockMedia.MediaPresent = TRUE;
++ BlockMedia.LogicalPartition = FALSE;
++ BlockMedia.ReadOnly = FALSE;
++ BlockMedia.WriteCaching = FALSE;
++ BlockMedia.BlockSize = 512;
++ BlockMedia.IoAlign = 1;
++ BlockMedia.LastBlock = 0;
++
++ // Generate EFI_BLOCK_IO_PROTOCOL test data
++ BlockIo.Revision = 1;
++ BlockIo.Media = &BlockMedia;
++ BlockIo.Reset = NULL;
++ BlockIo.ReadBlocks = NULL;
++ BlockIo.WriteBlocks = NULL;
++ BlockIo.FlushBlocks = NULL;
++
++ // Geneate EFI_PARTITION_TABLE_HEADER test data
++ PrimaryHeader.Header.Signature = EFI_PTAB_HEADER_ID;
++ PrimaryHeader.Header.Revision = DEFAULT_PRIMARY_TABLE_HEADER_REVISION;
++ PrimaryHeader.Header.HeaderSize = sizeof (EFI_PARTITION_TABLE_HEADER);
++ PrimaryHeader.MyLBA = 1;
++ PrimaryHeader.AlternateLBA = 2;
++ PrimaryHeader.FirstUsableLBA = 3;
++ PrimaryHeader.LastUsableLBA = 4;
++ PrimaryHeader.PartitionEntryLBA = 5;
++ PrimaryHeader.NumberOfPartitionEntries = DEFAULT_PRIMARY_TABLE_HEADER_NUMBER_OF_PARTITION_ENTRIES;
++ PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;
++ PrimaryHeader.PartitionEntryArrayCRC32 = 0; // Purposely invalid
++
++ // Calculate the CRC32 of the PrimaryHeader
++ PrimaryHeader.Header.CRC32 = CalculateCrc32 ((UINT8 *)&PrimaryHeader, PrimaryHeader.Header.HeaderSize);
++
++ // Test that a normal PrimaryHeader passes validation
++ Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo);
++ UT_ASSERT_NOT_EFI_ERROR (Status);
++
++ // Test that when number of partition entries is 0, the function returns EFI_DEVICE_ERROR
++ // Should print "Invalid Partition Table Header NumberOfPartitionEntries!""
++ PrimaryHeader.NumberOfPartitionEntries = 0;
++ Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo);
++ UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR);
++ PrimaryHeader.NumberOfPartitionEntries = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;
++
++ // Test that when the header size is too small, the function returns EFI_DEVICE_ERROR
++ // Should print "Invalid Partition Table Header Size!"
++ PrimaryHeader.Header.HeaderSize = 0;
++ Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo);
++ UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR);
++ PrimaryHeader.Header.HeaderSize = sizeof (EFI_PARTITION_TABLE_HEADER);
++
++ // Test that when the SizeOfPartitionEntry is too small, the function returns EFI_DEVICE_ERROR
++ // should print: "SizeOfPartitionEntry shall be set to a value of 128 x 2^n where n is an integer greater than or equal to zero (e.g., 128, 256, 512, etc.)!"
++ PrimaryHeader.SizeOfPartitionEntry = 1;
++ Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo);
++ UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR);
++
++ DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));
++
++ return UNIT_TEST_PASSED;
++}
++
++/**
++ This function tests the SanitizePrimaryHeaderAllocationSize function.
++ It's intent is to test that the untrusted input from a EFI_PARTITION_TABLE_HEADER
++ structure will not cause an overflow when calculating the allocation size.
++
++ @param[in] Context The unit test context.
++
++ @retval UNIT_TEST_PASSED The test passed.
++ @retval UNIT_TEST_ERROR_TEST_FAILED The test failed.
++**/
++UNIT_TEST_STATUS
++EFIAPI
++TestSanitizePrimaryHeaderAllocationSize (
++ IN UNIT_TEST_CONTEXT Context
++ )
++{
++ UINT32 AllocationSize;
++
++ EFI_STATUS Status;
++ EFI_PARTITION_TABLE_HEADER PrimaryHeader;
++
++ // Test that a normal PrimaryHeader passes validation
++ PrimaryHeader.NumberOfPartitionEntries = 5;
++ PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;
++
++ Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);
++ UT_ASSERT_NOT_EFI_ERROR (Status);
++
++ // Test that the allocation size is correct compared to the existing logic
++ UT_ASSERT_EQUAL (AllocationSize, PrimaryHeader.NumberOfPartitionEntries * PrimaryHeader.SizeOfPartitionEntry);
++
++ // Test that an overflow is detected
++ PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32;
++ PrimaryHeader.SizeOfPartitionEntry = 5;
++ Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);
++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
++
++ // Test the inverse
++ PrimaryHeader.NumberOfPartitionEntries = 5;
++ PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32;
++ Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);
++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
++
++ // Test the worst case scenario
++ PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32;
++ PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32;
++ Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);
++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
++
++ DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));
++
++ return UNIT_TEST_PASSED;
++}
++
++/**
++ This function tests the SanitizePrimaryHeaderGptEventSize function.
++ It's intent is to test that the untrusted input from a EFI_GPT_DATA structure
++ will not cause an overflow when calculating the event size.
++
++ @param[in] Context The unit test context.
++
++ @retval UNIT_TEST_PASSED The test passed.
++ @retval UNIT_TEST_ERROR_TEST_FAILED The test failed.
++**/
++UNIT_TEST_STATUS
++EFIAPI
++TestSanitizePrimaryHeaderGptEventSize (
++ IN UNIT_TEST_CONTEXT Context
++ )
++{
++ UINT32 EventSize;
++ UINT32 ExistingLogicEventSize;
++ EFI_STATUS Status;
++ EFI_PARTITION_TABLE_HEADER PrimaryHeader;
++ UINTN NumberOfPartition;
++ EFI_GPT_DATA *GptData;
++ EFI_TCG2_EVENT *Tcg2Event;
++
++ Tcg2Event = NULL;
++ GptData = NULL;
++
++ // Test that a normal PrimaryHeader passes validation
++ PrimaryHeader.NumberOfPartitionEntries = 5;
++ PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;
++
++ // set the number of partitions
++ NumberOfPartition = 13;
++
++ // that the primary event size is correct
++ Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize);
++ UT_ASSERT_NOT_EFI_ERROR (Status);
++
++ // Calculate the existing logic event size
++ ExistingLogicEventSize = (UINT32)(OFFSET_OF (EFI_TCG2_EVENT, Event) + OFFSET_OF (EFI_GPT_DATA, Partitions)
++ + NumberOfPartition * PrimaryHeader.SizeOfPartitionEntry);
++
++ // Check that the event size is correct
++ UT_ASSERT_EQUAL (EventSize, ExistingLogicEventSize);
++
++ // Tests that the primary event size may not overflow
++ Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, MAX_UINT32, &EventSize);
++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
++
++ // Test that the size of partition entries may not overflow
++ PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32;
++ Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize);
++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
++
++ DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));
++
++ return UNIT_TEST_PASSED;
++}
++
++// *--------------------------------------------------------------------*
++// * Unit Test Code Main Function
++// *--------------------------------------------------------------------*
++
++/**
++ This function acts as the entry point for the unit tests.
++
++ @retval UNIT_TEST_PASSED The test passed.
++ @retval UNIT_TEST_ERROR_TEST_FAILED The test failed.
++ @retval others The test failed.
++**/
++EFI_STATUS
++EFIAPI
++UefiTestMain (
++ VOID
++ )
++{
++ EFI_STATUS Status;
++ UNIT_TEST_FRAMEWORK_HANDLE Framework;
++ UNIT_TEST_SUITE_HANDLE Tcg2MeasureBootLibValidationTestSuite;
++
++ Framework = NULL;
++
++ DEBUG ((DEBUG_INFO, "%a: TestMain() - Start\n", UNIT_TEST_NAME));
++
++ Status = InitUnitTestFramework (&Framework, UNIT_TEST_NAME, gEfiCallerBaseName, UNIT_TEST_VERSION);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "%a: Failed in InitUnitTestFramework. Status = %r\n", UNIT_TEST_NAME, Status));
++ goto EXIT;
++ }
++
++ Status = CreateUnitTestSuite (&Tcg2MeasureBootLibValidationTestSuite, Framework, "Tcg2MeasureBootLibValidationTestSuite", "Common.Tcg2MeasureBootLibValidation", NULL, NULL);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "%s: Failed in CreateUnitTestSuite for Tcg2MeasureBootLibValidationTestSuite\n", UNIT_TEST_NAME));
++ Status = EFI_OUT_OF_RESOURCES;
++ goto EXIT;
++ }
++
++ // -----------Suite---------------------------------Description----------------------------Class----------------------------------Test Function------------------------Pre---Clean-Context
++ AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Validating EFI Partition Table", "Common.Tcg2MeasureBootLibValidation", TestSanitizeEfiPartitionTableHeader, NULL, NULL, NULL);
++ AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Primary header gpt event checks for overflow", "Common.Tcg2MeasureBootLibValidation", TestSanitizePrimaryHeaderAllocationSize, NULL, NULL, NULL);
++ AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Primary header allocation size checks for overflow", "Common.Tcg2MeasureBootLibValidation", TestSanitizePrimaryHeaderGptEventSize, NULL, NULL, NULL);
++
++ Status = RunAllTestSuites (Framework);
++
++EXIT:
++ if (Framework != NULL) {
++ FreeUnitTestFramework (Framework);
++ }
++
++ DEBUG ((DEBUG_INFO, "%a: TestMain() - End\n", UNIT_TEST_NAME));
++ return Status;
++}
++
++///
++/// Avoid ECC error for function name that starts with lower case letter
++///
++#define DxeTpm2MeasureBootLibUnitTestMain main
++
++/**
++ Standard POSIX C entry point for host based unit test execution.
++
++ @param[in] Argc Number of arguments
++ @param[in] Argv Array of pointers to arguments
++
++ @retval 0 Success
++ @retval other Error
++**/
++INT32
++DxeTpm2MeasureBootLibUnitTestMain (
++ IN INT32 Argc,
++ IN CHAR8 *Argv[]
++ )
++{
++ return (INT32)UefiTestMain ();
++}
+diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTestHost.inf b/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTestHost.inf
+new file mode 100644
+index 0000000000..2999aa2a44
+--- /dev/null
++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTestHost.inf
+@@ -0,0 +1,28 @@
++## @file
++# This file builds the unit tests for DxeTpm2MeasureBootLib
++#
++# Copyright (C) Microsoft Corporation.<BR>
++# SPDX-License-Identifier: BSD-2-Clause-Patent
++##
++
++[Defines]
++ INF_VERSION = 0x00010006
++ BASE_NAME = DxeTpm2MeasuredBootLibTest
++ FILE_GUID = 144d757f-d423-484e-9309-a23695fad5bd
++ MODULE_TYPE = HOST_APPLICATION
++ VERSION_STRING = 1.0
++ ENTRY_POINT = main
++
++[Sources]
++ DxeTpm2MeasureBootLibSanitizationTest.c
++ ../DxeTpm2MeasureBootLibSanitization.c
++
++[Packages]
++ MdePkg/MdePkg.dec
++
++[LibraryClasses]
++ BaseLib
++ DebugLib
++ UnitTestLib
++ PrintLib
++ SafeIntLib
+diff --git a/SecurityPkg/SecurityPkg.ci.yaml b/SecurityPkg/SecurityPkg.ci.yaml
+index 7912142398..da811fdf93 100644
+--- a/SecurityPkg/SecurityPkg.ci.yaml
++++ b/SecurityPkg/SecurityPkg.ci.yaml
+@@ -15,6 +15,7 @@
+ ## "<ErrorID>", "<KeyWord>"
+ ## ]
+ "ExceptionList": [
++ "8001", "DxeTpm2MeasureBootLibUnitTestMain",
+ ],
+ ## Both file path and directory path are accepted.
+ "IgnoreFiles": [
+--
+2.40.0
+
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0002.patch b/meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0002.patch
new file mode 100644
index 0000000000..6c20cc305e
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0002.patch
@@ -0,0 +1,889 @@
+From 4776a1b39ee08fc45c70c1eab5a0195f325000d3 Mon Sep 17 00:00:00 2001
+From: "Douglas Flick [MSFT]" <doug.edk2@gmail.com>
+Date: Fri, 12 Jan 2024 02:16:02 +0800
+Subject: [PATCH] SecurityPkg: DxeTpmMeasureBootLib: SECURITY PATCH 4117 - CVE
+ 2022-36763
+
+This commit contains the patch files and tests for DxeTpmMeasureBootLib
+CVE 2022-36763.
+
+Cc: Jiewen Yao <jiewen.yao@intel.com>
+
+Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
+Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
+
+CVE: CVE-2022-36763
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/4776a1b39ee08fc45c70c1eab5a0195f325000d3]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ .../DxeTpmMeasureBootLib.c | 40 ++-
+ .../DxeTpmMeasureBootLib.inf | 4 +-
+ .../DxeTpmMeasureBootLibSanitization.c | 241 ++++++++++++++
+ .../DxeTpmMeasureBootLibSanitization.h | 114 +++++++
+ .../DxeTpmMeasureBootLibSanitizationTest.c | 301 ++++++++++++++++++
+ ...eTpmMeasureBootLibSanitizationTestHost.inf | 28 ++
+ SecurityPkg/SecurityPkg.ci.yaml | 1 +
+ 7 files changed, 715 insertions(+), 14 deletions(-)
+ create mode 100644 SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c
+ create mode 100644 SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h
+ create mode 100644 SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c
+ create mode 100644 SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTestHost.inf
+
+diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c
+index 220393dd2b..669ab19134 100644
+--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c
++++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c
+@@ -18,6 +18,8 @@
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
++Copyright (c) Microsoft Corporation.<BR>
++SPDX-License-Identifier: BSD-2-Clause-Patent
+ **/
+
+ #include <PiDxe.h>
+@@ -40,6 +42,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
+ #include <Library/SecurityManagementLib.h>
+ #include <Library/HobLib.h>
+
++#include "DxeTpmMeasureBootLibSanitization.h"
++
+ //
+ // Flag to check GPT partition. It only need be measured once.
+ //
+@@ -136,6 +140,9 @@ TcgMeasureGptTable (
+ UINT32 EventSize;
+ UINT32 EventNumber;
+ EFI_PHYSICAL_ADDRESS EventLogLastEntry;
++ UINT32 AllocSize;
++
++ GptData = NULL;
+
+ if (mMeasureGptCount > 0) {
+ return EFI_SUCCESS;
+@@ -166,8 +173,8 @@ TcgMeasureGptTable (
+ BlockIo->Media->BlockSize,
+ (UINT8 *)PrimaryHeader
+ );
+- if (EFI_ERROR (Status)) {
+- DEBUG ((DEBUG_ERROR, "Failed to Read Partition Table Header!\n"));
++ if (EFI_ERROR (Status) || EFI_ERROR (SanitizeEfiPartitionTableHeader (PrimaryHeader, BlockIo))) {
++ DEBUG ((DEBUG_ERROR, "Failed to read Partition Table Header or invalid Partition Table Header!\n"));
+ FreePool (PrimaryHeader);
+ return EFI_DEVICE_ERROR;
+ }
+@@ -175,7 +182,13 @@ TcgMeasureGptTable (
+ //
+ // Read the partition entry.
+ //
+- EntryPtr = (UINT8 *)AllocatePool (PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry);
++ Status = SanitizePrimaryHeaderAllocationSize (PrimaryHeader, &AllocSize);
++ if (EFI_ERROR (Status)) {
++ FreePool (PrimaryHeader);
++ return EFI_DEVICE_ERROR;
++ }
++
++ EntryPtr = (UINT8 *)AllocatePool (AllocSize);
+ if (EntryPtr == NULL) {
+ FreePool (PrimaryHeader);
+ return EFI_OUT_OF_RESOURCES;
+@@ -185,7 +198,7 @@ TcgMeasureGptTable (
+ DiskIo,
+ BlockIo->Media->MediaId,
+ MultU64x32 (PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),
+- PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry,
++ AllocSize,
+ EntryPtr
+ );
+ if (EFI_ERROR (Status)) {
+@@ -210,9 +223,8 @@ TcgMeasureGptTable (
+ //
+ // Prepare Data for Measurement
+ //
+- EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions)
+- + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry);
+- TcgEvent = (TCG_PCR_EVENT *)AllocateZeroPool (EventSize + sizeof (TCG_PCR_EVENT_HDR));
++ Status = SanitizePrimaryHeaderGptEventSize (PrimaryHeader, NumberOfPartition, &EventSize);
++ TcgEvent = (TCG_PCR_EVENT *)AllocateZeroPool (EventSize);
+ if (TcgEvent == NULL) {
+ FreePool (PrimaryHeader);
+ FreePool (EntryPtr);
+@@ -221,7 +233,7 @@ TcgMeasureGptTable (
+
+ TcgEvent->PCRIndex = 5;
+ TcgEvent->EventType = EV_EFI_GPT_EVENT;
+- TcgEvent->EventSize = EventSize;
++ TcgEvent->EventSize = EventSize - sizeof (TCG_PCR_EVENT_HDR);
+ GptData = (EFI_GPT_DATA *)TcgEvent->Event;
+
+ //
+@@ -361,11 +373,13 @@ TcgMeasurePeImage (
+ TcgEvent->PCRIndex = 2;
+ break;
+ default:
+- DEBUG ((
+- DEBUG_ERROR,
+- "TcgMeasurePeImage: Unknown subsystem type %d",
+- ImageType
+- ));
++ DEBUG (
++ (
++ DEBUG_ERROR,
++ "TcgMeasurePeImage: Unknown subsystem type %d",
++ ImageType
++ )
++ );
+ goto Finish;
+ }
+
+diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf
+index ebab6f7c1e..414c654d15 100644
+--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf
++++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf
+@@ -32,6 +32,8 @@
+
+ [Sources]
+ DxeTpmMeasureBootLib.c
++ DxeTpmMeasureBootLibSanitization.c
++ DxeTpmMeasureBootLibSanitization.h
+
+ [Packages]
+ MdePkg/MdePkg.dec
+@@ -41,6 +43,7 @@
+
+ [LibraryClasses]
+ BaseMemoryLib
++ SafeIntLib
+ DebugLib
+ MemoryAllocationLib
+ DevicePathLib
+@@ -59,4 +62,3 @@
+ gEfiFirmwareVolumeBlockProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiBlockIoProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiDiskIoProtocolGuid ## SOMETIMES_CONSUMES
+-
+diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c
+new file mode 100644
+index 0000000000..a3fa46f5e6
+--- /dev/null
++++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c
+@@ -0,0 +1,241 @@
++/** @file
++ The library instance provides security service of TPM2 measure boot and
++ Confidential Computing (CC) measure boot.
++
++ Caution: This file requires additional review when modified.
++ This library will have external input - PE/COFF image and GPT partition.
++ This external input must be validated carefully to avoid security issue like
++ buffer overflow, integer overflow.
++
++ This file will pull out the validation logic from the following functions, in an
++ attempt to validate the untrusted input in the form of unit tests
++
++ These are those functions:
++
++ DxeTpmMeasureBootLibImageRead() function will make sure the PE/COFF image content
++ read is within the image buffer.
++
++ Tcg2MeasureGptTable() function will receive untrusted GPT partition table, and parse
++ partition data carefully.
++
++ Copyright (c) Microsoft Corporation.<BR>
++ SPDX-License-Identifier: BSD-2-Clause-Patent
++**/
++#include <Uefi.h>
++#include <Uefi/UefiSpec.h>
++#include <Library/SafeIntLib.h>
++#include <Library/UefiLib.h>
++#include <Library/DebugLib.h>
++#include <Library/BaseLib.h>
++#include <IndustryStandard/UefiTcgPlatform.h>
++#include <Protocol/BlockIo.h>
++#include <Library/MemoryAllocationLib.h>
++
++#include "DxeTpmMeasureBootLibSanitization.h"
++
++#define GPT_HEADER_REVISION_V1 0x00010000
++
++/**
++ This function will validate the EFI_PARTITION_TABLE_HEADER structure is safe to parse
++ However this function will not attempt to verify the validity of the GPT partition
++ It will check the following:
++ - Signature
++ - Revision
++ - AlternateLBA
++ - FirstUsableLBA
++ - LastUsableLBA
++ - PartitionEntryLBA
++ - NumberOfPartitionEntries
++ - SizeOfPartitionEntry
++ - BlockIo
++
++ @param[in] PrimaryHeader
++ Pointer to the EFI_PARTITION_TABLE_HEADER structure.
++
++ @param[in] BlockIo
++ Pointer to the EFI_BLOCK_IO_PROTOCOL structure.
++
++ @retval EFI_SUCCESS
++ The EFI_PARTITION_TABLE_HEADER structure is valid.
++
++ @retval EFI_INVALID_PARAMETER
++ The EFI_PARTITION_TABLE_HEADER structure is invalid.
++**/
++EFI_STATUS
++EFIAPI
++SanitizeEfiPartitionTableHeader (
++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader,
++ IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo
++ )
++{
++ // Verify that the input parameters are safe to use
++ if (PrimaryHeader == NULL) {
++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header!\n"));
++ return EFI_INVALID_PARAMETER;
++ }
++
++ if ((BlockIo == NULL) || (BlockIo->Media == NULL)) {
++ DEBUG ((DEBUG_ERROR, "Invalid BlockIo!\n"));
++ return EFI_INVALID_PARAMETER;
++ }
++
++ // The signature must be EFI_PTAB_HEADER_ID ("EFI PART" in ASCII)
++ if (PrimaryHeader->Header.Signature != EFI_PTAB_HEADER_ID) {
++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header!\n"));
++ return EFI_DEVICE_ERROR;
++ }
++
++ // The version must be GPT_HEADER_REVISION_V1 (0x00010000)
++ if (PrimaryHeader->Header.Revision != GPT_HEADER_REVISION_V1) {
++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header Revision!\n"));
++ return EFI_DEVICE_ERROR;
++ }
++
++ // The HeaderSize must be greater than or equal to 92 and must be less than or equal to the logical block size
++ if ((PrimaryHeader->Header.HeaderSize < sizeof (EFI_PARTITION_TABLE_HEADER)) || (PrimaryHeader->Header.HeaderSize > BlockIo->Media->BlockSize)) {
++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header HeaderSize!\n"));
++ return EFI_DEVICE_ERROR;
++ }
++
++ // check that the PartitionEntryLBA greater than the Max LBA
++ // This will be used later for multiplication
++ if (PrimaryHeader->PartitionEntryLBA > DivU64x32 (MAX_UINT64, BlockIo->Media->BlockSize)) {
++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header PartitionEntryLBA!\n"));
++ return EFI_DEVICE_ERROR;
++ }
++
++ // Check that the number of partition entries is greater than zero
++ if (PrimaryHeader->NumberOfPartitionEntries == 0) {
++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header NumberOfPartitionEntries!\n"));
++ return EFI_DEVICE_ERROR;
++ }
++
++ // SizeOfPartitionEntry must be 128, 256, 512... improper size may lead to accessing uninitialized memory
++ if ((PrimaryHeader->SizeOfPartitionEntry < 128) || ((PrimaryHeader->SizeOfPartitionEntry & (PrimaryHeader->SizeOfPartitionEntry - 1)) != 0)) {
++ DEBUG ((DEBUG_ERROR, "SizeOfPartitionEntry shall be set to a value of 128 x 2^n where n is an integer greater than or equal to zero (e.g., 128, 256, 512, etc.)!\n"));
++ return EFI_DEVICE_ERROR;
++ }
++
++ // This check is to prevent overflow when calculating the allocation size for the partition entries
++ // This check will be used later for multiplication
++ if (PrimaryHeader->NumberOfPartitionEntries > DivU64x32 (MAX_UINT64, PrimaryHeader->SizeOfPartitionEntry)) {
++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header NumberOfPartitionEntries!\n"));
++ return EFI_DEVICE_ERROR;
++ }
++
++ return EFI_SUCCESS;
++}
++
++/**
++ This function will validate that the allocation size from the primary header is sane
++ It will check the following:
++ - AllocationSize does not overflow
++
++ @param[in] PrimaryHeader
++ Pointer to the EFI_PARTITION_TABLE_HEADER structure.
++
++ @param[out] AllocationSize
++ Pointer to the allocation size.
++
++ @retval EFI_SUCCESS
++ The allocation size is valid.
++
++ @retval EFI_OUT_OF_RESOURCES
++ The allocation size is invalid.
++**/
++EFI_STATUS
++EFIAPI
++SanitizePrimaryHeaderAllocationSize (
++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader,
++ OUT UINT32 *AllocationSize
++ )
++{
++ EFI_STATUS Status;
++
++ if (PrimaryHeader == NULL) {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ if (AllocationSize == NULL) {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ // Replacing logic:
++ // PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry;
++ Status = SafeUint32Mult (PrimaryHeader->NumberOfPartitionEntries, PrimaryHeader->SizeOfPartitionEntry, AllocationSize);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "Allocation Size would have overflowed!\n"));
++ return EFI_BAD_BUFFER_SIZE;
++ }
++
++ return EFI_SUCCESS;
++}
++
++/**
++ This function will validate that the Gpt Event Size calculated from the primary header is sane
++ It will check the following:
++ - EventSize does not overflow
++
++ Important: This function includes the entire length of the allocated space, including the
++ TCG_PCR_EVENT_HDR. When hashing the buffer allocated with this size, the caller must subtract
++ the size of the TCG_PCR_EVENT_HDR from the size of the buffer before hashing.
++
++ @param[in] PrimaryHeader - Pointer to the EFI_PARTITION_TABLE_HEADER structure.
++ @param[in] NumberOfPartition - Number of partitions.
++ @param[out] EventSize - Pointer to the event size.
++
++ @retval EFI_SUCCESS
++ The event size is valid.
++
++ @retval EFI_OUT_OF_RESOURCES
++ Overflow would have occurred.
++
++ @retval EFI_INVALID_PARAMETER
++ One of the passed parameters was invalid.
++**/
++EFI_STATUS
++SanitizePrimaryHeaderGptEventSize (
++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader,
++ IN UINTN NumberOfPartition,
++ OUT UINT32 *EventSize
++ )
++{
++ EFI_STATUS Status;
++ UINT32 SafeNumberOfPartitions;
++
++ if (PrimaryHeader == NULL) {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ if (EventSize == NULL) {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ // We shouldn't even attempt to perform the multiplication if the number of partitions is greater than the maximum value of UINT32
++ Status = SafeUintnToUint32 (NumberOfPartition, &SafeNumberOfPartitions);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "NumberOfPartition would have overflowed!\n"));
++ return EFI_INVALID_PARAMETER;
++ }
++
++ // Replacing logic:
++ // (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions) + NumberOfPartition * PrimaryHeader.SizeOfPartitionEntry + sizeof (TCG_PCR_EVENT_HDR));
++ Status = SafeUint32Mult (SafeNumberOfPartitions, PrimaryHeader->SizeOfPartitionEntry, EventSize);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "Event Size would have overflowed!\n"));
++ return EFI_BAD_BUFFER_SIZE;
++ }
++
++ Status = SafeUint32Add (
++ sizeof (TCG_PCR_EVENT_HDR) +
++ OFFSET_OF (EFI_GPT_DATA, Partitions),
++ *EventSize,
++ EventSize
++ );
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "Event Size would have overflowed because of GPTData!\n"));
++ return EFI_BAD_BUFFER_SIZE;
++ }
++
++ return EFI_SUCCESS;
++}
+diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h
+new file mode 100644
+index 0000000000..0d9d00c281
+--- /dev/null
++++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h
+@@ -0,0 +1,114 @@
++/** @file
++ This file includes the function prototypes for the sanitization functions.
++
++ These are those functions:
++
++ DxeTpmMeasureBootLibImageRead() function will make sure the PE/COFF image content
++ read is within the image buffer.
++
++ TcgMeasurePeImage() function will accept untrusted PE/COFF image and validate its
++ data structure within this image buffer before use.
++
++ TcgMeasureGptTable() function will receive untrusted GPT partition table, and parse
++ partition data carefully.
++
++ Copyright (c) Microsoft Corporation.<BR>
++ SPDX-License-Identifier: BSD-2-Clause-Patent
++
++**/
++
++#ifndef DXE_TPM_MEASURE_BOOT_LIB_VALIDATION_
++#define DXE_TPM_MEASURE_BOOT_LIB_VALIDATION_
++
++#include <Uefi.h>
++#include <Uefi/UefiSpec.h>
++#include <Protocol/BlockIo.h>
++#include <IndustryStandard/UefiTcgPlatform.h>
++
++/**
++ This function will validate the EFI_PARTITION_TABLE_HEADER structure is safe to parse
++ However this function will not attempt to verify the validity of the GPT partition
++ It will check the following:
++ - Signature
++ - Revision
++ - AlternateLBA
++ - FirstUsableLBA
++ - LastUsableLBA
++ - PartitionEntryLBA
++ - NumberOfPartitionEntries
++ - SizeOfPartitionEntry
++ - BlockIo
++
++ @param[in] PrimaryHeader
++ Pointer to the EFI_PARTITION_TABLE_HEADER structure.
++
++ @param[in] BlockIo
++ Pointer to the EFI_BLOCK_IO_PROTOCOL structure.
++
++ @retval EFI_SUCCESS
++ The EFI_PARTITION_TABLE_HEADER structure is valid.
++
++ @retval EFI_INVALID_PARAMETER
++ The EFI_PARTITION_TABLE_HEADER structure is invalid.
++**/
++EFI_STATUS
++EFIAPI
++SanitizeEfiPartitionTableHeader (
++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader,
++ IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo
++ );
++
++/**
++ This function will validate that the allocation size from the primary header is sane
++ It will check the following:
++ - AllocationSize does not overflow
++
++ @param[in] PrimaryHeader
++ Pointer to the EFI_PARTITION_TABLE_HEADER structure.
++
++ @param[out] AllocationSize
++ Pointer to the allocation size.
++
++ @retval EFI_SUCCESS
++ The allocation size is valid.
++
++ @retval EFI_OUT_OF_RESOURCES
++ The allocation size is invalid.
++**/
++EFI_STATUS
++EFIAPI
++SanitizePrimaryHeaderAllocationSize (
++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader,
++ OUT UINT32 *AllocationSize
++ );
++
++/**
++ This function will validate that the Gpt Event Size calculated from the primary header is sane
++ It will check the following:
++ - EventSize does not overflow
++
++ Important: This function includes the entire length of the allocated space, including the
++ TCG_PCR_EVENT_HDR. When hashing the buffer allocated with this size, the caller must subtract
++ the size of the TCG_PCR_EVENT_HDR from the size of the buffer before hashing.
++
++ @param[in] PrimaryHeader - Pointer to the EFI_PARTITION_TABLE_HEADER structure.
++ @param[in] NumberOfPartition - Number of partitions.
++ @param[out] EventSize - Pointer to the event size.
++
++ @retval EFI_SUCCESS
++ The event size is valid.
++
++ @retval EFI_OUT_OF_RESOURCES
++ Overflow would have occurred.
++
++ @retval EFI_INVALID_PARAMETER
++ One of the passed parameters was invalid.
++**/
++EFI_STATUS
++SanitizePrimaryHeaderGptEventSize (
++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader,
++ IN UINTN NumberOfPartition,
++ OUT UINT32 *EventSize
++ );
++
++#endif // DXE_TPM_MEASURE_BOOT_LIB_VALIDATION_
+diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c
+new file mode 100644
+index 0000000000..eeb928cdb0
+--- /dev/null
++++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c
+@@ -0,0 +1,301 @@
++/** @file
++This file includes the unit test cases for the DxeTpmMeasureBootLibSanitizationTest.c.
++
++Copyright (c) Microsoft Corporation.<BR>
++SPDX-License-Identifier: BSD-2-Clause-Patent
++**/
++
++#include <Uefi.h>
++#include <Library/UefiLib.h>
++#include <Library/DebugLib.h>
++#include <Library/UnitTestLib.h>
++#include <Protocol/BlockIo.h>
++#include <Library/MemoryAllocationLib.h>
++#include <Library/BaseMemoryLib.h>
++#include <IndustryStandard/UefiTcgPlatform.h>
++
++#include "../DxeTpmMeasureBootLibSanitization.h"
++
++#define UNIT_TEST_NAME "DxeTpmMeasureBootLibSanitizationTest"
++#define UNIT_TEST_VERSION "1.0"
++
++#define DEFAULT_PRIMARY_TABLE_HEADER_REVISION 0x00010000
++#define DEFAULT_PRIMARY_TABLE_HEADER_NUMBER_OF_PARTITION_ENTRIES 1
++#define DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY 128
++
++/**
++ This function tests the SanitizeEfiPartitionTableHeader function.
++ It's intent is to test that a malicious EFI_PARTITION_TABLE_HEADER
++ structure will not cause undefined or unexpected behavior.
++
++ In general the TPM should still be able to measure the data, but
++ be the header should be sanitized to prevent any unexpected behavior.
++
++ @param[in] Context The unit test context.
++
++ @retval UNIT_TEST_PASSED The test passed.
++ @retval UNIT_TEST_ERROR_TEST_FAILED The test failed.
++**/
++UNIT_TEST_STATUS
++EFIAPI
++TestSanitizeEfiPartitionTableHeader (
++ IN UNIT_TEST_CONTEXT Context
++ )
++{
++ EFI_STATUS Status;
++ EFI_PARTITION_TABLE_HEADER PrimaryHeader;
++ EFI_BLOCK_IO_PROTOCOL BlockIo;
++ EFI_BLOCK_IO_MEDIA BlockMedia;
++
++ // Generate EFI_BLOCK_IO_MEDIA test data
++ BlockMedia.MediaId = 1;
++ BlockMedia.RemovableMedia = FALSE;
++ BlockMedia.MediaPresent = TRUE;
++ BlockMedia.LogicalPartition = FALSE;
++ BlockMedia.ReadOnly = FALSE;
++ BlockMedia.WriteCaching = FALSE;
++ BlockMedia.BlockSize = 512;
++ BlockMedia.IoAlign = 1;
++ BlockMedia.LastBlock = 0;
++
++ // Generate EFI_BLOCK_IO_PROTOCOL test data
++ BlockIo.Revision = 1;
++ BlockIo.Media = &BlockMedia;
++ BlockIo.Reset = NULL;
++ BlockIo.ReadBlocks = NULL;
++ BlockIo.WriteBlocks = NULL;
++ BlockIo.FlushBlocks = NULL;
++
++ // Geneate EFI_PARTITION_TABLE_HEADER test data
++ PrimaryHeader.Header.Signature = EFI_PTAB_HEADER_ID;
++ PrimaryHeader.Header.Revision = DEFAULT_PRIMARY_TABLE_HEADER_REVISION;
++ PrimaryHeader.Header.HeaderSize = sizeof (EFI_PARTITION_TABLE_HEADER);
++ PrimaryHeader.MyLBA = 1;
++ PrimaryHeader.AlternateLBA = 2;
++ PrimaryHeader.FirstUsableLBA = 3;
++ PrimaryHeader.LastUsableLBA = 4;
++ PrimaryHeader.PartitionEntryLBA = 5;
++ PrimaryHeader.NumberOfPartitionEntries = DEFAULT_PRIMARY_TABLE_HEADER_NUMBER_OF_PARTITION_ENTRIES;
++ PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;
++ PrimaryHeader.PartitionEntryArrayCRC32 = 0; // Purposely invalid
++
++ // Calculate the CRC32 of the PrimaryHeader
++ PrimaryHeader.Header.CRC32 = CalculateCrc32 ((UINT8 *)&PrimaryHeader, PrimaryHeader.Header.HeaderSize);
++
++ // Test that a normal PrimaryHeader passes validation
++ Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo);
++ UT_ASSERT_NOT_EFI_ERROR (Status);
++
++ // Test that when number of partition entries is 0, the function returns EFI_DEVICE_ERROR
++ // Should print "Invalid Partition Table Header NumberOfPartitionEntries!""
++ PrimaryHeader.NumberOfPartitionEntries = 0;
++ Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo);
++ UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR);
++ PrimaryHeader.NumberOfPartitionEntries = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;
++
++ // Test that when the header size is too small, the function returns EFI_DEVICE_ERROR
++ // Should print "Invalid Partition Table Header Size!"
++ PrimaryHeader.Header.HeaderSize = 0;
++ Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo);
++ UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR);
++ PrimaryHeader.Header.HeaderSize = sizeof (EFI_PARTITION_TABLE_HEADER);
++
++ // Test that when the SizeOfPartitionEntry is too small, the function returns EFI_DEVICE_ERROR
++ // should print: "SizeOfPartitionEntry shall be set to a value of 128 x 2^n where n is an integer greater than or equal to zero (e.g., 128, 256, 512, etc.)!"
++ PrimaryHeader.SizeOfPartitionEntry = 1;
++ Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo);
++ UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR);
++
++ DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));
++
++ return UNIT_TEST_PASSED;
++}
++
++/**
++ This function tests the SanitizePrimaryHeaderAllocationSize function.
++ It's intent is to test that the untrusted input from a EFI_PARTITION_TABLE_HEADER
++ structure will not cause an overflow when calculating the allocation size.
++
++ @param[in] Context The unit test context.
++
++ @retval UNIT_TEST_PASSED The test passed.
++ @retval UNIT_TEST_ERROR_TEST_FAILED The test failed.
++**/
++UNIT_TEST_STATUS
++EFIAPI
++TestSanitizePrimaryHeaderAllocationSize (
++ IN UNIT_TEST_CONTEXT Context
++ )
++{
++ UINT32 AllocationSize;
++
++ EFI_STATUS Status;
++ EFI_PARTITION_TABLE_HEADER PrimaryHeader;
++
++ // Test that a normal PrimaryHeader passes validation
++ PrimaryHeader.NumberOfPartitionEntries = 5;
++ PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;
++
++ Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);
++ UT_ASSERT_NOT_EFI_ERROR (Status);
++
++ // Test that the allocation size is correct compared to the existing logic
++ UT_ASSERT_EQUAL (AllocationSize, PrimaryHeader.NumberOfPartitionEntries * PrimaryHeader.SizeOfPartitionEntry);
++
++ // Test that an overflow is detected
++ PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32;
++ PrimaryHeader.SizeOfPartitionEntry = 5;
++ Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);
++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
++
++ // Test the inverse
++ PrimaryHeader.NumberOfPartitionEntries = 5;
++ PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32;
++ Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);
++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
++
++ // Test the worst case scenario
++ PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32;
++ PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32;
++ Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);
++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
++
++ DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));
++
++ return UNIT_TEST_PASSED;
++}
++
++/**
++ This function tests the SanitizePrimaryHeaderGptEventSize function.
++ It's intent is to test that the untrusted input from a EFI_GPT_DATA structure
++ will not cause an overflow when calculating the event size.
++
++ @param[in] Context The unit test context.
++
++ @retval UNIT_TEST_PASSED The test passed.
++ @retval UNIT_TEST_ERROR_TEST_FAILED The test failed.
++**/
++UNIT_TEST_STATUS
++EFIAPI
++TestSanitizePrimaryHeaderGptEventSize (
++ IN UNIT_TEST_CONTEXT Context
++ )
++{
++ UINT32 EventSize;
++ UINT32 ExistingLogicEventSize;
++ EFI_STATUS Status;
++ EFI_PARTITION_TABLE_HEADER PrimaryHeader;
++ UINTN NumberOfPartition;
++ EFI_GPT_DATA *GptData;
++
++ GptData = NULL;
++
++ // Test that a normal PrimaryHeader passes validation
++ PrimaryHeader.NumberOfPartitionEntries = 5;
++ PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;
++
++ // set the number of partitions
++ NumberOfPartition = 13;
++
++ // that the primary event size is correct
++ Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize);
++ UT_ASSERT_NOT_EFI_ERROR (Status);
++
++ // Calculate the existing logic event size
++ ExistingLogicEventSize = (UINT32)(sizeof (TCG_PCR_EVENT_HDR) + OFFSET_OF (EFI_GPT_DATA, Partitions)
++ + NumberOfPartition * PrimaryHeader.SizeOfPartitionEntry);
++
++ // Check that the event size is correct
++ UT_ASSERT_EQUAL (EventSize, ExistingLogicEventSize);
++
++ // Tests that the primary event size may not overflow
++ Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, MAX_UINT32, &EventSize);
++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
++
++ // Test that the size of partition entries may not overflow
++ PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32;
++ Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize);
++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
++
++ DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));
++
++ return UNIT_TEST_PASSED;
++}
++
++// *--------------------------------------------------------------------*
++// * Unit Test Code Main Function
++// *--------------------------------------------------------------------*
++
++/**
++ This function acts as the entry point for the unit tests.
++
++ @param argc - The number of command line arguments
++ @param argv - The command line arguments
++
++ @return int - The status of the test
++**/
++EFI_STATUS
++EFIAPI
++UefiTestMain (
++ VOID
++ )
++{
++ EFI_STATUS Status;
++ UNIT_TEST_FRAMEWORK_HANDLE Framework;
++ UNIT_TEST_SUITE_HANDLE TcgMeasureBootLibValidationTestSuite;
++
++ Framework = NULL;
++
++ DEBUG ((DEBUG_INFO, "%a: TestMain() - Start\n", UNIT_TEST_NAME));
++
++ Status = InitUnitTestFramework (&Framework, UNIT_TEST_NAME, gEfiCallerBaseName, UNIT_TEST_VERSION);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "%a: Failed in InitUnitTestFramework. Status = %r\n", UNIT_TEST_NAME, Status));
++ goto EXIT;
++ }
++
++ Status = CreateUnitTestSuite (&TcgMeasureBootLibValidationTestSuite, Framework, "TcgMeasureBootLibValidationTestSuite", "Common.TcgMeasureBootLibValidation", NULL, NULL);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "%s: Failed in CreateUnitTestSuite for TcgMeasureBootLibValidationTestSuite\n", UNIT_TEST_NAME));
++ Status = EFI_OUT_OF_RESOURCES;
++ goto EXIT;
++ }
++
++ // -----------Suite---------------------------------Description----------------------------Class----------------------------------Test Function------------------------Pre---Clean-Context
++ AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Validating EFI Partition Table", "Common.TcgMeasureBootLibValidation", TestSanitizeEfiPartitionTableHeader, NULL, NULL, NULL);
++ AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Primary header gpt event checks for overflow", "Common.TcgMeasureBootLibValidation", TestSanitizePrimaryHeaderAllocationSize, NULL, NULL, NULL);
++ AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Primary header allocation size checks for overflow", "Common.TcgMeasureBootLibValidation", TestSanitizePrimaryHeaderGptEventSize, NULL, NULL, NULL);
++
++ Status = RunAllTestSuites (Framework);
++
++EXIT:
++ if (Framework != NULL) {
++ FreeUnitTestFramework (Framework);
++ }
++
++ DEBUG ((DEBUG_INFO, "%a: TestMain() - End\n", UNIT_TEST_NAME));
++ return Status;
++}
++
++///
++/// Avoid ECC error for function name that starts with lower case letter
++///
++#define DxeTpmMeasureBootLibUnitTestMain main
++
++/**
++ Standard POSIX C entry point for host based unit test execution.
++
++ @param[in] Argc Number of arguments
++ @param[in] Argv Array of pointers to arguments
++
++ @retval 0 Success
++ @retval other Error
++**/
++INT32
++DxeTpmMeasureBootLibUnitTestMain (
++ IN INT32 Argc,
++ IN CHAR8 *Argv[]
++ )
++{
++ return (INT32)UefiTestMain ();
++}
+diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTestHost.inf b/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTestHost.inf
+new file mode 100644
+index 0000000000..47b0811b00
+--- /dev/null
++++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTestHost.inf
+@@ -0,0 +1,28 @@
++## @file
++# This file builds the unit tests for DxeTpmMeasureBootLib
++#
++# Copyright (C) Microsoft Corporation.<BR>
++# SPDX-License-Identifier: BSD-2-Clause-Patent
++##
++
++[Defines]
++ INF_VERSION = 0x00010006
++ BASE_NAME = DxeTpmMeasuredBootLibTest
++ FILE_GUID = eb01bc38-309c-4d3e-967e-9f078c90772f
++ MODULE_TYPE = HOST_APPLICATION
++ VERSION_STRING = 1.0
++ ENTRY_POINT = main
++
++[Sources]
++ DxeTpmMeasureBootLibSanitizationTest.c
++ ../DxeTpmMeasureBootLibSanitization.c
++
++[Packages]
++ MdePkg/MdePkg.dec
++
++[LibraryClasses]
++ BaseLib
++ DebugLib
++ UnitTestLib
++ PrintLib
++ SafeIntLib
+diff --git a/SecurityPkg/SecurityPkg.ci.yaml b/SecurityPkg/SecurityPkg.ci.yaml
+index da811fdf93..0e40eaa0fe 100644
+--- a/SecurityPkg/SecurityPkg.ci.yaml
++++ b/SecurityPkg/SecurityPkg.ci.yaml
+@@ -16,6 +16,7 @@
+ ## ]
+ "ExceptionList": [
+ "8001", "DxeTpm2MeasureBootLibUnitTestMain",
++ "8001", "DxeTpmMeasureBootLibUnitTestMain"
+ ],
+ ## Both file path and directory path are accepted.
+ "IgnoreFiles": [
+--
+2.40.0
+
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0003.patch b/meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0003.patch
new file mode 100644
index 0000000000..59bd5c4910
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0003.patch
@@ -0,0 +1,55 @@
+From 1ddcb9fc6b4164e882687b031e8beacfcf7df29e Mon Sep 17 00:00:00 2001
+From: "Douglas Flick [MSFT]" <doug.edk2@gmail.com>
+Date: Fri, 12 Jan 2024 02:16:03 +0800
+Subject: [PATCH] SecurityPkg: : Adding CVE 2022-36763 to SecurityFixes.yaml
+
+This creates / adds a security file that tracks the security fixes
+found in this package and can be used to find the fixes that were
+applied.
+
+Cc: Jiewen Yao <jiewen.yao@intel.com>
+
+Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
+Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
+
+CVE: CVE-2022-36763
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/1ddcb9fc6b4164e882687b031e8beacfcf7df29e]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ SecurityPkg/SecurityFixes.yaml | 22 ++++++++++++++++++++++
+ 1 file changed, 22 insertions(+)
+ create mode 100644 SecurityPkg/SecurityFixes.yaml
+
+diff --git a/SecurityPkg/SecurityFixes.yaml b/SecurityPkg/SecurityFixes.yaml
+new file mode 100644
+index 0000000000..f9e3e7be74
+--- /dev/null
++++ b/SecurityPkg/SecurityFixes.yaml
+@@ -0,0 +1,22 @@
++## @file
++# Security Fixes for SecurityPkg
++#
++# Copyright (c) Microsoft Corporation
++# SPDX-License-Identifier: BSD-2-Clause-Patent
++##
++CVE_2022_36763:
++ commit_titles:
++ - "SecurityPkg: DxeTpm2Measurement: SECURITY PATCH 4117 - CVE 2022-36763"
++ - "SecurityPkg: DxeTpmMeasurement: SECURITY PATCH 4117 - CVE 2022-36763"
++ - "SecurityPkg: : Adding CVE 2022-36763 to SecurityFixes.yaml"
++ cve: CVE-2022-36763
++ date_reported: 2022-10-25 11:31 UTC
++ description: (CVE-2022-36763) - Heap Buffer Overflow in Tcg2MeasureGptTable()
++ note: This patch is related to and supersedes TCBZ2168
++ files_impacted:
++ - Library\DxeTpm2MeasureBootLib\DxeTpm2MeasureBootLib.c
++ - Library\DxeTpmMeasureBootLib\DxeTpmMeasureBootLib.c
++ links:
++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4117
++ - https://bugzilla.tianocore.org/show_bug.cgi?id=2168
++ - https://bugzilla.tianocore.org/show_bug.cgi?id=1990
+--
+2.40.0
+
diff --git a/meta/recipes-core/ovmf/ovmf_git.bb b/meta/recipes-core/ovmf/ovmf_git.bb
index 84e3360a3a..78d86ad879 100644
--- a/meta/recipes-core/ovmf/ovmf_git.bb
+++ b/meta/recipes-core/ovmf/ovmf_git.bb
@@ -27,6 +27,9 @@ SRC_URI = "gitsm://github.com/tianocore/edk2.git;branch=master;protocol=https \
file://0006-reproducible.patch \
file://0001-BaseTools-fix-gcc12-warning.patch \
file://0001-BaseTools-fix-gcc12-warning-1.patch \
+ file://CVE-2022-36763-0001.patch \
+ file://CVE-2022-36763-0002.patch \
+ file://CVE-2022-36763-0003.patch \
"
PV = "edk2-stable202202"
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 02/38] ovmf: Fix CVE-2022-36764
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 01/38] ovmf: Fix CVE-2022-36763 Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 03/38] ovmf: Fix CVE-2023-45230 Steve Sakoman
` (35 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Soumya Sambu <soumya.sambu@windriver.com>
EDK2 is susceptible to a vulnerability in the Tcg2MeasurePeImage()
function, allowing a user to trigger a heap buffer overflow via a local
network. Successful exploitation of this vulnerability may result in a
compromise of confidentiality, integrity, and/or availability.
References:
https://nvd.nist.gov/vuln/detail/CVE-2022-36764
Upstream-patches:
https://github.com/tianocore/edk2/commit/c7b27944218130cca3bbb20314ba5b88b5de4aa4
https://github.com/tianocore/edk2/commit/0d341c01eeabe0ab5e76693b36e728b8f538a40e
https://github.com/tianocore/edk2/commit/8f6d343ae639fba8e4b80e45257275e23083431f
Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
---
.../ovmf/ovmf/CVE-2022-36764-0001.patch | 271 +++++++++++++++++
.../ovmf/ovmf/CVE-2022-36764-0002.patch | 281 ++++++++++++++++++
.../ovmf/ovmf/CVE-2022-36764-0003.patch | 48 +++
meta/recipes-core/ovmf/ovmf_git.bb | 3 +
4 files changed, 603 insertions(+)
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2022-36764-0001.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2022-36764-0002.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2022-36764-0003.patch
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2022-36764-0001.patch b/meta/recipes-core/ovmf/ovmf/CVE-2022-36764-0001.patch
new file mode 100644
index 0000000000..a552f36b2c
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/CVE-2022-36764-0001.patch
@@ -0,0 +1,271 @@
+From c7b27944218130cca3bbb20314ba5b88b5de4aa4 Mon Sep 17 00:00:00 2001
+From: "Douglas Flick [MSFT]" <doug.edk2@gmail.com>
+Date: Fri, 12 Jan 2024 02:16:04 +0800
+Subject: [PATCH] SecurityPkg: DxeTpm2MeasureBootLib: SECURITY PATCH 4118 - CVE
+ 2022-36764
+
+This commit contains the patch files and tests for DxeTpm2MeasureBootLib
+CVE 2022-36764.
+
+Cc: Jiewen Yao <jiewen.yao@intel.com>
+
+Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
+Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
+
+CVE: CVE-2022-36764
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/c7b27944218130cca3bbb20314ba5b88b5de4aa4]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ .../DxeTpm2MeasureBootLib.c | 12 ++--
+ .../DxeTpm2MeasureBootLibSanitization.c | 46 +++++++++++++-
+ .../DxeTpm2MeasureBootLibSanitization.h | 28 ++++++++-
+ .../DxeTpm2MeasureBootLibSanitizationTest.c | 60 ++++++++++++++++---
+ 4 files changed, 131 insertions(+), 15 deletions(-)
+
+diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c
+index 0475103d6e..714cc8e03e 100644
+--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c
++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c
+@@ -378,7 +378,6 @@ Exit:
+ @retval EFI_OUT_OF_RESOURCES No enough resource to measure image.
+ @retval EFI_UNSUPPORTED ImageType is unsupported or PE image is mal-format.
+ @retval other error value
+-
+ **/
+ EFI_STATUS
+ EFIAPI
+@@ -405,6 +404,7 @@ Tcg2MeasurePeImage (
+ Status = EFI_UNSUPPORTED;
+ ImageLoad = NULL;
+ EventPtr = NULL;
++ Tcg2Event = NULL;
+
+ Tcg2Protocol = MeasureBootProtocols->Tcg2Protocol;
+ CcProtocol = MeasureBootProtocols->CcProtocol;
+@@ -420,18 +420,22 @@ Tcg2MeasurePeImage (
+ }
+
+ FilePathSize = (UINT32)GetDevicePathSize (FilePath);
++ Status = SanitizePeImageEventSize (FilePathSize, &EventSize);
++ if (EFI_ERROR (Status)) {
++ return EFI_UNSUPPORTED;
++ }
+
+ //
+ // Determine destination PCR by BootPolicy
+ //
+- EventSize = sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath) + FilePathSize;
+- EventPtr = AllocateZeroPool (EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event));
++ // from a malicious GPT disk partition
++ EventPtr = AllocateZeroPool (EventSize);
+ if (EventPtr == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Tcg2Event = (EFI_TCG2_EVENT *)EventPtr;
+- Tcg2Event->Size = EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event);
++ Tcg2Event->Size = EventSize;
+ Tcg2Event->Header.HeaderSize = sizeof (EFI_TCG2_EVENT_HEADER);
+ Tcg2Event->Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION;
+ ImageLoad = (EFI_IMAGE_LOAD_EVENT *)Tcg2Event->Event;
+diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c
+index e2309655d3..2a4d52c6d5 100644
+--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c
++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c
+@@ -151,7 +151,7 @@ SanitizeEfiPartitionTableHeader (
+ }
+
+ /**
+- This function will validate that the allocation size from the primary header is sane
++ This function will validate that the allocation size from the primary header is sane
+ It will check the following:
+ - AllocationSize does not overflow
+
+@@ -273,3 +273,47 @@ SanitizePrimaryHeaderGptEventSize (
+
+ return EFI_SUCCESS;
+ }
++
++/**
++ This function will validate that the PeImage Event Size from the loaded image is sane
++ It will check the following:
++ - EventSize does not overflow
++
++ @param[in] FilePathSize - Size of the file path.
++ @param[out] EventSize - Pointer to the event size.
++
++ @retval EFI_SUCCESS
++ The event size is valid.
++
++ @retval EFI_OUT_OF_RESOURCES
++ Overflow would have occurred.
++
++ @retval EFI_INVALID_PARAMETER
++ One of the passed parameters was invalid.
++**/
++EFI_STATUS
++SanitizePeImageEventSize (
++ IN UINT32 FilePathSize,
++ OUT UINT32 *EventSize
++ )
++{
++ EFI_STATUS Status;
++
++ // Replacing logic:
++ // sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath) + FilePathSize;
++ Status = SafeUint32Add (OFFSET_OF (EFI_IMAGE_LOAD_EVENT, DevicePath), FilePathSize, EventSize);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "EventSize would overflow!\n"));
++ return EFI_BAD_BUFFER_SIZE;
++ }
++
++ // Replacing logic:
++ // EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event)
++ Status = SafeUint32Add (*EventSize, OFFSET_OF (EFI_TCG2_EVENT, Event), EventSize);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "EventSize would overflow!\n"));
++ return EFI_BAD_BUFFER_SIZE;
++ }
++
++ return EFI_SUCCESS;
++}
+diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h
+index 048b738987..8f72ba4240 100644
+--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h
++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h
+@@ -9,6 +9,9 @@
+ Tcg2MeasureGptTable() function will receive untrusted GPT partition table, and parse
+ partition data carefully.
+
++ Tcg2MeasurePeImage() function will accept untrusted PE/COFF image and validate its
++ data structure within this image buffer before use.
++
+ Copyright (c) Microsoft Corporation.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+@@ -110,4 +113,27 @@ SanitizePrimaryHeaderGptEventSize (
+ OUT UINT32 *EventSize
+ );
+
+-#endif // DXE_TPM2_MEASURE_BOOT_LIB_SANITATION_
++/**
++ This function will validate that the PeImage Event Size from the loaded image is sane
++ It will check the following:
++ - EventSize does not overflow
++
++ @param[in] FilePathSize - Size of the file path.
++ @param[out] EventSize - Pointer to the event size.
++
++ @retval EFI_SUCCESS
++ The event size is valid.
++
++ @retval EFI_OUT_OF_RESOURCES
++ Overflow would have occurred.
++
++ @retval EFI_INVALID_PARAMETER
++ One of the passed parameters was invalid.
++**/
++EFI_STATUS
++SanitizePeImageEventSize (
++ IN UINT32 FilePathSize,
++ OUT UINT32 *EventSize
++ );
++
++#endif // DXE_TPM2_MEASURE_BOOT_LIB_VALIDATION_
+diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c
+index 3eb9763e3c..820e99aeb9 100644
+--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c
++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c
+@@ -72,10 +72,10 @@ TestSanitizeEfiPartitionTableHeader (
+ PrimaryHeader.Header.Revision = DEFAULT_PRIMARY_TABLE_HEADER_REVISION;
+ PrimaryHeader.Header.HeaderSize = sizeof (EFI_PARTITION_TABLE_HEADER);
+ PrimaryHeader.MyLBA = 1;
+- PrimaryHeader.AlternateLBA = 2;
+- PrimaryHeader.FirstUsableLBA = 3;
+- PrimaryHeader.LastUsableLBA = 4;
+- PrimaryHeader.PartitionEntryLBA = 5;
++ PrimaryHeader.PartitionEntryLBA = 2;
++ PrimaryHeader.AlternateLBA = 3;
++ PrimaryHeader.FirstUsableLBA = 4;
++ PrimaryHeader.LastUsableLBA = 5;
+ PrimaryHeader.NumberOfPartitionEntries = DEFAULT_PRIMARY_TABLE_HEADER_NUMBER_OF_PARTITION_ENTRIES;
+ PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;
+ PrimaryHeader.PartitionEntryArrayCRC32 = 0; // Purposely invalid
+@@ -187,11 +187,6 @@ TestSanitizePrimaryHeaderGptEventSize (
+ EFI_STATUS Status;
+ EFI_PARTITION_TABLE_HEADER PrimaryHeader;
+ UINTN NumberOfPartition;
+- EFI_GPT_DATA *GptData;
+- EFI_TCG2_EVENT *Tcg2Event;
+-
+- Tcg2Event = NULL;
+- GptData = NULL;
+
+ // Test that a normal PrimaryHeader passes validation
+ PrimaryHeader.NumberOfPartitionEntries = 5;
+@@ -225,6 +220,52 @@ TestSanitizePrimaryHeaderGptEventSize (
+ return UNIT_TEST_PASSED;
+ }
+
++/**
++ This function tests the SanitizePeImageEventSize function.
++ It's intent is to test that the untrusted input from a file path when generating a
++ EFI_IMAGE_LOAD_EVENT structure will not cause an overflow when calculating
++ the event size when allocating space
++
++ @param[in] Context The unit test context.
++
++ @retval UNIT_TEST_PASSED The test passed.
++ @retval UNIT_TEST_ERROR_TEST_FAILED The test failed.
++**/
++UNIT_TEST_STATUS
++EFIAPI
++TestSanitizePeImageEventSize (
++ IN UNIT_TEST_CONTEXT Context
++ )
++{
++ UINT32 EventSize;
++ UINTN ExistingLogicEventSize;
++ UINT32 FilePathSize;
++ EFI_STATUS Status;
++
++ FilePathSize = 255;
++
++ // Test that a normal PE image passes validation
++ Status = SanitizePeImageEventSize (FilePathSize, &EventSize);
++ UT_ASSERT_EQUAL (Status, EFI_SUCCESS);
++
++ // Test that the event size is correct compared to the existing logic
++ ExistingLogicEventSize = OFFSET_OF (EFI_IMAGE_LOAD_EVENT, DevicePath) + FilePathSize;
++ ExistingLogicEventSize += OFFSET_OF (EFI_TCG2_EVENT, Event);
++
++ if (EventSize != ExistingLogicEventSize) {
++ UT_LOG_ERROR ("SanitizePeImageEventSize returned an incorrect event size. Expected %u, got %u\n", ExistingLogicEventSize, EventSize);
++ return UNIT_TEST_ERROR_TEST_FAILED;
++ }
++
++ // Test that the event size may not overflow
++ Status = SanitizePeImageEventSize (MAX_UINT32, &EventSize);
++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
++
++ DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));
++
++ return UNIT_TEST_PASSED;
++}
++
+ // *--------------------------------------------------------------------*
+ // * Unit Test Code Main Function
+ // *--------------------------------------------------------------------*
+@@ -267,6 +308,7 @@ UefiTestMain (
+ AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Validating EFI Partition Table", "Common.Tcg2MeasureBootLibValidation", TestSanitizeEfiPartitionTableHeader, NULL, NULL, NULL);
+ AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Primary header gpt event checks for overflow", "Common.Tcg2MeasureBootLibValidation", TestSanitizePrimaryHeaderAllocationSize, NULL, NULL, NULL);
+ AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Primary header allocation size checks for overflow", "Common.Tcg2MeasureBootLibValidation", TestSanitizePrimaryHeaderGptEventSize, NULL, NULL, NULL);
++ AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests PE Image and FileSize checks for overflow", "Common.Tcg2MeasureBootLibValidation", TestSanitizePeImageEventSize, NULL, NULL, NULL);
+
+ Status = RunAllTestSuites (Framework);
+
+--
+2.40.0
+
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2022-36764-0002.patch b/meta/recipes-core/ovmf/ovmf/CVE-2022-36764-0002.patch
new file mode 100644
index 0000000000..22a7713f52
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/CVE-2022-36764-0002.patch
@@ -0,0 +1,281 @@
+From 0d341c01eeabe0ab5e76693b36e728b8f538a40e Mon Sep 17 00:00:00 2001
+From: "Douglas Flick [MSFT]" <doug.edk2@gmail.com>
+Date: Fri, 12 Jan 2024 02:16:05 +0800
+Subject: [PATCH] SecurityPkg: DxeTpmMeasureBootLib: SECURITY PATCH 4118 - CVE
+ 2022-36764
+
+This commit contains the patch files and tests for DxeTpmMeasureBootLib
+CVE 2022-36764.
+
+Cc: Jiewen Yao <jiewen.yao@intel.com>
+
+Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
+Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
+
+CVE: CVE-2022-36764
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/0d341c01eeabe0ab5e76693b36e728b8f538a40e]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ .../DxeTpmMeasureBootLib.c | 13 ++-
+ .../DxeTpmMeasureBootLibSanitization.c | 44 +++++++++
+ .../DxeTpmMeasureBootLibSanitization.h | 23 +++++
+ .../DxeTpmMeasureBootLibSanitizationTest.c | 98 +++++++++++++++++--
+ 4 files changed, 168 insertions(+), 10 deletions(-)
+
+diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c
+index 669ab19134..a9fc440a09 100644
+--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c
++++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c
+@@ -17,6 +17,7 @@
+
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
++Copyright (c) Microsoft Corporation.<BR>
+
+ Copyright (c) Microsoft Corporation.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+@@ -345,18 +346,22 @@ TcgMeasurePeImage (
+ ImageLoad = NULL;
+ SectionHeader = NULL;
+ Sha1Ctx = NULL;
++ TcgEvent = NULL;
+ FilePathSize = (UINT32)GetDevicePathSize (FilePath);
+
+- //
+ // Determine destination PCR by BootPolicy
+ //
+- EventSize = sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath) + FilePathSize;
+- TcgEvent = AllocateZeroPool (EventSize + sizeof (TCG_PCR_EVENT));
++ Status = SanitizePeImageEventSize (FilePathSize, &EventSize);
++ if (EFI_ERROR (Status)) {
++ return EFI_UNSUPPORTED;
++ }
++
++ TcgEvent = AllocateZeroPool (EventSize);
+ if (TcgEvent == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+- TcgEvent->EventSize = EventSize;
++ TcgEvent->EventSize = EventSize - sizeof (TCG_PCR_EVENT_HDR);
+ ImageLoad = (EFI_IMAGE_LOAD_EVENT *)TcgEvent->Event;
+
+ switch (ImageType) {
+diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c
+index a3fa46f5e6..c989851cec 100644
+--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c
++++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c
+@@ -239,3 +239,47 @@ SanitizePrimaryHeaderGptEventSize (
+
+ return EFI_SUCCESS;
+ }
++
++/**
++ This function will validate that the PeImage Event Size from the loaded image is sane
++ It will check the following:
++ - EventSize does not overflow
++
++ @param[in] FilePathSize - Size of the file path.
++ @param[out] EventSize - Pointer to the event size.
++
++ @retval EFI_SUCCESS
++ The event size is valid.
++
++ @retval EFI_OUT_OF_RESOURCES
++ Overflow would have occurred.
++
++ @retval EFI_INVALID_PARAMETER
++ One of the passed parameters was invalid.
++**/
++EFI_STATUS
++SanitizePeImageEventSize (
++ IN UINT32 FilePathSize,
++ OUT UINT32 *EventSize
++ )
++{
++ EFI_STATUS Status;
++
++ // Replacing logic:
++ // sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath) + FilePathSize;
++ Status = SafeUint32Add (OFFSET_OF (EFI_IMAGE_LOAD_EVENT, DevicePath), FilePathSize, EventSize);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "EventSize would overflow!\n"));
++ return EFI_BAD_BUFFER_SIZE;
++ }
++
++ // Replacing logic:
++ // EventSize + sizeof (TCG_PCR_EVENT_HDR)
++ Status = SafeUint32Add (*EventSize, sizeof (TCG_PCR_EVENT_HDR), EventSize);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "EventSize would overflow!\n"));
++ return EFI_BAD_BUFFER_SIZE;
++ }
++
++ return EFI_SUCCESS;
++}
+diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h
+index 0d9d00c281..2248495813 100644
+--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h
++++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h
+@@ -111,4 +111,27 @@ SanitizePrimaryHeaderGptEventSize (
+ OUT UINT32 *EventSize
+ );
+
++/**
++ This function will validate that the PeImage Event Size from the loaded image is sane
++ It will check the following:
++ - EventSize does not overflow
++
++ @param[in] FilePathSize - Size of the file path.
++ @param[out] EventSize - Pointer to the event size.
++
++ @retval EFI_SUCCESS
++ The event size is valid.
++
++ @retval EFI_OUT_OF_RESOURCES
++ Overflow would have occurred.
++
++ @retval EFI_INVALID_PARAMETER
++ One of the passed parameters was invalid.
++**/
++EFI_STATUS
++SanitizePeImageEventSize (
++ IN UINT32 FilePathSize,
++ OUT UINT32 *EventSize
++ );
++
+ #endif // DXE_TPM_MEASURE_BOOT_LIB_VALIDATION_
+diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c
+index eeb928cdb0..c41498be45 100644
+--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c
++++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c
+@@ -1,8 +1,8 @@
+ /** @file
+-This file includes the unit test cases for the DxeTpmMeasureBootLibSanitizationTest.c.
++ This file includes the unit test cases for the DxeTpmMeasureBootLibSanitizationTest.c.
+
+-Copyright (c) Microsoft Corporation.<BR>
+-SPDX-License-Identifier: BSD-2-Clause-Patent
++ Copyright (c) Microsoft Corporation.<BR>
++ SPDX-License-Identifier: BSD-2-Clause-Patent
+ **/
+
+ #include <Uefi.h>
+@@ -186,9 +186,6 @@ TestSanitizePrimaryHeaderGptEventSize (
+ EFI_STATUS Status;
+ EFI_PARTITION_TABLE_HEADER PrimaryHeader;
+ UINTN NumberOfPartition;
+- EFI_GPT_DATA *GptData;
+-
+- GptData = NULL;
+
+ // Test that a normal PrimaryHeader passes validation
+ PrimaryHeader.NumberOfPartitionEntries = 5;
+@@ -222,6 +219,94 @@ TestSanitizePrimaryHeaderGptEventSize (
+ return UNIT_TEST_PASSED;
+ }
+
++/**
++ This function tests the SanitizePeImageEventSize function.
++ It's intent is to test that the untrusted input from a file path for an
++ EFI_IMAGE_LOAD_EVENT structure will not cause an overflow when calculating
++ the event size when allocating space.
++
++ @param[in] Context The unit test context.
++
++ @retval UNIT_TEST_PASSED The test passed.
++ @retval UNIT_TEST_ERROR_TEST_FAILED The test failed.
++**/
++UNIT_TEST_STATUS
++EFIAPI
++TestSanitizePeImageEventSize (
++ IN UNIT_TEST_CONTEXT Context
++ )
++{
++ UINT32 EventSize;
++ UINTN ExistingLogicEventSize;
++ UINT32 FilePathSize;
++ EFI_STATUS Status;
++ EFI_DEVICE_PATH_PROTOCOL DevicePath;
++ EFI_IMAGE_LOAD_EVENT *ImageLoadEvent;
++ UNIT_TEST_STATUS TestStatus;
++
++ TestStatus = UNIT_TEST_ERROR_TEST_FAILED;
++
++ // Generate EFI_DEVICE_PATH_PROTOCOL test data
++ DevicePath.Type = 0;
++ DevicePath.SubType = 0;
++ DevicePath.Length[0] = 0;
++ DevicePath.Length[1] = 0;
++
++ // Generate EFI_IMAGE_LOAD_EVENT test data
++ ImageLoadEvent = AllocateZeroPool (sizeof (EFI_IMAGE_LOAD_EVENT) + sizeof (EFI_DEVICE_PATH_PROTOCOL));
++ if (ImageLoadEvent == NULL) {
++ DEBUG ((DEBUG_ERROR, "%a: AllocateZeroPool failed\n", __func__));
++ goto Exit;
++ }
++
++ // Populate EFI_IMAGE_LOAD_EVENT54 test data
++ ImageLoadEvent->ImageLocationInMemory = (EFI_PHYSICAL_ADDRESS)0x12345678;
++ ImageLoadEvent->ImageLengthInMemory = 0x1000;
++ ImageLoadEvent->ImageLinkTimeAddress = (UINTN)ImageLoadEvent;
++ ImageLoadEvent->LengthOfDevicePath = sizeof (EFI_DEVICE_PATH_PROTOCOL);
++ CopyMem (ImageLoadEvent->DevicePath, &DevicePath, sizeof (EFI_DEVICE_PATH_PROTOCOL));
++
++ FilePathSize = 255;
++
++ // Test that a normal PE image passes validation
++ Status = SanitizePeImageEventSize (FilePathSize, &EventSize);
++ if (EFI_ERROR (Status)) {
++ UT_LOG_ERROR ("SanitizePeImageEventSize failed with %r\n", Status);
++ goto Exit;
++ }
++
++ // Test that the event size is correct compared to the existing logic
++ ExistingLogicEventSize = OFFSET_OF (EFI_IMAGE_LOAD_EVENT, DevicePath) + FilePathSize;
++ ExistingLogicEventSize += sizeof (TCG_PCR_EVENT_HDR);
++
++ if (EventSize != ExistingLogicEventSize) {
++ UT_LOG_ERROR ("SanitizePeImageEventSize returned an incorrect event size. Expected %u, got %u\n", ExistingLogicEventSize, EventSize);
++ goto Exit;
++ }
++
++ // Test that the event size may not overflow
++ Status = SanitizePeImageEventSize (MAX_UINT32, &EventSize);
++ if (Status != EFI_BAD_BUFFER_SIZE) {
++ UT_LOG_ERROR ("SanitizePeImageEventSize succeded when it was supposed to fail with %r\n", Status);
++ goto Exit;
++ }
++
++ TestStatus = UNIT_TEST_PASSED;
++Exit:
++
++ if (ImageLoadEvent != NULL) {
++ FreePool (ImageLoadEvent);
++ }
++
++ if (TestStatus == UNIT_TEST_ERROR_TEST_FAILED) {
++ DEBUG ((DEBUG_ERROR, "%a: Test failed\n", __func__));
++ } else {
++ DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));
++ }
++
++ return TestStatus;
++}
++
+ // *--------------------------------------------------------------------*
+ // * Unit Test Code Main Function
+ // *--------------------------------------------------------------------*
+@@ -265,6 +350,7 @@ UefiTestMain (
+ AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Validating EFI Partition Table", "Common.TcgMeasureBootLibValidation", TestSanitizeEfiPartitionTableHeader, NULL, NULL, NULL);
+ AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Primary header gpt event checks for overflow", "Common.TcgMeasureBootLibValidation", TestSanitizePrimaryHeaderAllocationSize, NULL, NULL, NULL);
+ AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Primary header allocation size checks for overflow", "Common.TcgMeasureBootLibValidation", TestSanitizePrimaryHeaderGptEventSize, NULL, NULL, NULL);
++ AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests PE Image and FileSize checks for overflow", "Common.TcgMeasureBootLibValidation", TestSanitizePeImageEventSize, NULL, NULL, NULL);
+
+ Status = RunAllTestSuites (Framework);
+
+--
+2.40.0
+
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2022-36764-0003.patch b/meta/recipes-core/ovmf/ovmf/CVE-2022-36764-0003.patch
new file mode 100644
index 0000000000..89386c0c29
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/CVE-2022-36764-0003.patch
@@ -0,0 +1,48 @@
+From 8f6d343ae639fba8e4b80e45257275e23083431f Mon Sep 17 00:00:00 2001
+From: "Douglas Flick [MSFT]" <doug.edk2@gmail.com>
+Date: Fri, 12 Jan 2024 02:16:06 +0800
+Subject: [PATCH] SecurityPkg: : Adding CVE 2022-36764 to SecurityFixes.yaml
+
+This creates / adds a security file that tracks the security fixes
+found in this package and can be used to find the fixes that were
+applied.
+
+Cc: Jiewen Yao <jiewen.yao@intel.com>
+
+Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
+Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
+
+CVE: CVE-2022-36764
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/8f6d343ae639fba8e4b80e45257275e23083431f]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ SecurityPkg/SecurityFixes.yaml | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/SecurityPkg/SecurityFixes.yaml b/SecurityPkg/SecurityFixes.yaml
+index f9e3e7be74..833fb827a9 100644
+--- a/SecurityPkg/SecurityFixes.yaml
++++ b/SecurityPkg/SecurityFixes.yaml
+@@ -20,3 +20,17 @@ CVE_2022_36763:
+ - https://bugzilla.tianocore.org/show_bug.cgi?id=4117
+ - https://bugzilla.tianocore.org/show_bug.cgi?id=2168
+ - https://bugzilla.tianocore.org/show_bug.cgi?id=1990
++CVE_2022_36764:
++ commit_titles:
++ - "SecurityPkg: DxeTpm2MeasureBootLib: SECURITY PATCH 4118 - CVE 2022-36764"
++ - "SecurityPkg: DxeTpmMeasureBootLib: SECURITY PATCH 4118 - CVE 2022-36764"
++ - "SecurityPkg: : Adding CVE 2022-36764 to SecurityFixes.yaml"
++ cve: CVE-2022-36764
++ date_reported: 2022-10-25 12:23 UTC
++ description: Heap Buffer Overflow in Tcg2MeasurePeImage()
++ note:
++ files_impacted:
++ - Library\DxeTpm2MeasureBootLib\DxeTpm2MeasureBootLib.c
++ - Library\DxeTpmMeasureBootLib\DxeTpmMeasureBootLib.c
++ links:
++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4118
+--
+2.40.0
+
diff --git a/meta/recipes-core/ovmf/ovmf_git.bb b/meta/recipes-core/ovmf/ovmf_git.bb
index 78d86ad879..59e5598a1b 100644
--- a/meta/recipes-core/ovmf/ovmf_git.bb
+++ b/meta/recipes-core/ovmf/ovmf_git.bb
@@ -30,6 +30,9 @@ SRC_URI = "gitsm://github.com/tianocore/edk2.git;branch=master;protocol=https \
file://CVE-2022-36763-0001.patch \
file://CVE-2022-36763-0002.patch \
file://CVE-2022-36763-0003.patch \
+ file://CVE-2022-36764-0001.patch \
+ file://CVE-2022-36764-0002.patch \
+ file://CVE-2022-36764-0003.patch \
"
PV = "edk2-stable202202"
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 03/38] ovmf: Fix CVE-2023-45230
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 01/38] ovmf: Fix CVE-2022-36763 Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 02/38] ovmf: Fix CVE-2022-36764 Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 04/38] ovmf: Fix CVE-2023-45231 Steve Sakoman
` (34 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Soumya Sambu <soumya.sambu@windriver.com>
EDK2's Network Package is susceptible to a buffer overflow vulnerability
via a long server ID option in DHCPv6 client. 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-45230
Upstream-patches:
https://github.com/tianocore/edk2/commit/f31453e8d6542461d92d835e0b79fec8b039174d
https://github.com/tianocore/edk2/commit/5f3658197bf29c83b3349b0ab1d99cdb0c3814bc
Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
---
.../ovmf/ovmf/CVE-2023-45230-0001.patch | 1617 +++++++++++++++++
.../ovmf/ovmf/CVE-2023-45230-0002.patch | 604 ++++++
meta/recipes-core/ovmf/ovmf_git.bb | 2 +
3 files changed, 2223 insertions(+)
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45230-0001.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45230-0002.patch
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2023-45230-0001.patch b/meta/recipes-core/ovmf/ovmf/CVE-2023-45230-0001.patch
new file mode 100644
index 0000000000..b0e13c1613
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/CVE-2023-45230-0001.patch
@@ -0,0 +1,1617 @@
+From f31453e8d6542461d92d835e0b79fec8b039174d Mon Sep 17 00:00:00 2001
+From: "Doug Flick via groups.io" <dougflick=microsoft.com@groups.io>
+Date: Fri, 26 Jan 2024 05:54:43 +0800
+Subject: [PATCH] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch
+
+REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4535
+
+Bug Details:
+PixieFail Bug #2
+CVE-2023-45230
+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
+
+Changes Overview:
+> -UINT8 *
+> +EFI_STATUS
+> Dhcp6AppendOption (
+> - IN OUT UINT8 *Buf,
+> - IN UINT16 OptType,
+> - IN UINT16 OptLen,
+> - IN UINT8 *Data
+> + IN OUT EFI_DHCP6_PACKET *Packet,
+> + IN OUT UINT8 **PacketCursor,
+> + IN UINT16 OptType,
+> + IN UINT16 OptLen,
+> + IN UINT8 *Data
+> );
+
+Dhcp6AppendOption() and variants can return errors now. All callsites
+are adapted accordingly.
+
+It gets passed in EFI_DHCP6_PACKET as additional parameter ...
+
+> + //
+> + // Verify the PacketCursor is within the packet
+> + //
+> + if ( (*PacketCursor < Packet->Dhcp6.Option)
+> + || (*PacketCursor >= Packet->Dhcp6.Option +
+ (Packet->Size - sizeof (EFI_DHCP6_HEADER))))
+> + {
+> + return EFI_INVALID_PARAMETER;
+> + }
+
+... so it can look at Packet->Size when checking buffer space.
+Also to allow Packet->Length updates.
+
+Lots of checks added.
+
+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-45230
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/f31453e8d6542461d92d835e0b79fec8b039174d]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h | 43 +++
+ NetworkPkg/Dhcp6Dxe/Dhcp6Io.c | 409 +++++++++++++++++++----------
+ NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c | 373 +++++++++++++++++++++-----
+ NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h | 82 +++---
+ 4 files changed, 668 insertions(+), 239 deletions(-)
+
+diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h
+index 0eb9c669b5..f2422c2f28 100644
+--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h
++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h
+@@ -45,6 +45,49 @@ typedef struct _DHCP6_INSTANCE DHCP6_INSTANCE;
+ #define DHCP6_SERVICE_SIGNATURE SIGNATURE_32 ('D', 'H', '6', 'S')
+ #define DHCP6_INSTANCE_SIGNATURE SIGNATURE_32 ('D', 'H', '6', 'I')
+
++//
++// For more information on DHCP options see RFC 8415, Section 21.1
++//
++// The format of DHCP options is:
++//
++// 0 1 2 3
++// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++// | option-code | option-len |
++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++// | option-data |
++// | (option-len octets) |
++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++//
++#define DHCP6_SIZE_OF_OPT_CODE (sizeof(UINT16))
++#define DHCP6_SIZE_OF_OPT_LEN (sizeof(UINT16))
++
++//
++// Combined size of Code and Length
++//
++#define DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN (DHCP6_SIZE_OF_OPT_CODE + \
++ DHCP6_SIZE_OF_OPT_LEN)
++
++STATIC_ASSERT (
++ DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN == 4,
++ "Combined size of Code and Length must be 4 per RFC 8415"
++ );
++
++//
++// Offset to the length is just past the code
++//
++#define DHCP6_OPT_LEN_OFFSET(a) (a + DHCP6_SIZE_OF_OPT_CODE)
++STATIC_ASSERT (
++ DHCP6_OPT_LEN_OFFSET (0) == 2,
++ "Offset of length is + 2 past start of option"
++ );
++
++#define DHCP6_OPT_DATA_OFFSET(a) (a + DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN)
++STATIC_ASSERT (
++ DHCP6_OPT_DATA_OFFSET (0) == 4,
++ "Offset to option data should be +4 from start of option"
++ );
++
+ #define DHCP6_PACKET_ALL 0
+ #define DHCP6_PACKET_STATEFUL 1
+ #define DHCP6_PACKET_STATELESS 2
+diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
+index dcd01e6268..bf5aa7a769 100644
+--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
+@@ -3,9 +3,9 @@
+
+ (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
++ Copyright (c) Microsoft Corporation
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+-
+ **/
+
+ #include "Dhcp6Impl.h"
+@@ -930,7 +930,8 @@ Dhcp6SendSolicitMsg (
+ //
+ Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);
+ if (Packet == NULL) {
+- return EFI_OUT_OF_RESOURCES;
++ Status = EFI_OUT_OF_RESOURCES;
++ goto ON_ERROR;
+ }
+
+ Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen;
+@@ -944,54 +945,64 @@ Dhcp6SendSolicitMsg (
+ Cursor = Packet->Dhcp6.Option;
+
+ Length = HTONS (ClientId->Length);
+- Cursor = Dhcp6AppendOption (
+- Cursor,
++ Status = Dhcp6AppendOption (
++ Packet,
++ &Cursor,
+ HTONS (Dhcp6OptClientId),
+ Length,
+ ClientId->Duid
+ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+
+- Cursor = Dhcp6AppendETOption (
+- Cursor,
++ Status = Dhcp6AppendETOption (
++ Packet,
++ &Cursor,
+ Instance,
+ &Elapsed
+ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+
+- Cursor = Dhcp6AppendIaOption (
+- Cursor,
++ Status = Dhcp6AppendIaOption (
++ Packet,
++ &Cursor,
+ Instance->IaCb.Ia,
+ Instance->IaCb.T1,
+ Instance->IaCb.T2,
+ Packet->Dhcp6.Header.MessageType
+ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+
+ //
+ // Append user-defined when configurate Dhcp6 service.
+ //
+ for (Index = 0; Index < Instance->Config->OptionCount; Index++) {
+ UserOpt = Instance->Config->OptionList[Index];
+- Cursor = Dhcp6AppendOption (
+- Cursor,
++ Status = Dhcp6AppendOption (
++ Packet,
++ &Cursor,
+ UserOpt->OpCode,
+ UserOpt->OpLen,
+ UserOpt->Data
+ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+ }
+
+- //
+- // Determine the size/length of packet.
+- //
+- Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
+ ASSERT (Packet->Size > Packet->Length + 8);
+
+ //
+ // Callback to user with the packet to be sent and check the user's feedback.
+ //
+ Status = Dhcp6CallbackUser (Instance, Dhcp6SendSolicit, &Packet);
+-
+ if (EFI_ERROR (Status)) {
+- FreePool (Packet);
+- return Status;
++ goto ON_ERROR;
+ }
+
+ //
+@@ -1005,10 +1016,8 @@ Dhcp6SendSolicitMsg (
+ Instance->StartTime = 0;
+
+ Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
+-
+ if (EFI_ERROR (Status)) {
+- FreePool (Packet);
+- return Status;
++ goto ON_ERROR;
+ }
+
+ //
+@@ -1020,6 +1029,14 @@ Dhcp6SendSolicitMsg (
+ Elapsed,
+ Instance->Config->SolicitRetransmission
+ );
++
++ON_ERROR:
++
++ if (Packet) {
++ FreePool (Packet);
++ }
++
++ return Status;
+ }
+
+ /**
+@@ -1110,7 +1127,8 @@ Dhcp6SendRequestMsg (
+ //
+ Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);
+ if (Packet == NULL) {
+- return EFI_OUT_OF_RESOURCES;
++ Status = EFI_OUT_OF_RESOURCES;
++ goto ON_ERROR;
+ }
+
+ Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen;
+@@ -1124,51 +1142,67 @@ Dhcp6SendRequestMsg (
+ Cursor = Packet->Dhcp6.Option;
+
+ Length = HTONS (ClientId->Length);
+- Cursor = Dhcp6AppendOption (
+- Cursor,
++ Status = Dhcp6AppendOption (
++ Packet,
++ &Cursor,
+ HTONS (Dhcp6OptClientId),
+ Length,
+ ClientId->Duid
+ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+
+- Cursor = Dhcp6AppendETOption (
+- Cursor,
++ Status = Dhcp6AppendETOption (
++ Packet,
++ &Cursor,
+ Instance,
+ &Elapsed
+ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+
+- Cursor = Dhcp6AppendOption (
+- Cursor,
++ Status = Dhcp6AppendOption (
++ Packet,
++ &Cursor,
+ HTONS (Dhcp6OptServerId),
+ ServerId->Length,
+ ServerId->Duid
+ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+
+- Cursor = Dhcp6AppendIaOption (
+- Cursor,
++ Status = Dhcp6AppendIaOption (
++ Packet,
++ &Cursor,
+ Instance->IaCb.Ia,
+ Instance->IaCb.T1,
+ Instance->IaCb.T2,
+ Packet->Dhcp6.Header.MessageType
+ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+
+ //
+ // Append user-defined when configurate Dhcp6 service.
+ //
+ for (Index = 0; Index < Instance->Config->OptionCount; Index++) {
+ UserOpt = Instance->Config->OptionList[Index];
+- Cursor = Dhcp6AppendOption (
+- Cursor,
++ Status = Dhcp6AppendOption (
++ Packet,
++ &Cursor,
+ UserOpt->OpCode,
+ UserOpt->OpLen,
+ UserOpt->Data
+ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+ }
+
+- //
+- // Determine the size/length of packet.
+- //
+- Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
+ ASSERT (Packet->Size > Packet->Length + 8);
+
+ //
+@@ -1177,8 +1211,7 @@ Dhcp6SendRequestMsg (
+ Status = Dhcp6CallbackUser (Instance, Dhcp6SendRequest, &Packet);
+
+ if (EFI_ERROR (Status)) {
+- FreePool (Packet);
+- return Status;
++ goto ON_ERROR;
+ }
+
+ //
+@@ -1194,14 +1227,21 @@ Dhcp6SendRequestMsg (
+ Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
+
+ if (EFI_ERROR (Status)) {
+- FreePool (Packet);
+- return Status;
++ goto ON_ERROR;
+ }
+
+ //
+ // Enqueue the sent packet for the retransmission in case reply timeout.
+ //
+ return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);
++
++ON_ERROR:
++
++ if (Packet) {
++ FreePool (Packet);
++ }
++
++ return Status;
+ }
+
+ /**
+@@ -1266,7 +1306,8 @@ Dhcp6SendDeclineMsg (
+ //
+ Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE);
+ if (Packet == NULL) {
+- return EFI_OUT_OF_RESOURCES;
++ Status = EFI_OUT_OF_RESOURCES;
++ goto ON_ERROR;
+ }
+
+ Packet->Size = DHCP6_BASE_PACKET_SIZE;
+@@ -1280,42 +1321,58 @@ Dhcp6SendDeclineMsg (
+ Cursor = Packet->Dhcp6.Option;
+
+ Length = HTONS (ClientId->Length);
+- Cursor = Dhcp6AppendOption (
+- Cursor,
++ Status = Dhcp6AppendOption (
++ Packet,
++ &Cursor,
+ HTONS (Dhcp6OptClientId),
+ Length,
+ ClientId->Duid
+ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+
+- Cursor = Dhcp6AppendETOption (
+- Cursor,
++ Status = Dhcp6AppendETOption (
++ Packet,
++ &Cursor,
+ Instance,
+ &Elapsed
+ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+
+- Cursor = Dhcp6AppendOption (
+- Cursor,
++ Status = Dhcp6AppendOption (
++ Packet,
++ &Cursor,
+ HTONS (Dhcp6OptServerId),
+ ServerId->Length,
+ ServerId->Duid
+ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+
+- Cursor = Dhcp6AppendIaOption (Cursor, DecIa, 0, 0, Packet->Dhcp6.Header.MessageType);
++ Status = Dhcp6AppendIaOption (
++ Packet,
++ &Cursor,
++ DecIa,
++ 0,
++ 0,
++ Packet->Dhcp6.Header.MessageType
++ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+
+- //
+- // Determine the size/length of packet.
+- //
+- Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
+ ASSERT (Packet->Size > Packet->Length + 8);
+
+ //
+ // Callback to user with the packet to be sent and check the user's feedback.
+ //
+ Status = Dhcp6CallbackUser (Instance, Dhcp6SendDecline, &Packet);
+-
+ if (EFI_ERROR (Status)) {
+- FreePool (Packet);
+- return Status;
++ goto ON_ERROR;
+ }
+
+ //
+@@ -1329,16 +1386,22 @@ Dhcp6SendDeclineMsg (
+ Instance->StartTime = 0;
+
+ Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
+-
+ if (EFI_ERROR (Status)) {
+- FreePool (Packet);
+- return Status;
++ goto ON_ERROR;
+ }
+
+ //
+ // Enqueue the sent packet for the retransmission in case reply timeout.
+ //
+ return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);
++
++ON_ERROR:
++
++ if (Packet) {
++ FreePool (Packet);
++ }
++
++ return Status;
+ }
+
+ /**
+@@ -1399,7 +1462,8 @@ Dhcp6SendReleaseMsg (
+ //
+ Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE);
+ if (Packet == NULL) {
+- return EFI_OUT_OF_RESOURCES;
++ Status = EFI_OUT_OF_RESOURCES;
++ goto ON_ERROR;
+ }
+
+ Packet->Size = DHCP6_BASE_PACKET_SIZE;
+@@ -1413,45 +1477,61 @@ Dhcp6SendReleaseMsg (
+ Cursor = Packet->Dhcp6.Option;
+
+ Length = HTONS (ClientId->Length);
+- Cursor = Dhcp6AppendOption (
+- Cursor,
++ Status = Dhcp6AppendOption (
++ Packet,
++ &Cursor,
+ HTONS (Dhcp6OptClientId),
+ Length,
+ ClientId->Duid
+ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+
+ //
+ // ServerId is extracted from packet, it's network order.
+ //
+- Cursor = Dhcp6AppendOption (
+- Cursor,
++ Status = Dhcp6AppendOption (
++ Packet,
++ &Cursor,
+ HTONS (Dhcp6OptServerId),
+ ServerId->Length,
+ ServerId->Duid
+ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+
+- Cursor = Dhcp6AppendETOption (
+- Cursor,
++ Status = Dhcp6AppendETOption (
++ Packet,
++ &Cursor,
+ Instance,
+ &Elapsed
+ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+
+- Cursor = Dhcp6AppendIaOption (Cursor, RelIa, 0, 0, Packet->Dhcp6.Header.MessageType);
++ Status = Dhcp6AppendIaOption (
++ Packet,
++ &Cursor,
++ RelIa,
++ 0,
++ 0,
++ Packet->Dhcp6.Header.MessageType
++ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+
+- //
+- // Determine the size/length of packet
+- //
+- Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
+ ASSERT (Packet->Size > Packet->Length + 8);
+
+ //
+ // Callback to user with the packet to be sent and check the user's feedback.
+ //
+ Status = Dhcp6CallbackUser (Instance, Dhcp6SendRelease, &Packet);
+-
+ if (EFI_ERROR (Status)) {
+- FreePool (Packet);
+- return Status;
++ goto ON_ERROR;
+ }
+
+ //
+@@ -1461,16 +1541,22 @@ Dhcp6SendReleaseMsg (
+ Instance->IaCb.Ia->State = Dhcp6Releasing;
+
+ Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
+-
+ if (EFI_ERROR (Status)) {
+- FreePool (Packet);
+- return Status;
++ goto ON_ERROR;
+ }
+
+ //
+ // Enqueue the sent packet for the retransmission in case reply timeout.
+ //
+ return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);
++
++ON_ERROR:
++
++ if (Packet) {
++ FreePool (Packet);
++ }
++
++ return Status;
+ }
+
+ /**
+@@ -1529,7 +1615,8 @@ Dhcp6SendRenewRebindMsg (
+ //
+ Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);
+ if (Packet == NULL) {
+- return EFI_OUT_OF_RESOURCES;
++ Status = EFI_OUT_OF_RESOURCES;
++ goto ON_ERROR;
+ }
+
+ Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen;
+@@ -1543,26 +1630,38 @@ Dhcp6SendRenewRebindMsg (
+ Cursor = Packet->Dhcp6.Option;
+
+ Length = HTONS (ClientId->Length);
+- Cursor = Dhcp6AppendOption (
+- Cursor,
++ Status = Dhcp6AppendOption (
++ Packet,
++ &Cursor,
+ HTONS (Dhcp6OptClientId),
+ Length,
+ ClientId->Duid
+ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+
+- Cursor = Dhcp6AppendETOption (
+- Cursor,
++ Status = Dhcp6AppendETOption (
++ Packet,
++ &Cursor,
+ Instance,
+ &Elapsed
+ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+
+- Cursor = Dhcp6AppendIaOption (
+- Cursor,
++ Status = Dhcp6AppendIaOption (
++ Packet,
++ &Cursor,
+ Instance->IaCb.Ia,
+ Instance->IaCb.T1,
+ Instance->IaCb.T2,
+ Packet->Dhcp6.Header.MessageType
+ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+
+ if (!RebindRequest) {
+ //
+@@ -1578,18 +1677,22 @@ Dhcp6SendRenewRebindMsg (
+ Dhcp6OptServerId
+ );
+ if (Option == NULL) {
+- FreePool (Packet);
+- return EFI_DEVICE_ERROR;
++ Status = EFI_DEVICE_ERROR;
++ goto ON_ERROR;
+ }
+
+ ServerId = (EFI_DHCP6_DUID *)(Option + 2);
+
+- Cursor = Dhcp6AppendOption (
+- Cursor,
++ Status = Dhcp6AppendOption (
++ Packet,
++ &Cursor,
+ HTONS (Dhcp6OptServerId),
+ ServerId->Length,
+ ServerId->Duid
+ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+ }
+
+ //
+@@ -1597,18 +1700,18 @@ Dhcp6SendRenewRebindMsg (
+ //
+ for (Index = 0; Index < Instance->Config->OptionCount; Index++) {
+ UserOpt = Instance->Config->OptionList[Index];
+- Cursor = Dhcp6AppendOption (
+- Cursor,
++ Status = Dhcp6AppendOption (
++ Packet,
++ &Cursor,
+ UserOpt->OpCode,
+ UserOpt->OpLen,
+ UserOpt->Data
+ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+ }
+
+- //
+- // Determine the size/length of packet.
+- //
+- Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
+ ASSERT (Packet->Size > Packet->Length + 8);
+
+ //
+@@ -1618,10 +1721,8 @@ Dhcp6SendRenewRebindMsg (
+ Event = (RebindRequest) ? Dhcp6EnterRebinding : Dhcp6EnterRenewing;
+
+ Status = Dhcp6CallbackUser (Instance, Event, &Packet);
+-
+ if (EFI_ERROR (Status)) {
+- FreePool (Packet);
+- return Status;
++ goto ON_ERROR;
+ }
+
+ //
+@@ -1638,16 +1739,22 @@ Dhcp6SendRenewRebindMsg (
+ Instance->StartTime = 0;
+
+ Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
+-
+ if (EFI_ERROR (Status)) {
+- FreePool (Packet);
+- return Status;
++ goto ON_ERROR;
+ }
+
+ //
+ // Enqueue the sent packet for the retransmission in case reply timeout.
+ //
+ return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);
++
++ON_ERROR:
++
++ if (Packet) {
++ FreePool (Packet);
++ }
++
++ return Status;
+ }
+
+ /**
+@@ -1811,7 +1918,8 @@ Dhcp6SendInfoRequestMsg (
+ //
+ Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);
+ if (Packet == NULL) {
+- return EFI_OUT_OF_RESOURCES;
++ Status = EFI_OUT_OF_RESOURCES;
++ goto ON_ERROR;
+ }
+
+ Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen;
+@@ -1828,44 +1936,56 @@ Dhcp6SendInfoRequestMsg (
+
+ if (SendClientId) {
+ Length = HTONS (ClientId->Length);
+- Cursor = Dhcp6AppendOption (
+- Cursor,
++ Status = Dhcp6AppendOption (
++ Packet,
++ &Cursor,
+ HTONS (Dhcp6OptClientId),
+ Length,
+ ClientId->Duid
+ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+ }
+
+- Cursor = Dhcp6AppendETOption (
+- Cursor,
++ Status = Dhcp6AppendETOption (
++ Packet,
++ &Cursor,
+ Instance,
+ &Elapsed
+ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+
+- Cursor = Dhcp6AppendOption (
+- Cursor,
++ Status = Dhcp6AppendOption (
++ Packet,
++ &Cursor,
+ OptionRequest->OpCode,
+ OptionRequest->OpLen,
+ OptionRequest->Data
+ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+
+ //
+ // Append user-defined when configurate Dhcp6 service.
+ //
+ for (Index = 0; Index < OptionCount; Index++) {
+ UserOpt = OptionList[Index];
+- Cursor = Dhcp6AppendOption (
+- Cursor,
++ Status = Dhcp6AppendOption (
++ Packet,
++ &Cursor,
+ UserOpt->OpCode,
+ UserOpt->OpLen,
+ UserOpt->Data
+ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+ }
+
+- //
+- // Determine the size/length of packet.
+- //
+- Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
+ ASSERT (Packet->Size > Packet->Length + 8);
+
+ //
+@@ -1877,16 +1997,22 @@ Dhcp6SendInfoRequestMsg (
+ // Send info-request packet with no state.
+ //
+ Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
+-
+ if (EFI_ERROR (Status)) {
+- FreePool (Packet);
+- return Status;
++ goto ON_ERROR;
+ }
+
+ //
+ // Enqueue the sent packet for the retransmission in case reply timeout.
+ //
+ return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, Retransmission);
++
++ON_ERROR:
++
++ if (Packet) {
++ FreePool (Packet);
++ }
++
++ return Status;
+ }
+
+ /**
+@@ -1937,7 +2063,8 @@ Dhcp6SendConfirmMsg (
+ //
+ Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);
+ if (Packet == NULL) {
+- return EFI_OUT_OF_RESOURCES;
++ Status = EFI_OUT_OF_RESOURCES;
++ goto ON_ERROR;
+ }
+
+ Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen;
+@@ -1951,54 +2078,64 @@ Dhcp6SendConfirmMsg (
+ Cursor = Packet->Dhcp6.Option;
+
+ Length = HTONS (ClientId->Length);
+- Cursor = Dhcp6AppendOption (
+- Cursor,
++ Status = Dhcp6AppendOption (
++ Packet,
++ &Cursor,
+ HTONS (Dhcp6OptClientId),
+ Length,
+ ClientId->Duid
+ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+
+- Cursor = Dhcp6AppendETOption (
+- Cursor,
++ Status = Dhcp6AppendETOption (
++ Packet,
++ &Cursor,
+ Instance,
+ &Elapsed
+ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+
+- Cursor = Dhcp6AppendIaOption (
+- Cursor,
++ Status = Dhcp6AppendIaOption (
++ Packet,
++ &Cursor,
+ Instance->IaCb.Ia,
+ Instance->IaCb.T1,
+ Instance->IaCb.T2,
+ Packet->Dhcp6.Header.MessageType
+ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+
+ //
+ // Append user-defined when configurate Dhcp6 service.
+ //
+ for (Index = 0; Index < Instance->Config->OptionCount; Index++) {
+ UserOpt = Instance->Config->OptionList[Index];
+- Cursor = Dhcp6AppendOption (
+- Cursor,
++ Status = Dhcp6AppendOption (
++ Packet,
++ &Cursor,
+ UserOpt->OpCode,
+ UserOpt->OpLen,
+ UserOpt->Data
+ );
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
+ }
+
+- //
+- // Determine the size/length of packet.
+- //
+- Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
+ ASSERT (Packet->Size > Packet->Length + 8);
+
+ //
+ // Callback to user with the packet to be sent and check the user's feedback.
+ //
+ Status = Dhcp6CallbackUser (Instance, Dhcp6SendConfirm, &Packet);
+-
+ if (EFI_ERROR (Status)) {
+- FreePool (Packet);
+- return Status;
++ goto ON_ERROR;
+ }
+
+ //
+@@ -2012,16 +2149,22 @@ Dhcp6SendConfirmMsg (
+ Instance->StartTime = 0;
+
+ Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
+-
+ if (EFI_ERROR (Status)) {
+- FreePool (Packet);
+- return Status;
++ goto ON_ERROR;
+ }
+
+ //
+ // Enqueue the sent packet for the retransmission in case reply timeout.
+ //
+ return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);
++
++ON_ERROR:
++
++ if (Packet) {
++ FreePool (Packet);
++ }
++
++ return Status;
+ }
+
+ /**
+diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c
+index e6368b5b1c..705c665c51 100644
+--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c
++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c
+@@ -577,24 +577,33 @@ Dhcp6OnTransmitted (
+ }
+
+ /**
+- Append the option to Buf, and move Buf to the end.
++ Append the option to Buf, update the length of packet, and move Buf to the end.
+
+- @param[in, out] Buf The pointer to the buffer.
+- @param[in] OptType The option type.
+- @param[in] OptLen The length of option contents.
+- @param[in] Data The pointer to the option content.
++ @param[in, out] Packet A pointer to the packet, on success Packet->Length
++ will be updated.
++ @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor
++ will be moved to the end of the option.
++ @param[in] OptType The option type.
++ @param[in] OptLen The length of option contents.
++ @param[in] Data The pointer to the option content.
+
+- @return Buf The position to append the next option.
++ @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid
++ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option.
++ @retval EFI_SUCCESS The option is appended successfully.
+
+ **/
+-UINT8 *
++EFI_STATUS
+ Dhcp6AppendOption (
+- IN OUT UINT8 *Buf,
+- IN UINT16 OptType,
+- IN UINT16 OptLen,
+- IN UINT8 *Data
++ IN OUT EFI_DHCP6_PACKET *Packet,
++ IN OUT UINT8 **PacketCursor,
++ IN UINT16 OptType,
++ IN UINT16 OptLen,
++ IN UINT8 *Data
+ )
+ {
++ UINT32 Length;
++ UINT32 BytesNeeded;
++
+ //
+ // The format of Dhcp6 option:
+ //
+@@ -607,35 +616,95 @@ Dhcp6AppendOption (
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ //
+
+- ASSERT (OptLen != 0);
++ //
++ // Verify the arguments are valid
++ //
++ if (Packet == NULL) {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ if ((PacketCursor == NULL) || (*PacketCursor == NULL)) {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ if (Data == NULL) {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ if (OptLen == 0) {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ //
++ // Verify the PacketCursor is within the packet
++ //
++ if ( (*PacketCursor < Packet->Dhcp6.Option)
++ || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))
++ {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ //
++ // Calculate the bytes needed for the option
++ //
++ BytesNeeded = DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN + NTOHS (OptLen);
++
++ //
++ // Space remaining in the packet
++ //
++ Length = Packet->Size - Packet->Length;
++ if (Length < BytesNeeded) {
++ return EFI_BUFFER_TOO_SMALL;
++ }
++
++ //
++ // Verify the PacketCursor is within the packet
++ //
++ if ( (*PacketCursor < Packet->Dhcp6.Option)
++ || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))
++ {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ WriteUnaligned16 ((UINT16 *)*PacketCursor, OptType);
++ *PacketCursor += DHCP6_SIZE_OF_OPT_CODE;
++ WriteUnaligned16 ((UINT16 *)*PacketCursor, OptLen);
++ *PacketCursor += DHCP6_SIZE_OF_OPT_LEN;
++ CopyMem (*PacketCursor, Data, NTOHS (OptLen));
++ *PacketCursor += NTOHS (OptLen);
+
+- WriteUnaligned16 ((UINT16 *)Buf, OptType);
+- Buf += 2;
+- WriteUnaligned16 ((UINT16 *)Buf, OptLen);
+- Buf += 2;
+- CopyMem (Buf, Data, NTOHS (OptLen));
+- Buf += NTOHS (OptLen);
++ // Update the packet length by the length of the option + 4 bytes
++ Packet->Length += BytesNeeded;
+
+- return Buf;
++ return EFI_SUCCESS;
+ }
+
+ /**
+ Append the appointed IA Address option to Buf, and move Buf to the end.
+
+- @param[in, out] Buf The pointer to the position to append.
++ @param[in, out] Packet A pointer to the packet, on success Packet->Length
++ will be updated.
++ @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor
++ will be moved to the end of the option.
+ @param[in] IaAddr The pointer to the IA Address.
+ @param[in] MessageType Message type of DHCP6 package.
+
+- @return Buf The position to append the next option.
++ @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid
++ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option.
++ @retval EFI_SUCCESS The option is appended successfully.
+
+ **/
+-UINT8 *
++EFI_STATUS
+ Dhcp6AppendIaAddrOption (
+- IN OUT UINT8 *Buf,
++ IN OUT EFI_DHCP6_PACKET *Packet,
++ IN OUT UINT8 **PacketCursor,
+ IN EFI_DHCP6_IA_ADDRESS *IaAddr,
+ IN UINT32 MessageType
+ )
+ {
++ UINT32 BytesNeeded;
++ UINT32 Length;
++
+ // The format of the IA Address option is:
+ //
+ // 0 1 2 3
+@@ -657,17 +726,60 @@ Dhcp6AppendIaAddrOption (
+ // . .
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
++ //
++ // Verify the arguments are valid
++ //
++ if (Packet == NULL) {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ if ((PacketCursor == NULL) || (*PacketCursor == NULL)) {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ if (IaAddr == NULL) {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ //
++ // Verify the PacketCursor is within the packet
++ //
++ if ( (*PacketCursor < Packet->Dhcp6.Option)
++ || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))
++ {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ BytesNeeded = DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN;
++ BytesNeeded += sizeof (EFI_IPv6_ADDRESS);
++ //
++ // Even if the preferred-lifetime is 0, it still needs to store it.
++ //
++ BytesNeeded += sizeof (IaAddr->PreferredLifetime);
++ //
++ // Even if the valid-lifetime is 0, it still needs to store it.
++ //
++ BytesNeeded += sizeof (IaAddr->ValidLifetime);
++
++ //
++ // Space remaining in the packet
++ //
++ Length = Packet->Size - Packet->Length;
++ if (Length < BytesNeeded) {
++ return EFI_BUFFER_TOO_SMALL;
++ }
++
+ //
+ // Fill the value of Ia Address option type
+ //
+- WriteUnaligned16 ((UINT16 *)Buf, HTONS (Dhcp6OptIaAddr));
+- Buf += 2;
++ WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (Dhcp6OptIaAddr));
++ *PacketCursor += DHCP6_SIZE_OF_OPT_CODE;
+
+- WriteUnaligned16 ((UINT16 *)Buf, HTONS (sizeof (EFI_DHCP6_IA_ADDRESS)));
+- Buf += 2;
++ WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (sizeof (EFI_DHCP6_IA_ADDRESS)));
++ *PacketCursor += DHCP6_SIZE_OF_OPT_LEN;
+
+- CopyMem (Buf, &IaAddr->IpAddress, sizeof (EFI_IPv6_ADDRESS));
+- Buf += sizeof (EFI_IPv6_ADDRESS);
++ CopyMem (*PacketCursor, &IaAddr->IpAddress, sizeof (EFI_IPv6_ADDRESS));
++ *PacketCursor += sizeof (EFI_IPv6_ADDRESS);
+
+ //
+ // Fill the value of preferred-lifetime and valid-lifetime.
+@@ -675,44 +787,58 @@ Dhcp6AppendIaAddrOption (
+ // should set to 0 when initiate a Confirm message.
+ //
+ if (MessageType != Dhcp6MsgConfirm) {
+- WriteUnaligned32 ((UINT32 *)Buf, HTONL (IaAddr->PreferredLifetime));
++ WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL (IaAddr->PreferredLifetime));
+ }
+
+- Buf += 4;
++ *PacketCursor += sizeof (IaAddr->PreferredLifetime);
+
+ if (MessageType != Dhcp6MsgConfirm) {
+- WriteUnaligned32 ((UINT32 *)Buf, HTONL (IaAddr->ValidLifetime));
++ WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL (IaAddr->ValidLifetime));
+ }
+
+- Buf += 4;
++ *PacketCursor += sizeof (IaAddr->ValidLifetime);
++
++ //
++ // Update the packet length
++ //
++ Packet->Length += BytesNeeded;
+
+- return Buf;
++ return EFI_SUCCESS;
+ }
+
+ /**
+ Append the appointed Ia option to Buf, and move Buf to the end.
+
+- @param[in, out] Buf The pointer to the position to append.
++ @param[in, out] Packet A pointer to the packet, on success Packet->Length
++ will be updated.
++ @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor
++ will be moved to the end of the option.
+ @param[in] Ia The pointer to the Ia.
+ @param[in] T1 The time of T1.
+ @param[in] T2 The time of T2.
+ @param[in] MessageType Message type of DHCP6 package.
+
+- @return Buf The position to append the next Ia option.
++ @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid
++ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option.
++ @retval EFI_SUCCESS The option is appended successfully.
+
+ **/
+-UINT8 *
++EFI_STATUS
+ Dhcp6AppendIaOption (
+- IN OUT UINT8 *Buf,
+- IN EFI_DHCP6_IA *Ia,
+- IN UINT32 T1,
+- IN UINT32 T2,
+- IN UINT32 MessageType
++ IN OUT EFI_DHCP6_PACKET *Packet,
++ IN OUT UINT8 **PacketCursor,
++ IN EFI_DHCP6_IA *Ia,
++ IN UINT32 T1,
++ IN UINT32 T2,
++ IN UINT32 MessageType
+ )
+ {
+- UINT8 *AddrOpt;
+- UINT16 *Len;
+- UINTN Index;
++ UINT8 *AddrOpt;
++ UINT16 *Len;
++ UINTN Index;
++ UINT32 BytesNeeded;
++ UINT32 Length;
++ EFI_STATUS Status;
+
+ //
+ // The format of IA_NA and IA_TA option:
+@@ -733,32 +859,74 @@ Dhcp6AppendIaOption (
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ //
+
++ //
++ // Verify the arguments are valid
++ //
++ if (Packet == NULL) {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ if ((PacketCursor == NULL) || (*PacketCursor == NULL)) {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ if (Ia == NULL) {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ //
++ // Verify the PacketCursor is within the packet
++ //
++ if ( (*PacketCursor < Packet->Dhcp6.Option)
++ || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))
++ {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ BytesNeeded = DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN;
++ BytesNeeded += sizeof (Ia->Descriptor.IaId);
++ //
++ // + N for the IA_NA-options/IA_TA-options
++ // Dhcp6AppendIaAddrOption will need to check the length for each address
++ //
++ if (Ia->Descriptor.Type == Dhcp6OptIana) {
++ BytesNeeded += sizeof (T1) + sizeof (T2);
++ }
++
++ //
++ // Space remaining in the packet
++ //
++ Length = (UINT16)(Packet->Size - Packet->Length);
++ if (Length < BytesNeeded) {
++ return EFI_BUFFER_TOO_SMALL;
++ }
++
+ //
+ // Fill the value of Ia option type
+ //
+- WriteUnaligned16 ((UINT16 *)Buf, HTONS (Ia->Descriptor.Type));
+- Buf += 2;
++ WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (Ia->Descriptor.Type));
++ *PacketCursor += DHCP6_SIZE_OF_OPT_CODE;
+
+ //
+ // Fill the len of Ia option later, keep the pointer first
+ //
+- Len = (UINT16 *)Buf;
+- Buf += 2;
++ Len = (UINT16 *)*PacketCursor;
++ *PacketCursor += DHCP6_SIZE_OF_OPT_LEN;
+
+ //
+ // Fill the value of iaid
+ //
+- WriteUnaligned32 ((UINT32 *)Buf, HTONL (Ia->Descriptor.IaId));
+- Buf += 4;
++ WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL (Ia->Descriptor.IaId));
++ *PacketCursor += sizeof (Ia->Descriptor.IaId);
+
+ //
+ // Fill the value of t1 and t2 if iana, keep it 0xffffffff if no specified.
+ //
+ if (Ia->Descriptor.Type == Dhcp6OptIana) {
+- WriteUnaligned32 ((UINT32 *)Buf, HTONL ((T1 != 0) ? T1 : 0xffffffff));
+- Buf += 4;
+- WriteUnaligned32 ((UINT32 *)Buf, HTONL ((T2 != 0) ? T2 : 0xffffffff));
+- Buf += 4;
++ WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL ((T1 != 0) ? T1 : 0xffffffff));
++ *PacketCursor += sizeof (T1);
++ WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL ((T2 != 0) ? T2 : 0xffffffff));
++ *PacketCursor += sizeof (T2);
+ }
+
+ //
+@@ -766,35 +934,51 @@ Dhcp6AppendIaOption (
+ //
+ for (Index = 0; Index < Ia->IaAddressCount; Index++) {
+ AddrOpt = (UINT8 *)Ia->IaAddress + Index * sizeof (EFI_DHCP6_IA_ADDRESS);
+- Buf = Dhcp6AppendIaAddrOption (Buf, (EFI_DHCP6_IA_ADDRESS *)AddrOpt, MessageType);
++ Status = Dhcp6AppendIaAddrOption (Packet, PacketCursor, (EFI_DHCP6_IA_ADDRESS *)AddrOpt, MessageType);
++ if (EFI_ERROR (Status)) {
++ return Status;
++ }
+ }
+
+ //
+ // Fill the value of Ia option length
+ //
+- *Len = HTONS ((UINT16)(Buf - (UINT8 *)Len - 2));
++ *Len = HTONS ((UINT16)(*PacketCursor - (UINT8 *)Len - 2));
+
+- return Buf;
++ //
++ // Update the packet length
++ //
++ Packet->Length += BytesNeeded;
++
++ return EFI_SUCCESS;
+ }
+
+ /**
+ Append the appointed Elapsed time option to Buf, and move Buf to the end.
+
+- @param[in, out] Buf The pointer to the position to append.
++ @param[in, out] Packet A pointer to the packet, on success Packet->Length
++ @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor
++ will be moved to the end of the option.
+ @param[in] Instance The pointer to the Dhcp6 instance.
+ @param[out] Elapsed The pointer to the elapsed time value in
+- the generated packet.
++ the generated packet.
+
+- @return Buf The position to append the next Ia option.
++ @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid
++ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option.
++ @retval EFI_SUCCESS The option is appended successfully.
+
+ **/
+-UINT8 *
++EFI_STATUS
+ Dhcp6AppendETOption (
+- IN OUT UINT8 *Buf,
+- IN DHCP6_INSTANCE *Instance,
+- OUT UINT16 **Elapsed
++ IN OUT EFI_DHCP6_PACKET *Packet,
++ IN OUT UINT8 **PacketCursor,
++ IN DHCP6_INSTANCE *Instance,
++ OUT UINT16 **Elapsed
+ )
+ {
++ UINT32 BytesNeeded;
++ UINT32 Length;
++
+ //
+ // The format of elapsed time option:
+ //
+@@ -806,27 +990,70 @@ Dhcp6AppendETOption (
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ //
+
++ //
++ // Verify the arguments are valid
++ //
++ if (Packet == NULL) {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ if ((PacketCursor == NULL) || (*PacketCursor == NULL)) {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ if (Instance == NULL) {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ if ((Elapsed == NULL)) {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ //
++ // Verify the PacketCursor is within the packet
++ //
++ if ( (*PacketCursor < Packet->Dhcp6.Option)
++ || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))
++ {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ BytesNeeded = DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN;
++ //
++ // + 2 for elapsed-time
++ //
++ BytesNeeded += sizeof (UINT16);
++ //
++ // Space remaining in the packet
++ //
++ Length = Packet->Size - Packet->Length;
++ if (Length < BytesNeeded) {
++ return EFI_BUFFER_TOO_SMALL;
++ }
++
+ //
+ // Fill the value of elapsed-time option type.
+ //
+- WriteUnaligned16 ((UINT16 *)Buf, HTONS (Dhcp6OptElapsedTime));
+- Buf += 2;
++ WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (Dhcp6OptElapsedTime));
++ *PacketCursor += DHCP6_SIZE_OF_OPT_CODE;
+
+ //
+ // Fill the len of elapsed-time option, which is fixed.
+ //
+- WriteUnaligned16 ((UINT16 *)Buf, HTONS (2));
+- Buf += 2;
++ WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (2));
++ *PacketCursor += DHCP6_SIZE_OF_OPT_LEN;
+
+ //
+ // Fill in elapsed time value with 0 value for now. The actual value is
+ // filled in later just before the packet is transmitted.
+ //
+- WriteUnaligned16 ((UINT16 *)Buf, HTONS (0));
+- *Elapsed = (UINT16 *)Buf;
+- Buf += 2;
++ WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (0));
++ *Elapsed = (UINT16 *)*PacketCursor;
++ *PacketCursor += sizeof (UINT16);
+
+- return Buf;
++ Packet->Length += BytesNeeded;
++
++ return EFI_SUCCESS;
+ }
+
+ /**
+diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h
+index 046454ff4a..06947f6c1f 100644
+--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h
++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h
+@@ -160,69 +160,85 @@ Dhcp6OnTransmitted (
+ );
+
+ /**
+- Append the appointed option to the buf, and move the buf to the end.
+-
+- @param[in, out] Buf The pointer to buffer.
+- @param[in] OptType The option type.
+- @param[in] OptLen The length of option content.s
+- @param[in] Data The pointer to the option content.
+-
+- @return Buf The position to append the next option.
+-
++ Append the option to Buf, update the length of packet, and move Buf to the end.
++
++ @param[in, out] Packet A pointer to the packet, on success Packet->Length
++ will be updated.
++ @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor
++ will be moved to the end of the option.
++ @param[in] OptType The option type.
++ @param[in] OptLen The length of option contents.
++ @param[in] Data The pointer to the option content.
++
++ @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid
++ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option.
++ @retval EFI_SUCCESS The option is appended successfully.
+ **/
+-UINT8 *
++EFI_STATUS
+ Dhcp6AppendOption (
+- IN OUT UINT8 *Buf,
+- IN UINT16 OptType,
+- IN UINT16 OptLen,
+- IN UINT8 *Data
++ IN OUT EFI_DHCP6_PACKET *Packet,
++ IN OUT UINT8 **PacketCursor,
++ IN UINT16 OptType,
++ IN UINT16 OptLen,
++ IN UINT8 *Data
+ );
+
+ /**
+- Append the Ia option to Buf, and move Buf to the end.
+-
+- @param[in, out] Buf The pointer to the position to append.
++ Append the appointed Ia option to Buf, update the Ia option length, and move Buf
++ to the end of the option.
++ @param[in, out] Packet A pointer to the packet, on success Packet->Length
++ will be updated.
++ @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor
++ will be moved to the end of the option.
+ @param[in] Ia The pointer to the Ia.
+ @param[in] T1 The time of T1.
+ @param[in] T2 The time of T2.
+ @param[in] MessageType Message type of DHCP6 package.
+
+- @return Buf The position to append the next Ia option.
+-
++ @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid
++ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option.
++ @retval EFI_SUCCESS The option is appended successfully.
+ **/
+-UINT8 *
++EFI_STATUS
+ Dhcp6AppendIaOption (
+- IN OUT UINT8 *Buf,
+- IN EFI_DHCP6_IA *Ia,
+- IN UINT32 T1,
+- IN UINT32 T2,
+- IN UINT32 MessageType
++ IN OUT EFI_DHCP6_PACKET *Packet,
++ IN OUT UINT8 **PacketCursor,
++ IN EFI_DHCP6_IA *Ia,
++ IN UINT32 T1,
++ IN UINT32 T2,
++ IN UINT32 MessageType
+ );
+
+ /**
+ Append the appointed Elapsed time option to Buf, and move Buf to the end.
+
+- @param[in, out] Buf The pointer to the position to append.
++ @param[in, out] Packet A pointer to the packet, on success Packet->Length
++ @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor
++ will be moved to the end of the option.
+ @param[in] Instance The pointer to the Dhcp6 instance.
+ @param[out] Elapsed The pointer to the elapsed time value in
+ the generated packet.
+
+- @return Buf The position to append the next Ia option.
++ @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid
++ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option.
++ @retval EFI_SUCCESS The option is appended successfully.
+
+ **/
+-UINT8 *
++EFI_STATUS
+ Dhcp6AppendETOption (
+- IN OUT UINT8 *Buf,
+- IN DHCP6_INSTANCE *Instance,
+- OUT UINT16 **Elapsed
++ IN OUT EFI_DHCP6_PACKET *Packet,
++ IN OUT UINT8 **PacketCursor,
++ IN DHCP6_INSTANCE *Instance,
++ OUT UINT16 **Elapsed
+ );
+
+ /**
+ Set the elapsed time based on the given instance and the pointer to the
+ elapsed time option.
+
+- @param[in] Elapsed The pointer to the position to append.
+- @param[in] Instance The pointer to the Dhcp6 instance.
++ @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid
++ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option.
++ @retval EFI_SUCCESS The option is appended successfully.
+ **/
+ VOID
+ SetElapsedTime (
+--
+2.40.0
+
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2023-45230-0002.patch b/meta/recipes-core/ovmf/ovmf/CVE-2023-45230-0002.patch
new file mode 100644
index 0000000000..1f891f8007
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/CVE-2023-45230-0002.patch
@@ -0,0 +1,604 @@
+From 5f3658197bf29c83b3349b0ab1d99cdb0c3814bc Mon Sep 17 00:00:00 2001
+From: "Doug Flick via groups.io" <dougflick=microsoft.com@groups.io>
+Date: Fri, 26 Jan 2024 05:54:45 +0800
+Subject: [PATCH] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Unit
+ Tests
+
+REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4535
+
+Confirms that reported issue...
+
+"Buffer overflow in the DHCPv6 client via a long Server ID option"
+
+..has been corrected by the provided patch.
+
+Tests the following functions to ensure they appropriately handle
+untrusted data (either too long or too small) to prevent a buffer
+overflow:
+
+Dhcp6AppendOption
+Dhcp6AppendETOption
+Dhcp6AppendIaOption
+
+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-45230
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/5f3658197bf29c83b3349b0ab1d99cdb0c3814bc]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ .../GoogleTest/Dhcp6DxeGoogleTest.cpp | 20 +
+ .../GoogleTest/Dhcp6DxeGoogleTest.inf | 43 ++
+ .../Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp | 478 ++++++++++++++++++
+ 3 files changed, 541 insertions(+)
+ create mode 100644 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp
+ create mode 100644 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
+ create mode 100644 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp
+
+diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp
+new file mode 100644
+index 0000000000..9aeced2f91
+--- /dev/null
++++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp
+@@ -0,0 +1,20 @@
++/** @file
++ Acts as the main entry point for the tests for the Dhcp6Dxe module.
++
++ Copyright (c) Microsoft Corporation
++ SPDX-License-Identifier: BSD-2-Clause-Patent
++**/
++#include <gtest/gtest.h>
++
++////////////////////////////////////////////////////////////////////////////////
++// Run the tests
++////////////////////////////////////////////////////////////////////////////////
++int
++main (
++ int argc,
++ char *argv[]
++ )
++{
++ testing::InitGoogleTest (&argc, argv);
++ return RUN_ALL_TESTS ();
++}
+diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
+new file mode 100644
+index 0000000000..8e9119a371
+--- /dev/null
++++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
+@@ -0,0 +1,43 @@
++## @file
++# Unit test suite for the Dhcp6Dxe using Google Test
++#
++# Copyright (c) Microsoft Corporation.<BR>
++# SPDX-License-Identifier: BSD-2-Clause-Patent
++##
++[Defines]
++ INF_VERSION = 0x00010017
++ BASE_NAME = Dhcp6DxeGoogleTest
++ FILE_GUID = 1D2A4C65-38C8-4C2F-BB60-B5FA49625AA9
++ VERSION_STRING = 1.0
++ MODULE_TYPE = HOST_APPLICATION
++#
++# The following information is for reference only and not required by the build tools.
++#
++# VALID_ARCHITECTURES = IA32 X64 AARCH64
++#
++[Sources]
++ Dhcp6DxeGoogleTest.cpp
++ Dhcp6IoGoogleTest.cpp
++ ../Dhcp6Io.c
++ ../Dhcp6Utility.c
++
++[Packages]
++ MdePkg/MdePkg.dec
++ MdeModulePkg/MdeModulePkg.dec
++ UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
++ NetworkPkg/NetworkPkg.dec
++
++[LibraryClasses]
++ GoogleTestLib
++ DebugLib
++ NetLib
++ PcdLib
++
++[Protocols]
++ gEfiDhcp6ServiceBindingProtocolGuid
++
++[Pcd]
++ gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType
++
++[Guids]
++ gZeroGuid
+diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp
+new file mode 100644
+index 0000000000..7ee40e4af4
+--- /dev/null
++++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp
+@@ -0,0 +1,478 @@
++/** @file
++ Tests for Dhcp6Io.c.
++
++ Copyright (c) Microsoft Corporation
++ SPDX-License-Identifier: BSD-2-Clause-Patent
++**/
++#include <gtest/gtest.h>
++
++extern "C" {
++ #include <Uefi.h>
++ #include <Library/BaseLib.h>
++ #include <Library/DebugLib.h>
++ #include <Library/BaseMemoryLib.h>
++ #include "../Dhcp6Impl.h"
++ #include "../Dhcp6Utility.h"
++}
++
++////////////////////////////////////////////////////////////////////////
++// Defines
++////////////////////////////////////////////////////////////////////////
++
++#define DHCP6_PACKET_MAX_LEN 1500
++
++////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////
++// Symbol Definitions
++// These functions are not directly under test - but required to compile
++////////////////////////////////////////////////////////////////////////
++
++// This definition is used by this test but is also required to compile
++// by Dhcp6Io.c
++EFI_IPv6_ADDRESS mAllDhcpRelayAndServersAddress = {
++ { 0xFF, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2 }
++};
++
++EFI_STATUS
++EFIAPI
++UdpIoSendDatagram (
++ IN UDP_IO *UdpIo,
++ IN NET_BUF *Packet,
++ IN UDP_END_POINT *EndPoint OPTIONAL,
++ IN EFI_IP_ADDRESS *Gateway OPTIONAL,
++ IN UDP_IO_CALLBACK CallBack,
++ IN VOID *Context
++ )
++{
++ return EFI_SUCCESS;
++}
++
++EFI_STATUS
++EFIAPI
++UdpIoRecvDatagram (
++ IN UDP_IO *UdpIo,
++ IN UDP_IO_CALLBACK CallBack,
++ IN VOID *Context,
++ IN UINT32 HeadLen
++ )
++{
++ return EFI_SUCCESS;
++}
++
++////////////////////////////////////////////////////////////////////////
++// Dhcp6AppendOptionTest Tests
++////////////////////////////////////////////////////////////////////////
++
++class Dhcp6AppendOptionTest : public ::testing::Test {
++public:
++ UINT8 *Buffer = NULL;
++ EFI_DHCP6_PACKET *Packet;
++
++protected:
++ // Add any setup code if needed
++ virtual void
++ SetUp (
++ )
++ {
++ // Initialize any resources or variables
++ Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);
++ ASSERT_NE (Buffer, (UINT8 *)NULL);
++
++ Packet = (EFI_DHCP6_PACKET *)Buffer;
++ Packet->Size = DHCP6_PACKET_MAX_LEN;
++ }
++
++ // Add any cleanup code if needed
++ virtual void
++ TearDown (
++ )
++ {
++ // Clean up any resources or variables
++ if (Buffer != NULL) {
++ FreePool (Buffer);
++ }
++ }
++};
++
++// Test Description:
++// Attempt to append an option to a packet that is too small by a duid that is too large
++TEST_F (Dhcp6AppendOptionTest, InvalidDataExpectBufferTooSmall) {
++ UINT8 *Cursor;
++ EFI_DHCP6_DUID *UntrustedDuid;
++ EFI_STATUS Status;
++
++ UntrustedDuid = (EFI_DHCP6_DUID *)AllocateZeroPool (sizeof (EFI_DHCP6_DUID));
++ ASSERT_NE (UntrustedDuid, (EFI_DHCP6_DUID *)NULL);
++
++ UntrustedDuid->Length = NTOHS (0xFFFF);
++
++ Cursor = Dhcp6AppendOptionTest::Packet->Dhcp6.Option;
++
++ Status = Dhcp6AppendOption (
++ Dhcp6AppendOptionTest::Packet,
++ &Cursor,
++ HTONS (Dhcp6OptServerId),
++ UntrustedDuid->Length,
++ UntrustedDuid->Duid
++ );
++
++ ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL);
++}
++
++// Test Description:
++// Attempt to append an option to a packet that is large enough
++TEST_F (Dhcp6AppendOptionTest, ValidDataExpectSuccess) {
++ UINT8 *Cursor;
++ EFI_DHCP6_DUID *UntrustedDuid;
++ EFI_STATUS Status;
++ UINTN OriginalLength;
++
++ UINT8 Duid[6] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
++
++ Packet->Length = sizeof (EFI_DHCP6_HEADER);
++ OriginalLength = Packet->Length;
++
++ UntrustedDuid = (EFI_DHCP6_DUID *)AllocateZeroPool (sizeof (EFI_DHCP6_DUID));
++ ASSERT_NE (UntrustedDuid, (EFI_DHCP6_DUID *)NULL);
++
++ UntrustedDuid->Length = NTOHS (sizeof (Duid));
++ CopyMem (UntrustedDuid->Duid, Duid, sizeof (Duid));
++
++ Cursor = Dhcp6AppendOptionTest::Packet->Dhcp6.Option;
++
++ Status = Dhcp6AppendOption (
++ Dhcp6AppendOptionTest::Packet,
++ &Cursor,
++ HTONS (Dhcp6OptServerId),
++ UntrustedDuid->Length,
++ UntrustedDuid->Duid
++ );
++
++ ASSERT_EQ (Status, EFI_SUCCESS);
++
++ // verify that the pointer to cursor moved by the expected amount
++ ASSERT_EQ (Cursor, (UINT8 *)Dhcp6AppendOptionTest::Packet->Dhcp6.Option + sizeof (Duid) + 4);
++
++ // verify that the length of the packet is now the expected amount
++ ASSERT_EQ (Dhcp6AppendOptionTest::Packet->Length, OriginalLength + sizeof (Duid) + 4);
++}
++
++////////////////////////////////////////////////////////////////////////
++// Dhcp6AppendETOption Tests
++////////////////////////////////////////////////////////////////////////
++
++class Dhcp6AppendETOptionTest : public ::testing::Test {
++public:
++ UINT8 *Buffer = NULL;
++ EFI_DHCP6_PACKET *Packet;
++
++protected:
++ // Add any setup code if needed
++ virtual void
++ SetUp (
++ )
++ {
++ // Initialize any resources or variables
++ Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);
++ ASSERT_NE (Buffer, (UINT8 *)NULL);
++
++ Packet = (EFI_DHCP6_PACKET *)Buffer;
++ Packet->Size = DHCP6_PACKET_MAX_LEN;
++ Packet->Length = sizeof (EFI_DHCP6_HEADER);
++ }
++
++ // Add any cleanup code if needed
++ virtual void
++ TearDown (
++ )
++ {
++ // Clean up any resources or variables
++ if (Buffer != NULL) {
++ FreePool (Buffer);
++ }
++ }
++};
++
++// Test Description:
++// Attempt to append an option to a packet that is too small by a duid that is too large
++TEST_F (Dhcp6AppendETOptionTest, InvalidDataExpectBufferTooSmall) {
++ UINT8 *Cursor;
++ EFI_STATUS Status;
++ DHCP6_INSTANCE Instance;
++ UINT16 ElapsedTimeVal;
++ UINT16 *ElapsedTime;
++
++ Cursor = Dhcp6AppendETOptionTest::Packet->Dhcp6.Option;
++ ElapsedTime = &ElapsedTimeVal;
++
++ Packet->Length = Packet->Size - 2;
++
++ Status = Dhcp6AppendETOption (
++ Dhcp6AppendETOptionTest::Packet,
++ &Cursor,
++ &Instance, // Instance is not used in this function
++ &ElapsedTime
++ );
++
++ // verify that we error out because the packet is too small for the option header
++ ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL);
++
++ // reset the length
++ Packet->Length = sizeof (EFI_DHCP6_HEADER);
++}
++
++// Test Description:
++// Attempt to append an option to a packet that is large enough
++TEST_F (Dhcp6AppendETOptionTest, ValidDataExpectSuccess) {
++ UINT8 *Cursor;
++ EFI_STATUS Status;
++ DHCP6_INSTANCE Instance;
++ UINT16 ElapsedTimeVal;
++ UINT16 *ElapsedTime;
++ UINTN ExpectedSize;
++ UINTN OriginalLength;
++
++ Cursor = Dhcp6AppendETOptionTest::Packet->Dhcp6.Option;
++ ElapsedTime = &ElapsedTimeVal;
++ ExpectedSize = 6;
++ OriginalLength = Packet->Length;
++
++ Status = Dhcp6AppendETOption (
++ Dhcp6AppendETOptionTest::Packet,
++ &Cursor,
++ &Instance, // Instance is not used in this function
++ &ElapsedTime
++ );
++
++ // verify that the status is EFI_SUCCESS
++ ASSERT_EQ (Status, EFI_SUCCESS);
++
++ // verify that the pointer to cursor moved by the expected amount
++ ASSERT_EQ (Cursor, (UINT8 *)Dhcp6AppendETOptionTest::Packet->Dhcp6.Option + ExpectedSize);
++
++ // verify that the length of the packet is now the expected amount
++ ASSERT_EQ (Dhcp6AppendETOptionTest::Packet->Length, OriginalLength + ExpectedSize);
++}
++
++////////////////////////////////////////////////////////////////////////
++// Dhcp6AppendIaOption Tests
++////////////////////////////////////////////////////////////////////////
++
++class Dhcp6AppendIaOptionTest : public ::testing::Test {
++public:
++ UINT8 *Buffer = NULL;
++ EFI_DHCP6_PACKET *Packet;
++ EFI_DHCP6_IA *Ia;
++
++protected:
++ // Add any setup code if needed
++ virtual void
++ SetUp (
++ )
++ {
++ // Initialize any resources or variables
++ Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);
++ ASSERT_NE (Buffer, (UINT8 *)NULL);
++
++ Packet = (EFI_DHCP6_PACKET *)Buffer;
++ Packet->Size = DHCP6_PACKET_MAX_LEN;
++
++ Ia = (EFI_DHCP6_IA *)AllocateZeroPool (sizeof (EFI_DHCP6_IA) + sizeof (EFI_DHCP6_IA_ADDRESS) * 2);
++ ASSERT_NE (Ia, (EFI_DHCP6_IA *)NULL);
++
++ CopyMem (Ia->IaAddress, mAllDhcpRelayAndServersAddress.Addr, sizeof (EFI_IPv6_ADDRESS));
++ CopyMem (Ia->IaAddress + 1, mAllDhcpRelayAndServersAddress.Addr, sizeof (EFI_IPv6_ADDRESS));
++
++ Ia->IaAddressCount = 2;
++ }
++
++ // Add any cleanup code if needed
++ virtual void
++ TearDown (
++ )
++ {
++ // Clean up any resources or variables
++ if (Buffer != NULL) {
++ FreePool (Buffer);
++ }
++
++ if (Ia != NULL) {
++ FreePool (Ia);
++ }
++ }
++};
++
++// Test Description:
++// Attempt to append an option to a packet that doesn't have enough space
++// for the option header
++TEST_F (Dhcp6AppendIaOptionTest, IaNaInvalidDataExpectBufferTooSmall) {
++ UINT8 *Cursor;
++ EFI_STATUS Status;
++
++ Packet->Length = Packet->Size - 2;
++
++ Ia->Descriptor.Type = Dhcp6OptIana;
++ Ia->Descriptor.IaId = 0x12345678;
++
++ Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option;
++
++ Status = Dhcp6AppendIaOption (
++ Dhcp6AppendIaOptionTest::Packet,
++ &Cursor,
++ Ia,
++ 0x12345678,
++ 0x11111111,
++ Dhcp6OptIana
++ );
++
++ // verify that we error out because the packet is too small for the option header
++ ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL);
++
++ // reset the length
++ Packet->Length = sizeof (EFI_DHCP6_HEADER);
++}
++
++// Test Description:
++// Attempt to append an option to a packet that doesn't have enough space
++// for the option header
++TEST_F (Dhcp6AppendIaOptionTest, IaTaInvalidDataExpectBufferTooSmall) {
++ UINT8 *Cursor;
++ EFI_STATUS Status;
++
++ // Use up nearly all the space in the packet
++ Packet->Length = Packet->Size - 2;
++
++ Ia->Descriptor.Type = Dhcp6OptIata;
++ Ia->Descriptor.IaId = 0x12345678;
++
++ Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option;
++
++ Status = Dhcp6AppendIaOption (
++ Dhcp6AppendIaOptionTest::Packet,
++ &Cursor,
++ Ia,
++ 0,
++ 0,
++ Dhcp6OptIata
++ );
++
++ // verify that we error out because the packet is too small for the option header
++ ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL);
++
++ // reset the length
++ Packet->Length = sizeof (EFI_DHCP6_HEADER);
++}
++
++TEST_F (Dhcp6AppendIaOptionTest, IaNaValidDataExpectSuccess) {
++ UINT8 *Cursor;
++ EFI_STATUS Status;
++ UINTN ExpectedSize;
++ UINTN OriginalLength;
++
++ //
++ // 2 bytes for the option header type
++ //
++ ExpectedSize = 2;
++ //
++ // 2 bytes for the option header length
++ //
++ ExpectedSize += 2;
++ //
++ // 4 bytes for the IAID
++ //
++ ExpectedSize += 4;
++ //
++ // + 4 bytes for the T1
++ //
++ ExpectedSize += 4;
++ //
++ // + 4 bytes for the T2
++ //
++ ExpectedSize += 4;
++ //
++ // + (4 + sizeof (EFI_DHCP6_IA_ADDRESS)) * 2;
++ // + 2 bytes for the option header type
++ // + 2 bytes for the option header length
++ // + sizeof (EFI_DHCP6_IA_ADDRESS) for the IA Address
++ //
++ ExpectedSize += (4 + sizeof (EFI_DHCP6_IA_ADDRESS)) * 2;
++
++ Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option;
++
++ Packet->Length = sizeof (EFI_DHCP6_HEADER);
++ OriginalLength = Packet->Length;
++
++ Ia->Descriptor.Type = Dhcp6OptIana;
++ Ia->Descriptor.IaId = 0x12345678;
++
++ Status = Dhcp6AppendIaOption (
++ Dhcp6AppendIaOptionTest::Packet,
++ &Cursor,
++ Ia,
++ 0x12345678,
++ 0x12345678,
++ Dhcp6OptIana
++ );
++
++ // verify that the pointer to cursor moved by the expected amount
++ ASSERT_EQ (Cursor, (UINT8 *)Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option + ExpectedSize);
++
++ // verify that the length of the packet is now the expected amount
++ ASSERT_EQ (Dhcp6AppendIaOptionTest::Packet->Length, OriginalLength + ExpectedSize);
++
++ // verify that the status is EFI_SUCCESS
++ ASSERT_EQ (Status, EFI_SUCCESS);
++}
++
++TEST_F (Dhcp6AppendIaOptionTest, IaTaValidDataExpectSuccess) {
++ UINT8 *Cursor;
++ EFI_STATUS Status;
++ UINTN ExpectedSize;
++ UINTN OriginalLength;
++
++ //
++ // 2 bytes for the option header type
++ //
++ ExpectedSize = 2;
++ //
++ // 2 bytes for the option header length
++ //
++ ExpectedSize += 2;
++ //
++ // 4 bytes for the IAID
++ //
++ ExpectedSize += 4;
++ //
++ // + (4 + sizeof (EFI_DHCP6_IA_ADDRESS)) * 2;
++ // + 2 bytes for the option header type
++ // + 2 bytes for the option header length
++ // + sizeof (EFI_DHCP6_IA_ADDRESS) for the IA Address
++ //
++ ExpectedSize += (4 + sizeof (EFI_DHCP6_IA_ADDRESS)) * 2;
++
++ Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option;
++
++ Packet->Length = sizeof (EFI_DHCP6_HEADER);
++ OriginalLength = Packet->Length;
++
++ Ia->Descriptor.Type = Dhcp6OptIata;
++ Ia->Descriptor.IaId = 0x12345678;
++
++ Status = Dhcp6AppendIaOption (
++ Dhcp6AppendIaOptionTest::Packet,
++ &Cursor,
++ Ia,
++ 0,
++ 0,
++ Dhcp6OptIata
++ );
++
++ // verify that the pointer to cursor moved by the expected amount
++ ASSERT_EQ (Cursor, (UINT8 *)Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option + ExpectedSize);
++
++ // verify that the length of the packet is now the expected amount
++ ASSERT_EQ (Dhcp6AppendIaOptionTest::Packet->Length, OriginalLength + ExpectedSize);
++
++ // verify that the status is EFI_SUCCESS
++ ASSERT_EQ (Status, EFI_SUCCESS);
++}
+--
+2.40.0
+
diff --git a/meta/recipes-core/ovmf/ovmf_git.bb b/meta/recipes-core/ovmf/ovmf_git.bb
index 59e5598a1b..957a74aabe 100644
--- a/meta/recipes-core/ovmf/ovmf_git.bb
+++ b/meta/recipes-core/ovmf/ovmf_git.bb
@@ -33,6 +33,8 @@ SRC_URI = "gitsm://github.com/tianocore/edk2.git;branch=master;protocol=https \
file://CVE-2022-36764-0001.patch \
file://CVE-2022-36764-0002.patch \
file://CVE-2022-36764-0003.patch \
+ file://CVE-2023-45230-0001.patch \
+ file://CVE-2023-45230-0002.patch \
"
PV = "edk2-stable202202"
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 04/38] ovmf: Fix CVE-2023-45231
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (2 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 03/38] ovmf: Fix CVE-2023-45230 Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 05/38] ovmf: Fix CVE-2023-45232, CVE-2023-45233 Steve Sakoman
` (33 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Soumya Sambu <soumya.sambu@windriver.com>
EDK2's Network Package is susceptible to an out-of-bounds read
vulnerability when processing Neighbor Discovery Redirect message. This
vulnerability can be exploited by an attacker to gain unauthorized access
and potentially lead to a loss of Confidentiality.
References:
https://nvd.nist.gov/vuln/detail/CVE-2023-45231
Upstream-patches:
https://github.com/tianocore/edk2/commit/bbfee34f4188ac00371abe1389ae9c9fb989a0cd
https://github.com/tianocore/edk2/commit/6f77463d72807ec7f4ed6518c3dac29a1040df9f
Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
---
.../ovmf/ovmf/CVE-2023-45231-0001.patch | 65 +++++
.../ovmf/ovmf/CVE-2023-45231-0002.patch | 250 ++++++++++++++++++
meta/recipes-core/ovmf/ovmf_git.bb | 2 +
3 files changed, 317 insertions(+)
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45231-0001.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45231-0002.patch
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2023-45231-0001.patch b/meta/recipes-core/ovmf/ovmf/CVE-2023-45231-0001.patch
new file mode 100644
index 0000000000..7aa9b27407
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/CVE-2023-45231-0001.patch
@@ -0,0 +1,65 @@
+From bbfee34f4188ac00371abe1389ae9c9fb989a0cd Mon Sep 17 00:00:00 2001
+From: Doug Flick <dougflick@microsoft.com>
+Date: Fri, 26 Jan 2024 05:54:48 +0800
+Subject: [PATCH] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 Patch
+
+REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4536
+
+Bug Overview:
+PixieFail Bug #3
+CVE-2023-45231
+CVSS 6.5 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
+CWE-125 Out-of-bounds Read
+
+Out-of-bounds read when handling a ND Redirect message with truncated
+options
+
+Change Overview:
+
+Adds a check to prevent truncated options from being parsed
++ //
++ // Cannot process truncated options.
++ // Cannot process options with a length of 0 as there is no Type
+field.
++ //
++ if (OptionLen < sizeof (IP6_OPTION_HEADER)) {
++ return FALSE;
++ }
+
+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-45231
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/bbfee34f4188ac00371abe1389ae9c9fb989a0cd]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ NetworkPkg/Ip6Dxe/Ip6Option.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/NetworkPkg/Ip6Dxe/Ip6Option.c b/NetworkPkg/Ip6Dxe/Ip6Option.c
+index 199eea124d..8718d5d875 100644
+--- a/NetworkPkg/Ip6Dxe/Ip6Option.c
++++ b/NetworkPkg/Ip6Dxe/Ip6Option.c
+@@ -137,6 +137,14 @@ Ip6IsNDOptionValid (
+ return FALSE;
+ }
+
++ //
++ // Cannot process truncated options.
++ // Cannot process options with a length of 0 as there is no Type field.
++ //
++ if (OptionLen < sizeof (IP6_OPTION_HEADER)) {
++ return FALSE;
++ }
++
+ Offset = 0;
+
+ //
+--
+2.40.0
+
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2023-45231-0002.patch b/meta/recipes-core/ovmf/ovmf/CVE-2023-45231-0002.patch
new file mode 100644
index 0000000000..fbc2c4416e
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/CVE-2023-45231-0002.patch
@@ -0,0 +1,250 @@
+From 6f77463d72807ec7f4ed6518c3dac29a1040df9f Mon Sep 17 00:00:00 2001
+From: Doug Flick <dougflick@microsoft.com>
+Date: Fri, 26 Jan 2024 05:54:49 +0800
+Subject: [PATCH] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 Unit Tests
+
+REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4536
+
+Validates that the patch for...
+
+Out-of-bounds read when handling a ND Redirect message with truncated
+options
+
+.. has been fixed
+
+Tests the following function to ensure that an out of bounds read does
+not occur
+Ip6OptionValidation
+
+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-45231
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/6f77463d72807ec7f4ed6518c3dac29a1040df9f]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ .../Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp | 20 +++
+ .../Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf | 42 ++++++
+ .../Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp | 129 ++++++++++++++++++
+ 3 files changed, 191 insertions(+)
+ create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp
+ create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
+ create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
+
+diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp
+new file mode 100644
+index 0000000000..6ebfd5fdfb
+--- /dev/null
++++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp
+@@ -0,0 +1,20 @@
++/** @file
++ Acts as the main entry point for the tests for the Ip6Dxe module.
++
++ Copyright (c) Microsoft Corporation
++ SPDX-License-Identifier: BSD-2-Clause-Patent
++**/
++#include <gtest/gtest.h>
++
++////////////////////////////////////////////////////////////////////////////////
++// Run the tests
++////////////////////////////////////////////////////////////////////////////////
++int
++main (
++ int argc,
++ char *argv[]
++ )
++{
++ testing::InitGoogleTest (&argc, argv);
++ return RUN_ALL_TESTS ();
++}
+diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
+new file mode 100644
+index 0000000000..6e4de0745f
+--- /dev/null
++++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
+@@ -0,0 +1,42 @@
++## @file
++# Unit test suite for the Ip6Dxe 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
++ VERSION_STRING = 1.0
++ MODULE_TYPE = HOST_APPLICATION
++#
++# The following information is for reference only and not required by the build tools.
++#
++# VALID_ARCHITECTURES = IA32 X64 AARCH64
++#
++[Sources]
++ Ip6DxeGoogleTest.cpp
++ Ip6OptionGoogleTest.cpp
++ ../Ip6Option.c
++
++[Packages]
++ MdePkg/MdePkg.dec
++ MdeModulePkg/MdeModulePkg.dec
++ UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
++ NetworkPkg/NetworkPkg.dec
++
++[LibraryClasses]
++ GoogleTestLib
++ DebugLib
++ NetLib
++ PcdLib
++
++[Protocols]
++ gEfiDhcp6ServiceBindingProtocolGuid
++
++[Pcd]
++ gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType
++
++[Guids]
++ gZeroGuid
+diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
+new file mode 100644
+index 0000000000..f2cd90e1a9
+--- /dev/null
++++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
+@@ -0,0 +1,129 @@
++/** @file
++ Tests for Ip6Option.c.
++
++ Copyright (c) Microsoft Corporation
++ SPDX-License-Identifier: BSD-2-Clause-Patent
++**/
++#include <gtest/gtest.h>
++
++extern "C" {
++ #include <Uefi.h>
++ #include <Library/BaseLib.h>
++ #include <Library/DebugLib.h>
++ #include "../Ip6Impl.h"
++ #include "../Ip6Option.h"
++}
++
++/////////////////////////////////////////////////////////////////////////
++// Defines
++///////////////////////////////////////////////////////////////////////
++
++#define IP6_PREFIX_INFO_OPTION_DATA_LEN 32
++#define OPTION_HEADER_IP6_PREFIX_DATA_LEN (sizeof (IP6_OPTION_HEADER) + IP6_PREFIX_INFO_OPTION_DATA_LEN)
++
++////////////////////////////////////////////////////////////////////////
++// Symbol Definitions
++// These functions are not directly under test - but required to compile
++////////////////////////////////////////////////////////////////////////
++UINT32 mIp6Id;
++
++EFI_STATUS
++Ip6SendIcmpError (
++ IN IP6_SERVICE *IpSb,
++ IN NET_BUF *Packet,
++ IN EFI_IPv6_ADDRESS *SourceAddress OPTIONAL,
++ IN EFI_IPv6_ADDRESS *DestinationAddress,
++ IN UINT8 Type,
++ IN UINT8 Code,
++ IN UINT32 *Pointer OPTIONAL
++ )
++{
++ // ..
++ return EFI_SUCCESS;
++}
++
++////////////////////////////////////////////////////////////////////////
++// Ip6OptionValidation Tests
++////////////////////////////////////////////////////////////////////////
++
++// Define a fixture for your tests if needed
++class Ip6OptionValidationTest : 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:
++// Null option should return false
++TEST_F (Ip6OptionValidationTest, NullOptionShouldReturnFalse) {
++ UINT8 *option = nullptr;
++ UINT16 optionLen = 10; // Provide a suitable length
++
++ EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen));
++}
++
++// Test Description:
++// Truncated option should return false
++TEST_F (Ip6OptionValidationTest, TruncatedOptionShouldReturnFalse) {
++ UINT8 option[] = { 0x01 }; // Provide a truncated option
++ UINT16 optionLen = 1;
++
++ EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen));
++}
++
++// Test Description:
++// Ip6OptionPrefixInfo Option with zero length should return false
++TEST_F (Ip6OptionValidationTest, OptionWithZeroLengthShouldReturnFalse) {
++ IP6_OPTION_HEADER optionHeader;
++
++ optionHeader.Type = Ip6OptionPrefixInfo;
++ optionHeader.Length = 0;
++ UINT8 option[sizeof (IP6_OPTION_HEADER)];
++
++ CopyMem (option, &optionHeader, sizeof (IP6_OPTION_HEADER));
++ UINT16 optionLen = sizeof (IP6_OPTION_HEADER);
++
++ EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen));
++}
++
++// Test Description:
++// Ip6OptionPrefixInfo Option with valid length should return true
++TEST_F (Ip6OptionValidationTest, ValidPrefixInfoOptionShouldReturnTrue) {
++ IP6_OPTION_HEADER optionHeader;
++
++ optionHeader.Type = Ip6OptionPrefixInfo;
++ optionHeader.Length = 4; // Length 4 * 8 = 32
++ UINT8 option[OPTION_HEADER_IP6_PREFIX_DATA_LEN];
++
++ CopyMem (option, &optionHeader, sizeof (IP6_OPTION_HEADER));
++
++ EXPECT_TRUE (Ip6IsNDOptionValid (option, IP6_PREFIX_INFO_OPTION_DATA_LEN));
++}
++
++// Test Description:
++// Ip6OptionPrefixInfo Option with invalid length should return false
++TEST_F (Ip6OptionValidationTest, InvalidPrefixInfoOptionLengthShouldReturnFalse) {
++ IP6_OPTION_HEADER optionHeader;
++
++ optionHeader.Type = Ip6OptionPrefixInfo;
++ optionHeader.Length = 3; // Length 3 * 8 = 24 (Invalid)
++ UINT8 option[sizeof (IP6_OPTION_HEADER)];
++
++ CopyMem (option, &optionHeader, sizeof (IP6_OPTION_HEADER));
++ UINT16 optionLen = sizeof (IP6_OPTION_HEADER);
++
++ EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen));
++}
+--
+2.40.0
+
diff --git a/meta/recipes-core/ovmf/ovmf_git.bb b/meta/recipes-core/ovmf/ovmf_git.bb
index 957a74aabe..e46b3ddebe 100644
--- a/meta/recipes-core/ovmf/ovmf_git.bb
+++ b/meta/recipes-core/ovmf/ovmf_git.bb
@@ -35,6 +35,8 @@ SRC_URI = "gitsm://github.com/tianocore/edk2.git;branch=master;protocol=https \
file://CVE-2022-36764-0003.patch \
file://CVE-2023-45230-0001.patch \
file://CVE-2023-45230-0002.patch \
+ file://CVE-2023-45231-0001.patch \
+ file://CVE-2023-45231-0002.patch \
"
PV = "edk2-stable202202"
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 05/38] ovmf: Fix CVE-2023-45232, CVE-2023-45233
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (3 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 04/38] ovmf: Fix CVE-2023-45231 Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 06/38] ovmf: Fix CVE-2023-45234 Steve Sakoman
` (32 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Soumya Sambu <soumya.sambu@windriver.com>
CVE-2023-45232:
EDK2's Network Package is susceptible to an infinite loop vulnerability
when parsing unknown options in the Destination Options header of IPv6.
This vulnerability can be exploited by an attacker to gain unauthorized
access and potentially lead to a loss of Availability.
CVE-2023-45233:
EDK2's Network Package is susceptible to an infinite lop vulnerability
when parsing a PadN option in the Destination Options header of IPv6.
This vulnerability can be exploited by an attacker to gain unauthorized
access and potentially lead to a loss of Availability.
References:
https://nvd.nist.gov/vuln/detail/CVE-2023-45232
https://nvd.nist.gov/vuln/detail/CVE-2023-45233
Upstream-patches:
https://github.com/tianocore/edk2/commit/4df0229ef992d4f2721a8508787ebf9dc81fbd6e
https://github.com/tianocore/edk2/commit/c9c87f08dd6ace36fa843424522c3558a8374cac
Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
---
.../CVE-2023-45232-CVE-2023-45233-0001.patch | 360 +++++++++++++++
.../CVE-2023-45232-CVE-2023-45233-0002.patch | 417 ++++++++++++++++++
meta/recipes-core/ovmf/ovmf_git.bb | 2 +
3 files changed, 779 insertions(+)
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45232-CVE-2023-45233-0001.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45232-CVE-2023-45233-0002.patch
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 @@
+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
+
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 @@
+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
+
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 \
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"
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 06/38] ovmf: Fix CVE-2023-45234
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (4 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 05/38] ovmf: Fix CVE-2023-45232, CVE-2023-45233 Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 07/38] ovmf: Fix CVE-2023-45235 Steve Sakoman
` (31 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Soumya Sambu <soumya.sambu@windriver.com>
EDK2's Network Package is susceptible to a buffer overflow vulnerability
when processing DNS Servers option from a DHCPv6 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-45234
Upstream-patches:
https://github.com/tianocore/edk2/commit/1b53515d53d303166b2bbd31e2cc7f16fd0aecd7
https://github.com/tianocore/edk2/commit/458c582685fc0e8057d2511c5a0394078d988c17
Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
---
.../ovmf/ovmf/CVE-2023-45234-0001.patch | 154 ++++++
.../ovmf/ovmf/CVE-2023-45234-0002.patch | 485 ++++++++++++++++++
meta/recipes-core/ovmf/ovmf_git.bb | 2 +
3 files changed, 641 insertions(+)
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45234-0001.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45234-0002.patch
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2023-45234-0001.patch b/meta/recipes-core/ovmf/ovmf/CVE-2023-45234-0001.patch
new file mode 100644
index 0000000000..463b4b824d
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/CVE-2023-45234-0001.patch
@@ -0,0 +1,154 @@
+From 1b53515d53d303166b2bbd31e2cc7f16fd0aecd7 Mon Sep 17 00:00:00 2001
+From: Doug Flick <dougflick@microsoft.com>
+Date: Fri, 26 Jan 2024 05:54:52 +0800
+Subject: [PATCH] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Patch
+
+REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4539
+
+Bug Details:
+PixieFail Bug #6
+CVE-2023-45234
+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 processing DNS Servers option in a DHCPv6
+Advertise message
+
+Change Overview:
+
+Introduces a function to cache the Dns Server and perform sanitizing
+on the incoming DnsServerLen to ensure that the length is valid
+
+> + EFI_STATUS
+> + PxeBcCacheDnsServerAddresses (
+> + IN PXEBC_PRIVATE_DATA *Private,
+> + IN PXEBC_DHCP6_PACKET_CACHE *Cache6
+> + )
+
+Additional code cleanup
+
+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-45234
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/1b53515d53d303166b2bbd31e2cc7f16fd0aecd7]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c | 71 +++++++++++++++++++++++++---
+ 1 file changed, 65 insertions(+), 6 deletions(-)
+
+diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
+index 425e0cf806..2b2d372889 100644
+--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
++++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
+@@ -3,6 +3,7 @@
+
+ (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
++ Copyright (c) Microsoft Corporation
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+@@ -1312,6 +1313,65 @@ PxeBcSelectDhcp6Offer (
+ }
+ }
+
++/**
++ Cache the DHCPv6 DNS Server addresses
++
++ @param[in] Private The pointer to PXEBC_PRIVATE_DATA.
++ @param[in] Cache6 The pointer to PXEBC_DHCP6_PACKET_CACHE.
++
++ @retval EFI_SUCCESS Cache the DHCPv6 DNS Server address successfully.
++ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
++ @retval EFI_DEVICE_ERROR The DNS Server Address Length provided by a untrusted
++ option is not a multiple of 16 bytes (sizeof (EFI_IPv6_ADDRESS)).
++**/
++EFI_STATUS
++PxeBcCacheDnsServerAddresses (
++ IN PXEBC_PRIVATE_DATA *Private,
++ IN PXEBC_DHCP6_PACKET_CACHE *Cache6
++ )
++{
++ UINT16 DnsServerLen;
++
++ DnsServerLen = NTOHS (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen);
++ //
++ // Make sure that the number is nonzero
++ //
++ if (DnsServerLen == 0) {
++ return EFI_DEVICE_ERROR;
++ }
++
++ //
++ // Make sure the DnsServerlen is a multiple of EFI_IPv6_ADDRESS (16)
++ //
++ if (DnsServerLen % sizeof (EFI_IPv6_ADDRESS) != 0) {
++ return EFI_DEVICE_ERROR;
++ }
++
++ //
++ // This code is currently written to only support a single DNS Server instead
++ // of multiple such as is spec defined (RFC3646, Section 3). The proper behavior
++ // would be to allocate the full space requested, CopyMem all of the data,
++ // and then add a DnsServerCount field to Private and update additional code
++ // that depends on this.
++ //
++ // To support multiple DNS servers the `AllocationSize` would need to be changed to DnsServerLen
++ //
++ // This is tracked in https://bugzilla.tianocore.org/show_bug.cgi?id=1886
++ //
++ Private->DnsServer = AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS));
++ if (Private->DnsServer == NULL) {
++ return EFI_OUT_OF_RESOURCES;
++ }
++
++ //
++ // Intentionally only copy over the first server address.
++ // To support multiple DNS servers, the `Length` would need to be changed to DnsServerLen
++ //
++ CopyMem (Private->DnsServer, Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, sizeof (EFI_IPv6_ADDRESS));
++
++ return EFI_SUCCESS;
++}
++
+ /**
+ Handle the DHCPv6 offer packet.
+
+@@ -1335,6 +1395,7 @@ PxeBcHandleDhcp6Offer (
+ UINT32 SelectIndex;
+ UINT32 Index;
+
++ ASSERT (Private != NULL);
+ ASSERT (Private->SelectIndex > 0);
+ SelectIndex = (UINT32)(Private->SelectIndex - 1);
+ ASSERT (SelectIndex < PXEBC_OFFER_MAX_NUM);
+@@ -1342,15 +1403,13 @@ PxeBcHandleDhcp6Offer (
+ Status = EFI_SUCCESS;
+
+ //
+- // First try to cache DNS server address if DHCP6 offer provides.
++ // First try to cache DNS server addresses if DHCP6 offer provides.
+ //
+ if (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] != NULL) {
+- Private->DnsServer = AllocateZeroPool (NTOHS (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen));
+- if (Private->DnsServer == NULL) {
+- return EFI_OUT_OF_RESOURCES;
++ Status = PxeBcCacheDnsServerAddresses (Private, Cache6);
++ if (EFI_ERROR (Status)) {
++ return Status;
+ }
+-
+- CopyMem (Private->DnsServer, Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, sizeof (EFI_IPv6_ADDRESS));
+ }
+
+ if (Cache6->OfferType == PxeOfferTypeDhcpBinl) {
+--
+2.40.0
+
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2023-45234-0002.patch b/meta/recipes-core/ovmf/ovmf/CVE-2023-45234-0002.patch
new file mode 100644
index 0000000000..4bc7ac16d6
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/CVE-2023-45234-0002.patch
@@ -0,0 +1,485 @@
+From 458c582685fc0e8057d2511c5a0394078d988c17 Mon Sep 17 00:00:00 2001
+From: Doug Flick <dougflick@microsoft.com>
+Date: Fri, 26 Jan 2024 05:54:53 +0800
+Subject: [PATCH] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Unit
+ Tests
+
+REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4539
+
+Unit tests to that the bug..
+
+Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise
+message
+
+..has been patched
+
+This contains tests for the following functions:
+PxeBcHandleDhcp6Offer
+PxeBcCacheDnsServerAddresses
+
+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-45234
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/458c582685fc0e8057d2511c5a0394078d988c17]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ .../GoogleTest/PxeBcDhcp6GoogleTest.cpp | 300 ++++++++++++++++++
+ .../GoogleTest/PxeBcDhcp6GoogleTest.h | 50 +++
+ .../GoogleTest/UefiPxeBcDxeGoogleTest.cpp | 19 ++
+ .../GoogleTest/UefiPxeBcDxeGoogleTest.inf | 48 +++
+ 4 files changed, 417 insertions(+)
+ create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
+ create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h
+ create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp
+ create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
+
+diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
+new file mode 100644
+index 0000000000..8260eeee50
+--- /dev/null
++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
+@@ -0,0 +1,300 @@
++/** @file
++ Host based unit test for PxeBcDhcp6.c.
++
++ Copyright (c) Microsoft Corporation
++ SPDX-License-Identifier: BSD-2-Clause-Patent
++**/
++#include <gtest/gtest.h>
++
++extern "C" {
++ #include <Uefi.h>
++ #include <Library/BaseLib.h>
++ #include <Library/DebugLib.h>
++ #include "../PxeBcImpl.h"
++ #include "../PxeBcDhcp6.h"
++ #include "PxeBcDhcp6GoogleTest.h"
++}
++
++///////////////////////////////////////////////////////////////////////////////
++// Definitions
++///////////////////////////////////////////////////////////////////////////////
++
++#define PACKET_SIZE (1500)
++
++typedef struct {
++ UINT16 OptionCode; // The option code for DHCP6_OPT_SERVER_ID (e.g., 0x03)
++ UINT16 OptionLen; // The length of the option (e.g., 16 bytes)
++ UINT8 ServerId[16]; // The 16-byte DHCPv6 Server Identifier
++} DHCP6_OPTION_SERVER_ID;
++
++///////////////////////////////////////////////////////////////////////////////
++/// Symbol Definitions
++///////////////////////////////////////////////////////////////////////////////
++
++EFI_STATUS
++MockUdpWrite (
++ IN EFI_PXE_BASE_CODE_PROTOCOL *This,
++ IN UINT16 OpFlags,
++ IN EFI_IP_ADDRESS *DestIp,
++ IN EFI_PXE_BASE_CODE_UDP_PORT *DestPort,
++ IN EFI_IP_ADDRESS *GatewayIp OPTIONAL,
++ IN EFI_IP_ADDRESS *SrcIp OPTIONAL,
++ IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort OPTIONAL,
++ IN UINTN *HeaderSize OPTIONAL,
++ IN VOID *HeaderPtr OPTIONAL,
++ IN UINTN *BufferSize,
++ IN VOID *BufferPtr
++ )
++{
++ return EFI_SUCCESS;
++}
++
++EFI_STATUS
++MockUdpRead (
++ IN EFI_PXE_BASE_CODE_PROTOCOL *This,
++ IN UINT16 OpFlags,
++ IN OUT EFI_IP_ADDRESS *DestIp OPTIONAL,
++ IN OUT EFI_PXE_BASE_CODE_UDP_PORT *DestPort OPTIONAL,
++ IN OUT EFI_IP_ADDRESS *SrcIp OPTIONAL,
++ IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort OPTIONAL,
++ IN UINTN *HeaderSize OPTIONAL,
++ IN VOID *HeaderPtr OPTIONAL,
++ IN OUT UINTN *BufferSize,
++ IN VOID *BufferPtr
++ )
++{
++ return EFI_SUCCESS;
++}
++
++EFI_STATUS
++MockConfigure (
++ IN EFI_UDP6_PROTOCOL *This,
++ IN EFI_UDP6_CONFIG_DATA *UdpConfigData OPTIONAL
++ )
++{
++ return EFI_SUCCESS;
++}
++
++// Needed by PxeBcSupport
++EFI_STATUS
++EFIAPI
++QueueDpc (
++ IN EFI_TPL DpcTpl,
++ IN EFI_DPC_PROCEDURE DpcProcedure,
++ IN VOID *DpcContext OPTIONAL
++ )
++{
++ return EFI_SUCCESS;
++}
++
++///////////////////////////////////////////////////////////////////////////////
++// PxeBcHandleDhcp6OfferTest Tests
++///////////////////////////////////////////////////////////////////////////////
++
++class PxeBcHandleDhcp6OfferTest : public ::testing::Test {
++public:
++ PXEBC_PRIVATE_DATA Private = { 0 };
++ EFI_UDP6_PROTOCOL Udp6Read;
++ EFI_PXE_BASE_CODE_MODE Mode = { 0 };
++
++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;
++
++ // Need to setup the EFI_PXE_BASE_CODE_MODE
++ Private.PxeBc.Mode = &Mode;
++
++ // for this test it doesn't really matter what the Dhcpv6 ack is set to
++ }
++
++ // Add any cleanup code if needed
++ virtual void
++ TearDown (
++ )
++ {
++ if (Private.Dhcp6Request != NULL) {
++ FreePool (Private.Dhcp6Request);
++ }
++
++ // Clean up any resources or variables
++ }
++};
++
++// Note:
++// Testing PxeBcHandleDhcp6Offer() is difficult because it depends on a
++// properly setup Private structure. Attempting to properly test this function
++// without a signficant refactor is a fools errand. Instead, we will test
++// that we can prevent an overflow in the function.
++TEST_F (PxeBcHandleDhcp6OfferTest, BasicUsageTest) {
++ PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL;
++ EFI_DHCP6_PACKET_OPTION Option = { 0 };
++
++ Private.SelectIndex = 1; // SelectIndex is 1-based
++ Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;
++
++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;
++ // Setup the DHCPv6 offer packet
++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;
++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (1337);
++
++ ASSERT_EQ (PxeBcHandleDhcp6Offer (&(PxeBcHandleDhcp6OfferTest::Private)), EFI_DEVICE_ERROR);
++}
++
++class PxeBcCacheDnsServerAddressesTest : public ::testing::Test {
++public:
++ PXEBC_PRIVATE_DATA Private = { 0 };
++
++protected:
++ // Add any setup code if needed
++ virtual void
++ SetUp (
++ )
++ {
++ }
++
++ // Add any cleanup code if needed
++ virtual void
++ TearDown (
++ )
++ {
++ }
++};
++
++// Test Description
++// Test that we cache the DNS server address from the DHCPv6 offer packet
++TEST_F (PxeBcCacheDnsServerAddressesTest, BasicUsageTest) {
++ UINT8 SearchPattern[16] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF };
++ EFI_DHCP6_PACKET_OPTION *Option;
++ PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL;
++
++ Option = (EFI_DHCP6_PACKET_OPTION *)AllocateZeroPool (sizeof (EFI_DHCP6_PACKET_OPTION) + sizeof (SearchPattern));
++ ASSERT_NE (Option, nullptr);
++
++ Option->OpCode = DHCP6_OPT_SERVER_ID;
++ Option->OpLen = NTOHS (sizeof (SearchPattern));
++ CopyMem (Option->Data, SearchPattern, sizeof (SearchPattern));
++
++ Private.SelectIndex = 1; // SelectIndex is 1-based
++ Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;
++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = Option;
++
++ Private.DnsServer = nullptr;
++
++ ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_SUCCESS);
++ ASSERT_NE (Private.DnsServer, nullptr);
++ ASSERT_EQ (CompareMem (Private.DnsServer, SearchPattern, sizeof (SearchPattern)), 0);
++
++ if (Private.DnsServer) {
++ FreePool (Private.DnsServer);
++ }
++
++ if (Option) {
++ FreePool (Option);
++ }
++}
++// Test Description
++// Test that we can prevent an overflow in the function
++TEST_F (PxeBcCacheDnsServerAddressesTest, AttemptOverflowTest) {
++ EFI_DHCP6_PACKET_OPTION Option = { 0 };
++ PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL;
++
++ Private.SelectIndex = 1; // SelectIndex is 1-based
++ Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;
++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;
++ // Setup the DHCPv6 offer packet
++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;
++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (1337);
++
++ Private.DnsServer = NULL;
++
++ ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_DEVICE_ERROR);
++ ASSERT_EQ (Private.DnsServer, nullptr);
++
++ if (Private.DnsServer) {
++ FreePool (Private.DnsServer);
++ }
++}
++
++// Test Description
++// Test that we can prevent an underflow in the function
++TEST_F (PxeBcCacheDnsServerAddressesTest, AttemptUnderflowTest) {
++ EFI_DHCP6_PACKET_OPTION Option = { 0 };
++ PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL;
++
++ Private.SelectIndex = 1; // SelectIndex is 1-based
++ Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;
++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;
++ // Setup the DHCPv6 offer packet
++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;
++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (2);
++
++ Private.DnsServer = NULL;
++
++ ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_DEVICE_ERROR);
++ ASSERT_EQ (Private.DnsServer, nullptr);
++
++ if (Private.DnsServer) {
++ FreePool (Private.DnsServer);
++ }
++}
++
++// Test Description
++// Test that we can handle recursive dns (multiple dns entries)
++TEST_F (PxeBcCacheDnsServerAddressesTest, MultipleDnsEntries) {
++ EFI_DHCP6_PACKET_OPTION Option = { 0 };
++ PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL;
++
++ Private.SelectIndex = 1; // SelectIndex is 1-based
++ Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;
++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;
++ // Setup the DHCPv6 offer packet
++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;
++
++ EFI_IPv6_ADDRESS addresses[2] = {
++ // 2001:db8:85a3::8a2e:370:7334
++ { 0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x34 },
++ // fe80::d478:91c3:ecd7:4ff9
++ { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x78, 0x91, 0xc3, 0xec, 0xd7, 0x4f, 0xf9 }
++ };
++
++ CopyMem (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, &addresses, sizeof (addresses));
++
++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (sizeof (addresses));
++
++ Private.DnsServer = NULL;
++
++ ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_SUCCESS);
++
++ ASSERT_NE (Private.DnsServer, nullptr);
++
++ //
++ // This is expected to fail until DnsServer supports multiple DNS servers
++ //
++ // This is tracked in https://bugzilla.tianocore.org/show_bug.cgi?id=1886
++ //
++ // Disabling:
++ // ASSERT_EQ (CompareMem(Private.DnsServer, &addresses, sizeof(addresses)), 0);
++
++ if (Private.DnsServer) {
++ FreePool (Private.DnsServer);
++ }
++}
+diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h
+new file mode 100644
+index 0000000000..b17c314791
+--- /dev/null
++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h
+@@ -0,0 +1,50 @@
++/** @file
++ This file exposes the internal interfaces which may be unit tested
++ for the PxeBcDhcp6Dxe driver.
++
++ Copyright (c) Microsoft Corporation.<BR>
++ SPDX-License-Identifier: BSD-2-Clause-Patent
++**/
++
++#ifndef PXE_BC_DHCP6_GOOGLE_TEST_H_
++#define PXE_BC_DHCP6_GOOGLE_TEST_H_
++
++//
++// Minimal includes needed to compile
++//
++#include <Uefi.h>
++#include "../PxeBcImpl.h"
++
++/**
++ Handle the DHCPv6 offer packet.
++
++ @param[in] Private The pointer to PXEBC_PRIVATE_DATA.
++
++ @retval EFI_SUCCESS Handled the DHCPv6 offer packet successfully.
++ @retval EFI_NO_RESPONSE No response to the following request packet.
++ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
++ @retval EFI_BUFFER_TOO_SMALL Can't cache the offer pacet.
++
++**/
++EFI_STATUS
++PxeBcHandleDhcp6Offer (
++ IN PXEBC_PRIVATE_DATA *Private
++ );
++
++/**
++ Cache the DHCPv6 Server address
++
++ @param[in] Private The pointer to PXEBC_PRIVATE_DATA.
++ @param[in] Cache6 The pointer to PXEBC_DHCP6_PACKET_CACHE.
++
++ @retval EFI_SUCCESS Cache the DHCPv6 Server address successfully.
++ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
++ @retval EFI_DEVICE_ERROR Failed to cache the DHCPv6 Server address.
++**/
++EFI_STATUS
++PxeBcCacheDnsServerAddresses (
++ IN PXEBC_PRIVATE_DATA *Private,
++ IN PXEBC_DHCP6_PACKET_CACHE *Cache6
++ );
++
++#endif // PXE_BC_DHCP6_GOOGLE_TEST_H_
+diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp
+new file mode 100644
+index 0000000000..cc4fdf525b
+--- /dev/null
++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp
+@@ -0,0 +1,19 @@
++/** @file
++ Acts as the main entry point for the tests for the UefiPxeBcDxe module.
++ Copyright (c) Microsoft Corporation
++ SPDX-License-Identifier: BSD-2-Clause-Patent
++**/
++#include <gtest/gtest.h>
++
++////////////////////////////////////////////////////////////////////////////////
++// Run the tests
++////////////////////////////////////////////////////////////////////////////////
++int
++main (
++ int argc,
++ char *argv[]
++ )
++{
++ testing::InitGoogleTest (&argc, argv);
++ return RUN_ALL_TESTS ();
++}
+diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
+new file mode 100644
+index 0000000000..301dcdf611
+--- /dev/null
++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
+@@ -0,0 +1,48 @@
++## @file
++# Unit test suite for the UefiPxeBcDxe using Google Test
++#
++# Copyright (c) Microsoft Corporation.<BR>
++# SPDX-License-Identifier: BSD-2-Clause-Patent
++##
++[Defines]
++INF_VERSION = 0x00010005
++BASE_NAME = UefiPxeBcDxeGoogleTest
++FILE_GUID = 77D45C64-EC1E-4174-887B-886E89FD1EDF
++MODULE_TYPE = HOST_APPLICATION
++VERSION_STRING = 1.0
++
++#
++# The following information is for reference only and not required by the build tools.
++#
++# VALID_ARCHITECTURES = IA32 X64
++#
++
++[Sources]
++ UefiPxeBcDxeGoogleTest.cpp
++ PxeBcDhcp6GoogleTest.cpp
++ PxeBcDhcp6GoogleTest.h
++ ../PxeBcDhcp6.c
++ ../PxeBcSupport.c
++
++[Packages]
++ MdePkg/MdePkg.dec
++ MdeModulePkg/MdeModulePkg.dec
++ UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
++ NetworkPkg/NetworkPkg.dec
++
++[LibraryClasses]
++ GoogleTestLib
++ DebugLib
++ NetLib
++ PcdLib
++
++[Protocols]
++ gEfiDhcp6ServiceBindingProtocolGuid
++ gEfiDns6ServiceBindingProtocolGuid
++ gEfiDns6ProtocolGuid
++
++[Pcd]
++ gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType
++
++[Guids]
++ gZeroGuid
+--
+2.40.0
+
diff --git a/meta/recipes-core/ovmf/ovmf_git.bb b/meta/recipes-core/ovmf/ovmf_git.bb
index fc87cdf441..ac6a0a40e7 100644
--- a/meta/recipes-core/ovmf/ovmf_git.bb
+++ b/meta/recipes-core/ovmf/ovmf_git.bb
@@ -39,6 +39,8 @@ SRC_URI = "gitsm://github.com/tianocore/edk2.git;branch=master;protocol=https \
file://CVE-2023-45231-0002.patch \
file://CVE-2023-45232-CVE-2023-45233-0001.patch \
file://CVE-2023-45232-CVE-2023-45233-0002.patch \
+ file://CVE-2023-45234-0001.patch \
+ file://CVE-2023-45234-0002.patch \
"
PV = "edk2-stable202202"
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 07/38] ovmf: Fix CVE-2023-45235
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (5 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 06/38] ovmf: Fix CVE-2023-45234 Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 08/38] ovmf: Fix CVE-2023-45229 Steve Sakoman
` (30 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
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
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 08/38] ovmf: Fix CVE-2023-45229
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (6 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 07/38] ovmf: Fix CVE-2023-45235 Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 09/38] ovmf: Fix CVE-2023-45237 Steve Sakoman
` (29 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Soumya Sambu <soumya.sambu@windriver.com>
EDK2's Network Package is susceptible to an out-of-bounds read
vulnerability when processing the IA_NA or IA_TA option in a DHCPv6
Advertise message. This vulnerability can be exploited by an attacker
to gain unauthorized access and potentially lead to a loss of
Confidentiality.
References:
https://nvd.nist.gov/vuln/detail/CVE-2023-45229
Upstream-patches:
https://github.com/tianocore/edk2/commit/1dbb10cc52dc8ef49bb700daa1cefc76b26d52e0
https://github.com/tianocore/edk2/commit/07362769ab7a7d74dbea1c7a7a3662c7b5d1f097
https://github.com/tianocore/edk2/commit/1c440a5eceedc64e892877eeac0f1a4938f5abbb
https://github.com/tianocore/edk2/commit/1d0b95f6457d225c5108302a9da74b4ed7aa5a38
Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
---
.../ovmf/ovmf/CVE-2023-45229-0001.patch | 604 ++++++++++++++++++
.../ovmf/ovmf/CVE-2023-45229-0002.patch | 539 ++++++++++++++++
.../ovmf/ovmf/CVE-2023-45229-0003.patch | 244 +++++++
.../ovmf/ovmf/CVE-2023-45229-0004.patch | 157 +++++
meta/recipes-core/ovmf/ovmf_git.bb | 4 +
5 files changed, 1548 insertions(+)
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45229-0001.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45229-0002.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45229-0003.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45229-0004.patch
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2023-45229-0001.patch b/meta/recipes-core/ovmf/ovmf/CVE-2023-45229-0001.patch
new file mode 100644
index 0000000000..9d8549b27d
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/CVE-2023-45229-0001.patch
@@ -0,0 +1,604 @@
+From 1dbb10cc52dc8ef49bb700daa1cefc76b26d52e0 Mon Sep 17 00:00:00 2001
+From: "Doug Flick via groups.io" <dougflick=microsoft.com@groups.io>
+Date: Fri, 26 Jan 2024 05:54:46 +0800
+Subject: [PATCH] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Patch
+
+REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4534
+
+Bug Details:
+PixieFail Bug #1
+CVE-2023-45229
+CVSS 6.5 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
+CWE-125 Out-of-bounds Read
+
+Change Overview:
+
+Introduce Dhcp6SeekInnerOptionSafe which performs checks before seeking
+the Inner Option from a DHCP6 Option.
+
+>
+> EFI_STATUS
+> Dhcp6SeekInnerOptionSafe (
+> IN UINT16 IaType,
+> IN UINT8 *Option,
+> IN UINT32 OptionLen,
+> OUT UINT8 **IaInnerOpt,
+> OUT UINT16 *IaInnerLen
+> );
+>
+
+Lots of code cleanup to improve code readability.
+
+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-45229
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/1dbb10cc52dc8ef49bb700daa1cefc76b26d52e0]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h | 138 +++++++++++++++++++---
+ NetworkPkg/Dhcp6Dxe/Dhcp6Io.c | 203 +++++++++++++++++++++-----------
+ 2 files changed, 256 insertions(+), 85 deletions(-)
+
+diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h
+index f2422c2f28..220e7c68f1 100644
+--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h
++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h
+@@ -45,6 +45,20 @@ typedef struct _DHCP6_INSTANCE DHCP6_INSTANCE;
+ #define DHCP6_SERVICE_SIGNATURE SIGNATURE_32 ('D', 'H', '6', 'S')
+ #define DHCP6_INSTANCE_SIGNATURE SIGNATURE_32 ('D', 'H', '6', 'I')
+
++#define DHCP6_PACKET_ALL 0
++#define DHCP6_PACKET_STATEFUL 1
++#define DHCP6_PACKET_STATELESS 2
++
++#define DHCP6_BASE_PACKET_SIZE 1024
++
++#define DHCP6_PORT_CLIENT 546
++#define DHCP6_PORT_SERVER 547
++
++#define DHCP_CHECK_MEDIA_WAITING_TIME EFI_TIMER_PERIOD_SECONDS(20)
++
++#define DHCP6_INSTANCE_FROM_THIS(Instance) CR ((Instance), DHCP6_INSTANCE, Dhcp6, DHCP6_INSTANCE_SIGNATURE)
++#define DHCP6_SERVICE_FROM_THIS(Service) CR ((Service), DHCP6_SERVICE, ServiceBinding, DHCP6_SERVICE_SIGNATURE)
++
+ //
+ // For more information on DHCP options see RFC 8415, Section 21.1
+ //
+@@ -59,12 +73,10 @@ typedef struct _DHCP6_INSTANCE DHCP6_INSTANCE;
+ // | (option-len octets) |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ //
+-#define DHCP6_SIZE_OF_OPT_CODE (sizeof(UINT16))
+-#define DHCP6_SIZE_OF_OPT_LEN (sizeof(UINT16))
++#define DHCP6_SIZE_OF_OPT_CODE (sizeof (((EFI_DHCP6_PACKET_OPTION *)0)->OpCode))
++#define DHCP6_SIZE_OF_OPT_LEN (sizeof (((EFI_DHCP6_PACKET_OPTION *)0)->OpLen))
+
+-//
+ // Combined size of Code and Length
+-//
+ #define DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN (DHCP6_SIZE_OF_OPT_CODE + \
+ DHCP6_SIZE_OF_OPT_LEN)
+
+@@ -73,34 +85,122 @@ STATIC_ASSERT (
+ "Combined size of Code and Length must be 4 per RFC 8415"
+ );
+
+-//
+ // Offset to the length is just past the code
+-//
+-#define DHCP6_OPT_LEN_OFFSET(a) (a + DHCP6_SIZE_OF_OPT_CODE)
++#define DHCP6_OFFSET_OF_OPT_LEN(a) (a + DHCP6_SIZE_OF_OPT_CODE)
+ STATIC_ASSERT (
+- DHCP6_OPT_LEN_OFFSET (0) == 2,
++ DHCP6_OFFSET_OF_OPT_LEN (0) == 2,
+ "Offset of length is + 2 past start of option"
+ );
+
+-#define DHCP6_OPT_DATA_OFFSET(a) (a + DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN)
++#define DHCP6_OFFSET_OF_OPT_DATA(a) (a + DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN)
+ STATIC_ASSERT (
+- DHCP6_OPT_DATA_OFFSET (0) == 4,
++ DHCP6_OFFSET_OF_OPT_DATA (0) == 4,
+ "Offset to option data should be +4 from start of option"
+ );
++//
++// Identity Association options (both NA (Non-Temporary) and TA (Temporary Association))
++// are defined in RFC 8415 and are a deriviation of a TLV stucture
++// For more information on IA_NA see Section 21.4
++// For more information on IA_TA see Section 21.5
++//
++//
++// The format of IA_NA and IA_TA option:
++//
++// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++// | OPTION_IA_NA | option-len |
++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++// | IAID (4 octets) |
++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++// | T1 (only for IA_NA) |
++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++// | T2 (only for IA_NA) |
++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++// | |
++// . IA_NA-options/IA_TA-options .
++// . .
++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++//
++#define DHCP6_SIZE_OF_IAID (sizeof(UINT32))
++#define DHCP6_SIZE_OF_TIME_INTERVAL (sizeof(UINT32))
+
+-#define DHCP6_PACKET_ALL 0
+-#define DHCP6_PACKET_STATEFUL 1
+-#define DHCP6_PACKET_STATELESS 2
++// Combined size of IAID, T1, and T2
++#define DHCP6_SIZE_OF_COMBINED_IAID_T1_T2 (DHCP6_SIZE_OF_IAID + \
++ DHCP6_SIZE_OF_TIME_INTERVAL + \
++ DHCP6_SIZE_OF_TIME_INTERVAL)
++STATIC_ASSERT (
++ DHCP6_SIZE_OF_COMBINED_IAID_T1_T2 == 12,
++ "Combined size of IAID, T1, T2 must be 12 per RFC 8415"
++ );
+
+-#define DHCP6_BASE_PACKET_SIZE 1024
++// This is the size of IA_TA without options
++#define DHCP6_MIN_SIZE_OF_IA_TA (DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN + \
++ DHCP6_SIZE_OF_IAID)
++STATIC_ASSERT (
++ DHCP6_MIN_SIZE_OF_IA_TA == 8,
++ "Minimum combined size of IA_TA per RFC 8415"
++ );
+
+-#define DHCP6_PORT_CLIENT 546
+-#define DHCP6_PORT_SERVER 547
++// Offset to a IA_TA inner option
++#define DHCP6_OFFSET_OF_IA_TA_INNER_OPT(a) (a + DHCP6_MIN_SIZE_OF_IA_TA)
++STATIC_ASSERT (
++ DHCP6_OFFSET_OF_IA_TA_INNER_OPT (0) == 8,
++ "Offset of IA_TA Inner option is + 8 past start of option"
++ );
+
+-#define DHCP_CHECK_MEDIA_WAITING_TIME EFI_TIMER_PERIOD_SECONDS(20)
++// This is the size of IA_NA without options (16)
++#define DHCP6_MIN_SIZE_OF_IA_NA DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN + \
++ DHCP6_SIZE_OF_COMBINED_IAID_T1_T2
++STATIC_ASSERT (
++ DHCP6_MIN_SIZE_OF_IA_NA == 16,
++ "Minimum combined size of IA_TA per RFC 8415"
++ );
+
+-#define DHCP6_INSTANCE_FROM_THIS(Instance) CR ((Instance), DHCP6_INSTANCE, Dhcp6, DHCP6_INSTANCE_SIGNATURE)
+-#define DHCP6_SERVICE_FROM_THIS(Service) CR ((Service), DHCP6_SERVICE, ServiceBinding, DHCP6_SERVICE_SIGNATURE)
++#define DHCP6_OFFSET_OF_IA_NA_INNER_OPT(a) (a + DHCP6_MIN_SIZE_OF_IA_NA)
++STATIC_ASSERT (
++ DHCP6_OFFSET_OF_IA_NA_INNER_OPT (0) == 16,
++ "Offset of IA_NA Inner option is + 16 past start of option"
++ );
++
++#define DHCP6_OFFSET_OF_IA_NA_T1(a) (a + \
++ DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN + \
++ DHCP6_SIZE_OF_IAID)
++STATIC_ASSERT (
++ DHCP6_OFFSET_OF_IA_NA_T1 (0) == 8,
++ "Offset of IA_NA Inner option is + 8 past start of option"
++ );
++
++#define DHCP6_OFFSET_OF_IA_NA_T2(a) (a + \
++ DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN +\
++ DHCP6_SIZE_OF_IAID + \
++ DHCP6_SIZE_OF_TIME_INTERVAL)
++STATIC_ASSERT (
++ DHCP6_OFFSET_OF_IA_NA_T2 (0) == 12,
++ "Offset of IA_NA Inner option is + 12 past start of option"
++ );
++
++//
++// For more information see RFC 8415 Section 21.13
++//
++// The format of the Status Code Option:
++//
++// 0 1 2 3
++// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++// | OPTION_STATUS_CODE | option-len |
++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++// | status-code | |
++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
++// . .
++// . status-message .
++// . .
++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++//
++#define DHCP6_OFFSET_OF_STATUS_CODE(a) (a + DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN)
++STATIC_ASSERT (
++ DHCP6_OFFSET_OF_STATUS_CODE (0) == 4,
++ "Offset of status is + 4 past start of option"
++ );
+
+ extern EFI_IPv6_ADDRESS mAllDhcpRelayAndServersAddress;
+ extern EFI_DHCP6_PROTOCOL gDhcp6ProtocolTemplate;
+diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
+index bf5aa7a769..89d16484a5 100644
+--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
+@@ -598,8 +598,8 @@ Dhcp6UpdateIaInfo (
+ // The inner options still start with 2 bytes option-code and 2 bytes option-len.
+ //
+ if (Instance->Config->IaDescriptor.Type == Dhcp6OptIana) {
+- T1 = NTOHL (ReadUnaligned32 ((UINT32 *)(Option + 8)));
+- T2 = NTOHL (ReadUnaligned32 ((UINT32 *)(Option + 12)));
++ T1 = NTOHL (ReadUnaligned32 ((UINT32 *)(DHCP6_OFFSET_OF_IA_NA_T1 (Option))));
++ T2 = NTOHL (ReadUnaligned32 ((UINT32 *)(DHCP6_OFFSET_OF_IA_NA_T2 (Option))));
+ //
+ // Refer to RFC3155 Chapter 22.4. If a client receives an IA_NA with T1 greater than T2,
+ // and both T1 and T2 are greater than 0, the client discards the IA_NA option and processes
+@@ -609,13 +609,14 @@ Dhcp6UpdateIaInfo (
+ return EFI_DEVICE_ERROR;
+ }
+
+- IaInnerOpt = Option + 16;
+- IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(Option + 2))) - 12);
++ IaInnerOpt = DHCP6_OFFSET_OF_IA_NA_INNER_OPT (Option);
++ IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN (Option)))) - DHCP6_SIZE_OF_COMBINED_IAID_T1_T2);
+ } else {
+- T1 = 0;
+- T2 = 0;
+- IaInnerOpt = Option + 8;
+- IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(Option + 2))) - 4);
++ T1 = 0;
++ T2 = 0;
++
++ IaInnerOpt = DHCP6_OFFSET_OF_IA_TA_INNER_OPT (Option);
++ IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN (Option)))) - DHCP6_SIZE_OF_IAID);
+ }
+
+ //
+@@ -641,7 +642,7 @@ Dhcp6UpdateIaInfo (
+ Option = Dhcp6SeekOption (IaInnerOpt, IaInnerLen, Dhcp6OptStatusCode);
+
+ if (Option != NULL) {
+- StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(Option + 4)));
++ StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN (Option))));
+ if (StsCode != Dhcp6StsSuccess) {
+ return EFI_DEVICE_ERROR;
+ }
+@@ -661,6 +662,87 @@ Dhcp6UpdateIaInfo (
+ return Status;
+ }
+
++/**
++ Seeks the Inner Options from a DHCP6 Option
++
++ @param[in] IaType The type of the IA option.
++ @param[in] Option The pointer to the DHCP6 Option.
++ @param[in] OptionLen The length of the DHCP6 Option.
++ @param[out] IaInnerOpt The pointer to the IA inner option.
++ @param[out] IaInnerLen The length of the IA inner option.
++
++ @retval EFI_SUCCESS Seek the inner option successfully.
++ @retval EFI_DEVICE_ERROR The OptionLen is invalid. On Error,
++ the pointers are not modified
++**/
++EFI_STATUS
++Dhcp6SeekInnerOptionSafe (
++ IN UINT16 IaType,
++ IN UINT8 *Option,
++ IN UINT32 OptionLen,
++ OUT UINT8 **IaInnerOpt,
++ OUT UINT16 *IaInnerLen
++ )
++{
++ UINT16 IaInnerLenTmp;
++ UINT8 *IaInnerOptTmp;
++
++ if (Option == NULL) {
++ ASSERT (Option != NULL);
++ return EFI_DEVICE_ERROR;
++ }
++
++ if (IaInnerOpt == NULL) {
++ ASSERT (IaInnerOpt != NULL);
++ return EFI_DEVICE_ERROR;
++ }
++
++ if (IaInnerLen == NULL) {
++ ASSERT (IaInnerLen != NULL);
++ return EFI_DEVICE_ERROR;
++ }
++
++ if (IaType == Dhcp6OptIana) {
++ // Verify we have a fully formed IA_NA
++ if (OptionLen < DHCP6_MIN_SIZE_OF_IA_NA) {
++ return EFI_DEVICE_ERROR;
++ }
++
++ //
++ IaInnerOptTmp = DHCP6_OFFSET_OF_IA_NA_INNER_OPT (Option);
++
++ // Verify the IaInnerLen is valid.
++ IaInnerLenTmp = (UINT16)NTOHS (ReadUnaligned16 ((UINT16 *)DHCP6_OFFSET_OF_OPT_LEN (Option)));
++ if (IaInnerLenTmp < DHCP6_SIZE_OF_COMBINED_IAID_T1_T2) {
++ return EFI_DEVICE_ERROR;
++ }
++
++ IaInnerLenTmp -= DHCP6_SIZE_OF_COMBINED_IAID_T1_T2;
++ } else if (IaType == Dhcp6OptIata) {
++ // Verify the OptionLen is valid.
++ if (OptionLen < DHCP6_MIN_SIZE_OF_IA_TA) {
++ return EFI_DEVICE_ERROR;
++ }
++
++ IaInnerOptTmp = DHCP6_OFFSET_OF_IA_TA_INNER_OPT (Option);
++
++ // Verify the IaInnerLen is valid.
++ IaInnerLenTmp = (UINT16)NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN (Option))));
++ if (IaInnerLenTmp < DHCP6_SIZE_OF_IAID) {
++ return EFI_DEVICE_ERROR;
++ }
++
++ IaInnerLenTmp -= DHCP6_SIZE_OF_IAID;
++ } else {
++ return EFI_DEVICE_ERROR;
++ }
++
++ *IaInnerOpt = IaInnerOptTmp;
++ *IaInnerLen = IaInnerLenTmp;
++
++ return EFI_SUCCESS;
++}
++
+ /**
+ Seek StatusCode Option in package. A Status Code option may appear in the
+ options field of a DHCP message and/or in the options field of another option.
+@@ -684,6 +766,12 @@ Dhcp6SeekStsOption (
+ UINT8 *IaInnerOpt;
+ UINT16 IaInnerLen;
+ UINT16 StsCode;
++ UINT32 OptionLen;
++
++ // OptionLen is the length of the Options excluding the DHCP header.
++ // Length of the EFI_DHCP6_PACKET from the first byte of the Header field to the last
++ // byte of the Option[] field.
++ OptionLen = Packet->Length - sizeof (Packet->Dhcp6.Header);
+
+ //
+ // Seek StatusCode option directly in DHCP message body. That is, search in
+@@ -691,12 +779,12 @@ Dhcp6SeekStsOption (
+ //
+ *Option = Dhcp6SeekOption (
+ Packet->Dhcp6.Option,
+- Packet->Length - 4,
++ OptionLen,
+ Dhcp6OptStatusCode
+ );
+
+ if (*Option != NULL) {
+- StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(*Option + 4)));
++ StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_STATUS_CODE (*Option))));
+ if (StsCode != Dhcp6StsSuccess) {
+ return EFI_DEVICE_ERROR;
+ }
+@@ -707,7 +795,7 @@ Dhcp6SeekStsOption (
+ //
+ *Option = Dhcp6SeekIaOption (
+ Packet->Dhcp6.Option,
+- Packet->Length - sizeof (EFI_DHCP6_HEADER),
++ OptionLen,
+ &Instance->Config->IaDescriptor
+ );
+ if (*Option == NULL) {
+@@ -715,52 +803,35 @@ Dhcp6SeekStsOption (
+ }
+
+ //
+- // The format of the IA_NA option is:
++ // Calculate the distance from Packet->Dhcp6.Option to the IA option.
+ //
+- // 0 1 2 3
+- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+- // | OPTION_IA_NA | option-len |
+- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+- // | IAID (4 octets) |
+- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+- // | T1 |
+- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+- // | T2 |
+- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+- // | |
+- // . IA_NA-options .
+- // . .
+- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ // Packet->Size and Packet->Length are both UINT32 type, and Packet->Size is
++ // the size of the whole packet, including the DHCP header, and Packet->Length
++ // is the length of the DHCP message body, excluding the DHCP header.
+ //
+- // The format of the IA_TA option is:
++ // (*Option - Packet->Dhcp6.Option) is the number of bytes from the start of
++ // DHCP6 option area to the start of the IA option.
+ //
+- // 0 1 2 3
+- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+- // | OPTION_IA_TA | option-len |
+- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+- // | IAID (4 octets) |
+- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+- // | |
+- // . IA_TA-options .
+- // . .
+- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ // Dhcp6SeekInnerOptionSafe() is searching starting from the start of the
++ // IA option to the end of the DHCP6 option area, thus subtract the space
++ // up until this option
+ //
++ OptionLen = OptionLen - (*Option - Packet->Dhcp6.Option);
+
+ //
+- // sizeof (option-code + option-len + IaId) = 8
+- // sizeof (option-code + option-len + IaId + T1) = 12
+- // sizeof (option-code + option-len + IaId + T1 + T2) = 16
+- //
+- // The inner options still start with 2 bytes option-code and 2 bytes option-len.
++ // Seek the inner option
+ //
+- if (Instance->Config->IaDescriptor.Type == Dhcp6OptIana) {
+- IaInnerOpt = *Option + 16;
+- IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(*Option + 2))) - 12);
+- } else {
+- IaInnerOpt = *Option + 8;
+- IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(*Option + 2))) - 4);
++ if (EFI_ERROR (
++ Dhcp6SeekInnerOptionSafe (
++ Instance->Config->IaDescriptor.Type,
++ *Option,
++ OptionLen,
++ &IaInnerOpt,
++ &IaInnerLen
++ )
++ ))
++ {
++ return EFI_DEVICE_ERROR;
+ }
+
+ //
+@@ -784,7 +855,7 @@ Dhcp6SeekStsOption (
+ //
+ *Option = Dhcp6SeekOption (IaInnerOpt, IaInnerLen, Dhcp6OptStatusCode);
+ if (*Option != NULL) {
+- StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(*Option + 4)));
++ StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)((DHCP6_OFFSET_OF_STATUS_CODE (*Option)))));
+ if (StsCode != Dhcp6StsSuccess) {
+ return EFI_DEVICE_ERROR;
+ }
+@@ -1105,7 +1176,7 @@ Dhcp6SendRequestMsg (
+ //
+ Option = Dhcp6SeekOption (
+ Instance->AdSelect->Dhcp6.Option,
+- Instance->AdSelect->Length - 4,
++ Instance->AdSelect->Length - sizeof (EFI_DHCP6_HEADER),
+ Dhcp6OptServerId
+ );
+ if (Option == NULL) {
+@@ -1289,7 +1360,7 @@ Dhcp6SendDeclineMsg (
+ //
+ Option = Dhcp6SeekOption (
+ LastReply->Dhcp6.Option,
+- LastReply->Length - 4,
++ LastReply->Length - sizeof (EFI_DHCP6_HEADER),
+ Dhcp6OptServerId
+ );
+ if (Option == NULL) {
+@@ -1448,7 +1519,7 @@ Dhcp6SendReleaseMsg (
+ //
+ Option = Dhcp6SeekOption (
+ LastReply->Dhcp6.Option,
+- LastReply->Length - 4,
++ LastReply->Length - sizeof (EFI_DHCP6_HEADER),
+ Dhcp6OptServerId
+ );
+ if (Option == NULL) {
+@@ -1673,7 +1744,7 @@ Dhcp6SendRenewRebindMsg (
+
+ Option = Dhcp6SeekOption (
+ LastReply->Dhcp6.Option,
+- LastReply->Length - 4,
++ LastReply->Length - sizeof (EFI_DHCP6_HEADER),
+ Dhcp6OptServerId
+ );
+ if (Option == NULL) {
+@@ -2208,7 +2279,7 @@ Dhcp6HandleReplyMsg (
+ //
+ Option = Dhcp6SeekOption (
+ Packet->Dhcp6.Option,
+- Packet->Length - 4,
++ Packet->Length - sizeof (EFI_DHCP6_HEADER),
+ Dhcp6OptRapidCommit
+ );
+
+@@ -2354,7 +2425,7 @@ Dhcp6HandleReplyMsg (
+ //
+ // Any error status code option is found.
+ //
+- StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(Option + 4)));
++ StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)((DHCP6_OFFSET_OF_STATUS_CODE (Option)))));
+ switch (StsCode) {
+ case Dhcp6StsUnspecFail:
+ //
+@@ -2487,7 +2558,7 @@ Dhcp6SelectAdvertiseMsg (
+ //
+ Option = Dhcp6SeekOption (
+ AdSelect->Dhcp6.Option,
+- AdSelect->Length - 4,
++ AdSelect->Length - sizeof (EFI_DHCP6_HEADER),
+ Dhcp6OptServerUnicast
+ );
+
+@@ -2498,7 +2569,7 @@ Dhcp6SelectAdvertiseMsg (
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+- CopyMem (Instance->Unicast, Option + 4, sizeof (EFI_IPv6_ADDRESS));
++ CopyMem (Instance->Unicast, DHCP6_OFFSET_OF_OPT_DATA (Option), sizeof (EFI_IPv6_ADDRESS));
+ }
+
+ //
+@@ -2551,7 +2622,7 @@ Dhcp6HandleAdvertiseMsg (
+ //
+ Option = Dhcp6SeekOption (
+ Packet->Dhcp6.Option,
+- Packet->Length - 4,
++ Packet->Length - sizeof (EFI_DHCP6_HEADER),
+ Dhcp6OptRapidCommit
+ );
+
+@@ -2645,7 +2716,7 @@ Dhcp6HandleAdvertiseMsg (
+ CopyMem (Instance->AdSelect, Packet, Packet->Size);
+
+ if (Option != NULL) {
+- Instance->AdPref = *(Option + 4);
++ Instance->AdPref = *(DHCP6_OFFSET_OF_OPT_DATA (Option));
+ }
+ } else {
+ //
+@@ -2714,11 +2785,11 @@ Dhcp6HandleStateful (
+ //
+ Option = Dhcp6SeekOption (
+ Packet->Dhcp6.Option,
+- Packet->Length - 4,
++ Packet->Length - DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN,
+ Dhcp6OptClientId
+ );
+
+- if ((Option == NULL) || (CompareMem (Option + 4, ClientId->Duid, ClientId->Length) != 0)) {
++ if ((Option == NULL) || (CompareMem (DHCP6_OFFSET_OF_OPT_DATA (Option), ClientId->Duid, ClientId->Length) != 0)) {
+ goto ON_CONTINUE;
+ }
+
+@@ -2727,7 +2798,7 @@ Dhcp6HandleStateful (
+ //
+ Option = Dhcp6SeekOption (
+ Packet->Dhcp6.Option,
+- Packet->Length - 4,
++ Packet->Length - DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN,
+ Dhcp6OptServerId
+ );
+
+@@ -2832,7 +2903,7 @@ Dhcp6HandleStateless (
+ //
+ Option = Dhcp6SeekOption (
+ Packet->Dhcp6.Option,
+- Packet->Length - 4,
++ Packet->Length - sizeof (EFI_DHCP6_HEADER),
+ Dhcp6OptServerId
+ );
+
+--
+2.40.0
+
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2023-45229-0002.patch b/meta/recipes-core/ovmf/ovmf/CVE-2023-45229-0002.patch
new file mode 100644
index 0000000000..7ce5c98789
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/CVE-2023-45229-0002.patch
@@ -0,0 +1,539 @@
+From 07362769ab7a7d74dbea1c7a7a3662c7b5d1f097 Mon Sep 17 00:00:00 2001
+From: "Doug Flick via groups.io" <dougflick=microsoft.com@groups.io>
+Date: Fri, 26 Jan 2024 05:54:47 +0800
+Subject: [PATCH] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Unit
+ Tests
+
+REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4534
+
+These tests confirm that the report bug...
+
+"Out-of-bounds read when processing IA_NA/IA_TA options in a
+DHCPv6 Advertise message"
+
+..has been patched.
+
+The following functions are tested to confirm an out of bounds read is
+patched and that the correct statuses are returned:
+
+Dhcp6SeekInnerOptionSafe
+Dhcp6SeekStsOption
+
+TCBZ4534
+CVE-2023-45229
+CVSS 6.5 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
+CWE-125 Out-of-bounds Read
+
+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-45229
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/07362769ab7a7d74dbea1c7a7a3662c7b5d1f097]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ NetworkPkg/Dhcp6Dxe/Dhcp6Io.c | 2 +-
+ .../GoogleTest/Dhcp6DxeGoogleTest.inf | 1 +
+ .../Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp | 365 +++++++++++++++++-
+ .../Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h | 58 +++
+ 4 files changed, 423 insertions(+), 3 deletions(-)
+ create mode 100644 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h
+
+diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
+index 89d16484a5..3b8feb4a20 100644
+--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
+@@ -816,7 +816,7 @@ Dhcp6SeekStsOption (
+ // IA option to the end of the DHCP6 option area, thus subtract the space
+ // up until this option
+ //
+- OptionLen = OptionLen - (*Option - Packet->Dhcp6.Option);
++ OptionLen = OptionLen - (UINT32)(*Option - Packet->Dhcp6.Option);
+
+ //
+ // Seek the inner option
+diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
+index 8e9119a371..12532ed30c 100644
+--- a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
++++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
+@@ -18,6 +18,7 @@
+ [Sources]
+ Dhcp6DxeGoogleTest.cpp
+ Dhcp6IoGoogleTest.cpp
++ Dhcp6IoGoogleTest.h
+ ../Dhcp6Io.c
+ ../Dhcp6Utility.c
+
+diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp
+index 7ee40e4af4..7db253a7b8 100644
+--- a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp
++++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp
+@@ -13,6 +13,7 @@ extern "C" {
+ #include <Library/BaseMemoryLib.h>
+ #include "../Dhcp6Impl.h"
+ #include "../Dhcp6Utility.h"
++ #include "Dhcp6IoGoogleTest.h"
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+@@ -21,7 +22,35 @@ extern "C" {
+
+ #define DHCP6_PACKET_MAX_LEN 1500
+
++// This definition is used by this test but is also required to compile
++// by Dhcp6Io.c
++#define DHCPV6_OPTION_IA_NA 3
++#define DHCPV6_OPTION_IA_TA 4
++
++#define SEARCH_PATTERN 0xDEADC0DE
++#define SEARCH_PATTERN_LEN sizeof(SEARCH_PATTERN)
++
+ ////////////////////////////////////////////////////////////////////////
++// Test structures for IA_NA and IA_TA options
++////////////////////////////////////////////////////////////////////////
++typedef struct {
++ UINT16 Code;
++ UINT16 Len;
++ UINT32 IAID;
++} DHCPv6_OPTION;
++
++typedef struct {
++ DHCPv6_OPTION Header;
++ UINT32 T1;
++ UINT32 T2;
++ UINT8 InnerOptions[0];
++} DHCPv6_OPTION_IA_NA;
++
++typedef struct {
++ DHCPv6_OPTION Header;
++ UINT8 InnerOptions[0];
++} DHCPv6_OPTION_IA_TA;
++
+ ////////////////////////////////////////////////////////////////////////
+ // Symbol Definitions
+ // These functions are not directly under test - but required to compile
+@@ -210,7 +239,7 @@ TEST_F (Dhcp6AppendETOptionTest, InvalidDataExpectBufferTooSmall) {
+ Status = Dhcp6AppendETOption (
+ Dhcp6AppendETOptionTest::Packet,
+ &Cursor,
+- &Instance, // Instance is not used in this function
++ &Instance, // Instance is not used in this function
+ &ElapsedTime
+ );
+
+@@ -240,7 +269,7 @@ TEST_F (Dhcp6AppendETOptionTest, ValidDataExpectSuccess) {
+ Status = Dhcp6AppendETOption (
+ Dhcp6AppendETOptionTest::Packet,
+ &Cursor,
+- &Instance, // Instance is not used in this function
++ &Instance, // Instance is not used in this function
+ &ElapsedTime
+ );
+
+@@ -476,3 +505,335 @@ TEST_F (Dhcp6AppendIaOptionTest, IaTaValidDataExpectSuccess) {
+ // verify that the status is EFI_SUCCESS
+ ASSERT_EQ (Status, EFI_SUCCESS);
+ }
++
++////////////////////////////////////////////////////////////////////////
++// Dhcp6SeekInnerOptionSafe Tests
++////////////////////////////////////////////////////////////////////////
++
++// Define a fixture for your tests if needed
++class Dhcp6SeekInnerOptionSafeTest : 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:
++// This test verifies that Dhcp6SeekInnerOptionSafe returns EFI_SUCCESS when the IANA option is found.
++TEST_F (Dhcp6SeekInnerOptionSafeTest, IANAValidOptionExpectSuccess) {
++ EFI_STATUS Result;
++ UINT8 Option[sizeof (DHCPv6_OPTION_IA_NA) + SEARCH_PATTERN_LEN] = { 0 };
++ UINT32 OptionLength = sizeof (Option);
++ DHCPv6_OPTION_IA_NA *OptionPtr = (DHCPv6_OPTION_IA_NA *)Option;
++ UINT32 SearchPattern = SEARCH_PATTERN;
++
++ UINTN SearchPatternLength = SEARCH_PATTERN_LEN;
++ UINT8 *InnerOptionPtr = NULL;
++ UINT16 InnerOptionLength = 0;
++
++ OptionPtr->Header.Code = Dhcp6OptIana;
++ OptionPtr->Header.Len = HTONS (4 + 12); // Valid length has to be more than 12
++ OptionPtr->Header.IAID = 0x12345678;
++ OptionPtr->T1 = 0x11111111;
++ OptionPtr->T2 = 0x22222222;
++ CopyMem (OptionPtr->InnerOptions, &SearchPattern, SearchPatternLength);
++
++ Result = Dhcp6SeekInnerOptionSafe (
++ Dhcp6OptIana,
++ Option,
++ OptionLength,
++ &InnerOptionPtr,
++ &InnerOptionLength
++ );
++ ASSERT_EQ (Result, EFI_SUCCESS);
++ ASSERT_EQ (InnerOptionLength, 4);
++ ASSERT_EQ (CompareMem (InnerOptionPtr, &SearchPattern, SearchPatternLength), 0);
++}
++
++// Test Description:
++// This test verifies that Dhcp6SeekInnerOptionSafe returns EFI_DEIVCE_ERROR when the IANA option size is invalid.
++TEST_F (Dhcp6SeekInnerOptionSafeTest, IANAInvalidSizeExpectFail) {
++ // Lets add an inner option of bytes we expect to find
++ EFI_STATUS Status;
++ UINT8 Option[sizeof (DHCPv6_OPTION_IA_NA) + SEARCH_PATTERN_LEN] = { 0 };
++ UINT32 OptionLength = sizeof (Option);
++ DHCPv6_OPTION_IA_NA *OptionPtr = (DHCPv6_OPTION_IA_NA *)Option;
++ UINT32 SearchPattern = SEARCH_PATTERN;
++
++ UINTN SearchPatternLength = SEARCH_PATTERN_LEN;
++ UINT8 *InnerOptionPtr = NULL;
++ UINT16 InnerOptionLength = 0;
++
++ OptionPtr->Header.Code = Dhcp6OptIana;
++ OptionPtr->Header.Len = HTONS (4); // Set the length to lower than expected (12)
++ OptionPtr->Header.IAID = 0x12345678;
++ OptionPtr->T1 = 0x11111111;
++ OptionPtr->T2 = 0x22222222;
++ CopyMem (OptionPtr->InnerOptions, &SearchPattern, SearchPatternLength);
++
++ // Set the InnerOptionLength to be less than the size of the option
++ Status = Dhcp6SeekInnerOptionSafe (
++ Dhcp6OptIana,
++ Option,
++ OptionLength,
++ &InnerOptionPtr,
++ &InnerOptionLength
++ );
++ ASSERT_EQ (Status, EFI_DEVICE_ERROR);
++
++ // Now set the OptionLength to be less than the size of the option
++ OptionLength = sizeof (DHCPv6_OPTION_IA_NA) - 1;
++ Status = Dhcp6SeekInnerOptionSafe (
++ Dhcp6OptIana,
++ Option,
++ OptionLength,
++ &InnerOptionPtr,
++ &InnerOptionLength
++ );
++ ASSERT_EQ (Status, EFI_DEVICE_ERROR);
++}
++
++// Test Description:
++// This test verifies that Dhcp6SeekInnerOptionSafe returns EFI_SUCCESS when the IATA option is found
++TEST_F (Dhcp6SeekInnerOptionSafeTest, IATAValidOptionExpectSuccess) {
++ // Lets add an inner option of bytes we expect to find
++ EFI_STATUS Status;
++ UINT8 Option[sizeof (DHCPv6_OPTION_IA_TA) + SEARCH_PATTERN_LEN] = { 0 };
++ UINT32 OptionLength = sizeof (Option);
++ DHCPv6_OPTION_IA_TA *OptionPtr = (DHCPv6_OPTION_IA_TA *)Option;
++ UINT32 SearchPattern = SEARCH_PATTERN;
++
++ UINTN SearchPatternLength = SEARCH_PATTERN_LEN;
++ UINT8 *InnerOptionPtr = NULL;
++ UINT16 InnerOptionLength = 0;
++
++ OptionPtr->Header.Code = Dhcp6OptIata;
++ OptionPtr->Header.Len = HTONS (4 + 4); // Valid length has to be more than 4
++ OptionPtr->Header.IAID = 0x12345678;
++ CopyMem (OptionPtr->InnerOptions, &SearchPattern, SearchPatternLength);
++
++ Status = Dhcp6SeekInnerOptionSafe (
++ Dhcp6OptIata,
++ Option,
++ OptionLength,
++ &InnerOptionPtr,
++ &InnerOptionLength
++ );
++ ASSERT_EQ (Status, EFI_SUCCESS);
++ ASSERT_EQ (InnerOptionLength, 4);
++ ASSERT_EQ (CompareMem (InnerOptionPtr, &SearchPattern, SearchPatternLength), 0);
++}
++
++// Test Description:
++// This test verifies that Dhcp6SeekInnerOptionSafe returns EFI_SUCCESS when the IATA option size is invalid.
++TEST_F (Dhcp6SeekInnerOptionSafeTest, IATAInvalidSizeExpectFail) {
++ // Lets add an inner option of bytes we expect to find
++ EFI_STATUS Status;
++ UINT8 Option[sizeof (DHCPv6_OPTION_IA_TA) + SEARCH_PATTERN_LEN] = { 0 };
++ UINT32 OptionLength = sizeof (Option);
++ DHCPv6_OPTION_IA_TA *OptionPtr = (DHCPv6_OPTION_IA_TA *)Option;
++ UINT32 SearchPattern = SEARCH_PATTERN;
++
++ UINTN SearchPatternLength = SEARCH_PATTERN_LEN;
++ UINT8 *InnerOptionPtr = NULL;
++ UINT16 InnerOptionLength = 0;
++
++ OptionPtr->Header.Code = Dhcp6OptIata;
++ OptionPtr->Header.Len = HTONS (2); // Set the length to lower than expected (4)
++ OptionPtr->Header.IAID = 0x12345678;
++ CopyMem (OptionPtr->InnerOptions, &SearchPattern, SearchPatternLength);
++
++ Status = Dhcp6SeekInnerOptionSafe (
++ Dhcp6OptIata,
++ Option,
++ OptionLength,
++ &InnerOptionPtr,
++ &InnerOptionLength
++ );
++ ASSERT_EQ (Status, EFI_DEVICE_ERROR);
++
++ // Now lets try modifying the OptionLength to be less than the size of the option
++ OptionLength = sizeof (DHCPv6_OPTION_IA_TA) - 1;
++ Status = Dhcp6SeekInnerOptionSafe (
++ Dhcp6OptIata,
++ Option,
++ OptionLength,
++ &InnerOptionPtr,
++ &InnerOptionLength
++ );
++ ASSERT_EQ (Status, EFI_DEVICE_ERROR);
++}
++
++// Test Description:
++// This test verifies that any other Option Type fails
++TEST_F (Dhcp6SeekInnerOptionSafeTest, InvalidOption) {
++ // Lets add an inner option of bytes we expect to find
++ EFI_STATUS Result;
++ UINT8 Option[sizeof (DHCPv6_OPTION_IA_TA) + SEARCH_PATTERN_LEN] = { 0 };
++ UINT32 OptionLength = sizeof (Option);
++ DHCPv6_OPTION_IA_TA *OptionPtr = (DHCPv6_OPTION_IA_TA *)Option;
++ UINT32 SearchPattern = SEARCH_PATTERN;
++
++ UINTN SearchPatternLength = SEARCH_PATTERN_LEN;
++ UINT8 *InnerOptionPtr = NULL;
++ UINT16 InnerOptionLength = 0;
++
++ OptionPtr->Header.Code = 0xC0DE;
++ OptionPtr->Header.Len = HTONS (2); // Set the length to lower than expected (4)
++ OptionPtr->Header.IAID = 0x12345678;
++ CopyMem (OptionPtr->InnerOptions, &SearchPattern, SearchPatternLength);
++
++ Result = Dhcp6SeekInnerOptionSafe (0xC0DE, Option, OptionLength, &InnerOptionPtr, &InnerOptionLength);
++ ASSERT_EQ (Result, EFI_DEVICE_ERROR);
++}
++
++////////////////////////////////////////////////////////////////////////
++// Dhcp6SeekStsOption Tests
++////////////////////////////////////////////////////////////////////////
++
++#define PACKET_SIZE (1500)
++
++class Dhcp6SeekStsOptionTest : public ::testing::Test {
++public:
++ DHCP6_INSTANCE Instance = { 0 };
++ EFI_DHCP6_PACKET *Packet = NULL;
++ EFI_DHCP6_CONFIG_DATA Config = { 0 };
++
++protected:
++ // Add any setup code if needed
++ virtual void
++ SetUp (
++ )
++ {
++ // Allocate a packet
++ Packet = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE);
++ ASSERT_NE (Packet, nullptr);
++
++ // Initialize the packet
++ Packet->Size = PACKET_SIZE;
++
++ Instance.Config = &Config;
++ }
++
++ // Add any cleanup code if needed
++ virtual void
++ TearDown (
++ )
++ {
++ // Clean up any resources or variables
++ FreePool (Packet);
++ }
++};
++
++// Test Description:
++// This test verifies that Dhcp6SeekStsOption returns EFI_DEVICE_ERROR when the option is invalid
++// This verifies that the calling function is working as expected
++TEST_F (Dhcp6SeekStsOptionTest, SeekIATAOptionExpectFail) {
++ EFI_STATUS Status;
++ UINT8 *Option = NULL;
++ UINT32 SearchPattern = SEARCH_PATTERN;
++ UINT16 SearchPatternLength = SEARCH_PATTERN_LEN;
++ UINT16 *Len = NULL;
++ EFI_DHCP6_IA Ia = { 0 };
++
++ Ia.Descriptor.Type = DHCPV6_OPTION_IA_TA;
++ Ia.IaAddressCount = 1;
++ Ia.IaAddress[0].PreferredLifetime = 0xDEADBEEF;
++ Ia.IaAddress[0].ValidLifetime = 0xDEADAAAA;
++ Ia.IaAddress[0].IpAddress = mAllDhcpRelayAndServersAddress;
++
++ Packet->Length = sizeof (EFI_DHCP6_HEADER);
++
++ Option = Dhcp6SeekStsOptionTest::Packet->Dhcp6.Option;
++
++ // Let's append the option to the packet
++ Status = Dhcp6AppendOption (
++ Dhcp6SeekStsOptionTest::Packet,
++ &Option,
++ Dhcp6OptStatusCode,
++ SearchPatternLength,
++ (UINT8 *)&SearchPattern
++ );
++ ASSERT_EQ (Status, EFI_SUCCESS);
++
++ // Inner option length - this will be overwritten later
++ Len = (UINT16 *)(Option + 2);
++
++ // Fill in the inner IA option
++ Status = Dhcp6AppendIaOption (
++ Dhcp6SeekStsOptionTest::Packet,
++ &Option,
++ &Ia,
++ 0x12345678,
++ 0x11111111,
++ 0x22222222
++ );
++ ASSERT_EQ (Status, EFI_SUCCESS);
++
++ // overwrite the len of inner Ia option
++ *Len = HTONS (3);
++
++ Dhcp6SeekStsOptionTest::Instance.Config->IaDescriptor.Type = DHCPV6_OPTION_IA_TA;
++
++ Option = NULL;
++ Status = Dhcp6SeekStsOption (&(Dhcp6SeekStsOptionTest::Instance), Dhcp6SeekStsOptionTest::Packet, &Option);
++
++ ASSERT_EQ (Status, EFI_DEVICE_ERROR);
++}
++
++// Test Description:
++// This test verifies that Dhcp6SeekInnerOptionSafe returns EFI_SUCCESS when the IATA option size is invalid.
++TEST_F (Dhcp6SeekStsOptionTest, SeekIANAOptionExpectSuccess) {
++ EFI_STATUS Status = EFI_NOT_FOUND;
++ UINT8 *Option = NULL;
++ UINT32 SearchPattern = SEARCH_PATTERN;
++ UINT16 SearchPatternLength = SEARCH_PATTERN_LEN;
++ EFI_DHCP6_IA Ia = { 0 };
++
++ Ia.Descriptor.Type = DHCPV6_OPTION_IA_NA;
++ Ia.IaAddressCount = 1;
++ Ia.IaAddress[0].PreferredLifetime = 0x11111111;
++ Ia.IaAddress[0].ValidLifetime = 0x22222222;
++ Ia.IaAddress[0].IpAddress = mAllDhcpRelayAndServersAddress;
++ Packet->Length = sizeof (EFI_DHCP6_HEADER);
++
++ Option = Dhcp6SeekStsOptionTest::Packet->Dhcp6.Option;
++
++ Status = Dhcp6AppendOption (
++ Dhcp6SeekStsOptionTest::Packet,
++ &Option,
++ Dhcp6OptStatusCode,
++ SearchPatternLength,
++ (UINT8 *)&SearchPattern
++ );
++ ASSERT_EQ (Status, EFI_SUCCESS);
++
++ Status = Dhcp6AppendIaOption (
++ Dhcp6SeekStsOptionTest::Packet,
++ &Option,
++ &Ia,
++ 0x12345678,
++ 0x11111111,
++ 0x22222222
++ );
++ ASSERT_EQ (Status, EFI_SUCCESS);
++
++ Dhcp6SeekStsOptionTest::Instance.Config->IaDescriptor.Type = DHCPV6_OPTION_IA_NA;
++
++ Option = NULL;
++ Status = Dhcp6SeekStsOption (&(Dhcp6SeekStsOptionTest::Instance), Dhcp6SeekStsOptionTest::Packet, &Option);
++
++ ASSERT_EQ (Status, EFI_SUCCESS);
++}
+diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h
+new file mode 100644
+index 0000000000..aed3b89082
+--- /dev/null
++++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h
+@@ -0,0 +1,58 @@
++/** @file
++ Acts as header for private functions under test in Dhcp6Io.c
++
++ Copyright (c) Microsoft Corporation
++ SPDX-License-Identifier: BSD-2-Clause-Patent
++**/
++
++#ifndef DHCP6_IO_GOOGLE_TEST_H_
++#define DHCP6_IO_GOOGLE_TEST_H_
++
++////////////////////////////////////////////////////////////////////////////////
++// These are the functions that are being unit tested
++////////////////////////////////////////////////////////////////////////////////
++
++#include <Uefi.h>
++
++/**
++ Seeks the Inner Options from a DHCP6 Option
++
++ @param[in] IaType The type of the IA option.
++ @param[in] Option The pointer to the DHCP6 Option.
++ @param[in] OptionLen The length of the DHCP6 Option.
++ @param[out] IaInnerOpt The pointer to the IA inner option.
++ @param[out] IaInnerLen The length of the IA inner option.
++
++ @retval EFI_SUCCESS Seek the inner option successfully.
++ @retval EFI_DEVICE_ERROR The OptionLen is invalid.
++*/
++EFI_STATUS
++Dhcp6SeekInnerOptionSafe (
++ UINT16 IaType,
++ UINT8 *Option,
++ UINT32 OptionLen,
++ UINT8 **IaInnerOpt,
++ UINT16 *IaInnerLen
++ );
++
++/**
++ Seek StatusCode Option in package. A Status Code option may appear in the
++ options field of a DHCP message and/or in the options field of another option.
++ See details in section 22.13, RFC3315.
++
++ @param[in] Instance The pointer to the Dhcp6 instance.
++ @param[in] Packet The pointer to reply messages.
++ @param[out] Option The pointer to status code option.
++
++ @retval EFI_SUCCESS Seek status code option successfully.
++ @retval EFI_DEVICE_ERROR An unexpected error.
++
++**/
++EFI_STATUS
++Dhcp6SeekStsOption (
++ IN DHCP6_INSTANCE *Instance,
++ IN EFI_DHCP6_PACKET *Packet,
++ OUT UINT8 **Option
++ );
++
++#endif // DHCP6_IO_GOOGLE_TEST_H
+--
+2.40.0
+
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2023-45229-0003.patch b/meta/recipes-core/ovmf/ovmf/CVE-2023-45229-0003.patch
new file mode 100644
index 0000000000..bf4e8eda1f
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/CVE-2023-45229-0003.patch
@@ -0,0 +1,244 @@
+From 1c440a5eceedc64e892877eeac0f1a4938f5abbb Mon Sep 17 00:00:00 2001
+From: Doug Flick <dougflick@microsoft.com>
+Date: Tue, 13 Feb 2024 10:46:00 -0800
+Subject: [PATCH] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Related
+ Patch
+
+REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4673
+REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4534
+
+This was not part of the Quarkslab bugs however the same pattern
+as CVE-2023-45229 exists in Dhcp6UpdateIaInfo.
+
+This patch replaces the code in question with the safe function
+created to patch CVE-2023-45229
+
+>
+> if (EFI_ERROR (
+> Dhcp6SeekInnerOptionSafe (
+> Instance->Config->IaDescriptor.Type,
+> Option,
+> OptionLen,
+> &IaInnerOpt,
+> &IaInnerLen
+> )
+> ))
+> {
+> return EFI_DEVICE_ERROR;
+> }
+>
+
+Additionally corrects incorrect usage of macro to read the status
+
+> - StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)DHCP6_OFFSET_OF_OPT_LEN
+ (Option)));
+> + StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)
+DHCP6_OFFSET_OF_STATUS_CODE (Option));
+
+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>
+Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
+
+CVE: CVE-2023-45229
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/1c440a5eceedc64e892877eeac0f1a4938f5abbb]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ NetworkPkg/Dhcp6Dxe/Dhcp6Io.c | 70 ++++++++++++++++++++++++++---------
+ NetworkPkg/Dhcp6Dxe/Dhcp6Io.h | 22 +++++++++++
+ 2 files changed, 75 insertions(+), 17 deletions(-)
+
+diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
+index 3b8feb4a20..a9bffae353 100644
+--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
+@@ -528,13 +528,23 @@ Dhcp6UpdateIaInfo (
+ {
+ EFI_STATUS Status;
+ UINT8 *Option;
++ UINT32 OptionLen;
+ UINT8 *IaInnerOpt;
+ UINT16 IaInnerLen;
+ UINT16 StsCode;
+ UINT32 T1;
+ UINT32 T2;
+
++ T1 = 0;
++ T2 = 0;
++
+ ASSERT (Instance->Config != NULL);
++
++ // OptionLen is the length of the Options excluding the DHCP header.
++ // Length of the EFI_DHCP6_PACKET from the first byte of the Header field to the last
++ // byte of the Option[] field.
++ OptionLen = Packet->Length - sizeof (Packet->Dhcp6.Header);
++
+ //
+ // If the reply was received in response to a solicit with rapid commit option,
+ // request, renew or rebind message, the client updates the information it has
+@@ -549,13 +559,29 @@ Dhcp6UpdateIaInfo (
+ //
+ Option = Dhcp6SeekIaOption (
+ Packet->Dhcp6.Option,
+- Packet->Length - sizeof (EFI_DHCP6_HEADER),
++ OptionLen,
+ &Instance->Config->IaDescriptor
+ );
+ if (Option == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
++ //
++ // Calculate the distance from Packet->Dhcp6.Option to the IA option.
++ //
++ // Packet->Size and Packet->Length are both UINT32 type, and Packet->Size is
++ // the size of the whole packet, including the DHCP header, and Packet->Length
++ // is the length of the DHCP message body, excluding the DHCP header.
++ //
++ // (*Option - Packet->Dhcp6.Option) is the number of bytes from the start of
++ // DHCP6 option area to the start of the IA option.
++ //
++ // Dhcp6SeekInnerOptionSafe() is searching starting from the start of the
++ // IA option to the end of the DHCP6 option area, thus subtract the space
++ // up until this option
++ //
++ OptionLen = OptionLen - (UINT32)(Option - Packet->Dhcp6.Option);
++
+ //
+ // The format of the IA_NA option is:
+ //
+@@ -591,32 +617,32 @@ Dhcp6UpdateIaInfo (
+ //
+
+ //
+- // sizeof (option-code + option-len + IaId) = 8
+- // sizeof (option-code + option-len + IaId + T1) = 12
+- // sizeof (option-code + option-len + IaId + T1 + T2) = 16
+- //
+- // The inner options still start with 2 bytes option-code and 2 bytes option-len.
++ // Seek the inner option
+ //
++ if (EFI_ERROR (
++ Dhcp6SeekInnerOptionSafe (
++ Instance->Config->IaDescriptor.Type,
++ Option,
++ OptionLen,
++ &IaInnerOpt,
++ &IaInnerLen
++ )
++ ))
++ {
++ return EFI_DEVICE_ERROR;
++ }
++
+ if (Instance->Config->IaDescriptor.Type == Dhcp6OptIana) {
+ T1 = NTOHL (ReadUnaligned32 ((UINT32 *)(DHCP6_OFFSET_OF_IA_NA_T1 (Option))));
+ T2 = NTOHL (ReadUnaligned32 ((UINT32 *)(DHCP6_OFFSET_OF_IA_NA_T2 (Option))));
+ //
+ // Refer to RFC3155 Chapter 22.4. If a client receives an IA_NA with T1 greater than T2,
+ // and both T1 and T2 are greater than 0, the client discards the IA_NA option and processes
+- // the remainder of the message as though the server had not included the invalid IA_NA option.
++ // the remainder of the message as though the server had not included the invalid IA_NA option.
+ //
+ if ((T1 > T2) && (T2 > 0)) {
+ return EFI_DEVICE_ERROR;
+ }
+-
+- IaInnerOpt = DHCP6_OFFSET_OF_IA_NA_INNER_OPT (Option);
+- IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN (Option)))) - DHCP6_SIZE_OF_COMBINED_IAID_T1_T2);
+- } else {
+- T1 = 0;
+- T2 = 0;
+-
+- IaInnerOpt = DHCP6_OFFSET_OF_IA_TA_INNER_OPT (Option);
+- IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN (Option)))) - DHCP6_SIZE_OF_IAID);
+ }
+
+ //
+@@ -642,7 +668,7 @@ Dhcp6UpdateIaInfo (
+ Option = Dhcp6SeekOption (IaInnerOpt, IaInnerLen, Dhcp6OptStatusCode);
+
+ if (Option != NULL) {
+- StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN (Option))));
++ StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_STATUS_CODE (Option))));
+ if (StsCode != Dhcp6StsSuccess) {
+ return EFI_DEVICE_ERROR;
+ }
+@@ -703,15 +729,21 @@ Dhcp6SeekInnerOptionSafe (
+ }
+
+ if (IaType == Dhcp6OptIana) {
++ //
+ // Verify we have a fully formed IA_NA
++ //
+ if (OptionLen < DHCP6_MIN_SIZE_OF_IA_NA) {
+ return EFI_DEVICE_ERROR;
+ }
+
++ //
++ // Get the IA Inner Option and Length
+ //
+ IaInnerOptTmp = DHCP6_OFFSET_OF_IA_NA_INNER_OPT (Option);
+
++ //
+ // Verify the IaInnerLen is valid.
++ //
+ IaInnerLenTmp = (UINT16)NTOHS (ReadUnaligned16 ((UINT16 *)DHCP6_OFFSET_OF_OPT_LEN (Option)));
+ if (IaInnerLenTmp < DHCP6_SIZE_OF_COMBINED_IAID_T1_T2) {
+ return EFI_DEVICE_ERROR;
+@@ -719,14 +751,18 @@ Dhcp6SeekInnerOptionSafe (
+
+ IaInnerLenTmp -= DHCP6_SIZE_OF_COMBINED_IAID_T1_T2;
+ } else if (IaType == Dhcp6OptIata) {
++ //
+ // Verify the OptionLen is valid.
++ //
+ if (OptionLen < DHCP6_MIN_SIZE_OF_IA_TA) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ IaInnerOptTmp = DHCP6_OFFSET_OF_IA_TA_INNER_OPT (Option);
+
++ //
+ // Verify the IaInnerLen is valid.
++ //
+ IaInnerLenTmp = (UINT16)NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN (Option))));
+ if (IaInnerLenTmp < DHCP6_SIZE_OF_IAID) {
+ return EFI_DEVICE_ERROR;
+diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.h b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.h
+index 051a652f2b..ab0e1ac27f 100644
+--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.h
++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.h
+@@ -217,4 +217,26 @@ Dhcp6OnTimerTick (
+ IN VOID *Context
+ );
+
++/**
++ Seeks the Inner Options from a DHCP6 Option
++
++ @param[in] IaType The type of the IA option.
++ @param[in] Option The pointer to the DHCP6 Option.
++ @param[in] OptionLen The length of the DHCP6 Option.
++ @param[out] IaInnerOpt The pointer to the IA inner option.
++ @param[out] IaInnerLen The length of the IA inner option.
++
++ @retval EFI_SUCCESS Seek the inner option successfully.
++ @retval EFI_DEVICE_ERROR The OptionLen is invalid. On Error,
++ the pointers are not modified
++**/
++EFI_STATUS
++Dhcp6SeekInnerOptionSafe (
++ IN UINT16 IaType,
++ IN UINT8 *Option,
++ IN UINT32 OptionLen,
++ OUT UINT8 **IaInnerOpt,
++ OUT UINT16 *IaInnerLen
++ );
++
+ #endif
+--
+2.40.0
+
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2023-45229-0004.patch b/meta/recipes-core/ovmf/ovmf/CVE-2023-45229-0004.patch
new file mode 100644
index 0000000000..85d204972d
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/CVE-2023-45229-0004.patch
@@ -0,0 +1,157 @@
+From 1d0b95f6457d225c5108302a9da74b4ed7aa5a38 Mon Sep 17 00:00:00 2001
+From: "Doug Flick via groups.io" <dougflick=microsoft.com@groups.io>
+Date: Fri, 26 Jan 2024 05:54:57 +0800
+Subject: [PATCH] NetworkPkg: : Adds a SecurityFix.yaml file
+
+This creates / adds a security file that tracks the security fixes
+found in this package and can be used to find the fixes that were
+applied.
+
+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_45229
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/1d0b95f6457d225c5108302a9da74b4ed7aa5a38]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ NetworkPkg/SecurityFixes.yaml | 123 ++++++++++++++++++++++++++++++++++
+ 1 file changed, 123 insertions(+)
+ create mode 100644 NetworkPkg/SecurityFixes.yaml
+
+diff --git a/NetworkPkg/SecurityFixes.yaml b/NetworkPkg/SecurityFixes.yaml
+new file mode 100644
+index 0000000000..7e900483fe
+--- /dev/null
++++ b/NetworkPkg/SecurityFixes.yaml
+@@ -0,0 +1,123 @@
++## @file
++# Security Fixes for SecurityPkg
++#
++# Copyright (c) Microsoft Corporation
++# SPDX-License-Identifier: BSD-2-Clause-Patent
++##
++CVE_2023_45229:
++ commit_titles:
++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Patch"
++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Unit Tests"
++ cve: CVE-2023-45229
++ date_reported: 2023-08-28 13:56 UTC
++ description: "Bug 01 - edk2/NetworkPkg: Out-of-bounds read when processing IA_NA/IA_TA options in a DHCPv6 Advertise message"
++ note:
++ files_impacted:
++ - NetworkPkg\Dhcp6Dxe\Dhcp6Io.c
++ - NetworkPkg\Dhcp6Dxe\Dhcp6Impl.h
++ links:
++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4534
++ - https://nvd.nist.gov/vuln/detail/CVE-2023-45229
++ - http://www.openwall.com/lists/oss-security/2024/01/16/2
++ - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html
++ - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html
++CVE_2023_45230:
++ commit_titles:
++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch"
++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Unit Tests"
++ cve: CVE-2023-45230
++ date_reported: 2023-08-28 13:56 UTC
++ description: "Bug 02 - edk2/NetworkPkg: Buffer overflow in the DHCPv6 client via a long Server ID option"
++ note:
++ files_impacted:
++ - NetworkPkg\Dhcp6Dxe\Dhcp6Io.c
++ - NetworkPkg\Dhcp6Dxe\Dhcp6Impl.h
++ links:
++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4535
++ - https://nvd.nist.gov/vuln/detail/CVE-2023-45230
++ - http://www.openwall.com/lists/oss-security/2024/01/16/2
++ - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html
++ - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html
++CVE_2023_45231:
++ commit_titles:
++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45231 Patch"
++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45231 Unit Tests"
++ cve: CVE-2023-45231
++ date_reported: 2023-08-28 13:56 UTC
++ description: "Bug 03 - edk2/NetworkPkg: Out-of-bounds read when handling a ND Redirect message with truncated options"
++ note:
++ files_impacted:
++ - NetworkPkg/Ip6Dxe/Ip6Option.c
++ links:
++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4536
++ - https://nvd.nist.gov/vuln/detail/CVE-2023-45231
++ - http://www.openwall.com/lists/oss-security/2024/01/16/2
++ - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html
++ - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html
++CVE_2023_45232:
++ commit_titles:
++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45232 Patch"
++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45232 Unit Tests"
++ cve: CVE-2023-45232
++ date_reported: 2023-08-28 13:56 UTC
++ description: "Bug 04 - edk2/NetworkPkg: Infinite loop when parsing unknown options in the Destination Options header"
++ note:
++ files_impacted:
++ - NetworkPkg/Ip6Dxe/Ip6Option.c
++ - NetworkPkg/Ip6Dxe/Ip6Option.h
++ links:
++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4537
++ - https://nvd.nist.gov/vuln/detail/CVE-2023-45232
++ - http://www.openwall.com/lists/oss-security/2024/01/16/2
++ - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html
++ - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html
++CVE_2023_45233:
++ commit_titles:
++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45232 Patch"
++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45232 Unit Tests"
++ cve: CVE-2023-45233
++ date_reported: 2023-08-28 13:56 UTC
++ description: "Bug 05 - edk2/NetworkPkg: Infinite loop when parsing a PadN option in the Destination Options header "
++ note: This was fixed along with CVE-2023-45233
++ files_impacted:
++ - NetworkPkg/Ip6Dxe/Ip6Option.c
++ - NetworkPkg/Ip6Dxe/Ip6Option.h
++ links:
++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4538
++ - https://nvd.nist.gov/vuln/detail/CVE-2023-45233
++ - http://www.openwall.com/lists/oss-security/2024/01/16/2
++ - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html
++ - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html
++CVE_2023_45234:
++ commit_titles:
++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45234 Patch"
++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45234 Unit Tests"
++ cve: CVE-2023-45234
++ date_reported: 2023-08-28 13:56 UTC
++ description: "Bug 06 - edk2/NetworkPkg: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message"
++ note:
++ files_impacted:
++ - NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
++ links:
++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4539
++ - https://nvd.nist.gov/vuln/detail/CVE-2023-45234
++ - http://www.openwall.com/lists/oss-security/2024/01/16/2
++ - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html
++ - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html
++CVE_2023_45235:
++ commit_titles:
++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45235 Patch"
++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45235 Unit Tests"
++ cve: CVE-2023-45235
++ date_reported: 2023-08-28 13:56 UTC
++ description: "Bug 07 - edk2/NetworkPkg: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message"
++ note:
++ files_impacted:
++ - NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
++ - NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h
++ links:
++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4540
++ - https://nvd.nist.gov/vuln/detail/CVE-2023-45235
++ - http://www.openwall.com/lists/oss-security/2024/01/16/2
++ - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html
++ - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html
+--
+2.40.0
+
diff --git a/meta/recipes-core/ovmf/ovmf_git.bb b/meta/recipes-core/ovmf/ovmf_git.bb
index ceebb53438..6ac72772d1 100644
--- a/meta/recipes-core/ovmf/ovmf_git.bb
+++ b/meta/recipes-core/ovmf/ovmf_git.bb
@@ -43,6 +43,10 @@ SRC_URI = "gitsm://github.com/tianocore/edk2.git;branch=master;protocol=https \
file://CVE-2023-45234-0002.patch \
file://CVE-2023-45235-0001.patch \
file://CVE-2023-45235-0002.patch \
+ file://CVE-2023-45229-0001.patch \
+ file://CVE-2023-45229-0002.patch \
+ file://CVE-2023-45229-0003.patch \
+ file://CVE-2023-45229-0004.patch \
"
PV = "edk2-stable202202"
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 09/38] ovmf: Fix CVE-2023-45237
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (7 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 08/38] ovmf: Fix CVE-2023-45229 Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 10/38] ovmf: Fix CVE-2023-45236 Steve Sakoman
` (28 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Soumya Sambu <soumya.sambu@windriver.com>
EDK2's Network Package is susceptible to a predictable TCP Initial Sequence
Number. This vulnerability can be exploited by an attacker to gain
unauthorized access and potentially lead to a loss of Confidentiality.
References:
https://nvd.nist.gov/vuln/detail/CVE-2023-45237
Upstream-patches:
https://github.com/tianocore/edk2/commit/cf07238e5fa4f8b1138ac1c9e80530b4d4e59f1c
https://github.com/tianocore/edk2/commit/4c4ceb2ceb80c42fd5545b2a4bd80321f07f4345
Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
---
.../ovmf/ovmf/CVE-2023-45237-0001.patch | 78 +
.../ovmf/ovmf/CVE-2023-45237-0002.patch | 1288 +++++++++++++++++
meta/recipes-core/ovmf/ovmf_git.bb | 2 +
3 files changed, 1368 insertions(+)
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45237-0001.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45237-0002.patch
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2023-45237-0001.patch b/meta/recipes-core/ovmf/ovmf/CVE-2023-45237-0001.patch
new file mode 100644
index 0000000000..d1dcb8dc44
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/CVE-2023-45237-0001.patch
@@ -0,0 +1,78 @@
+From cf07238e5fa4f8b1138ac1c9e80530b4d4e59f1c Mon Sep 17 00:00:00 2001
+From: Pierre Gondois <pierre.gondois@arm.com>
+Date: Fri, 11 Aug 2023 16:33:06 +0200
+Subject: [PATCH] MdePkg/Rng: Add GUID to describe Arm Rndr Rng algorithms
+
+BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4441
+
+The EFI_RNG_PROTOCOL can rely on the RngLib. The RngLib has multiple
+implementations, some of them are unsafe (e.g. BaseRngLibTimerLib).
+To allow the RngDxe to detect when such implementation is used,
+a GetRngGuid() function is added in a following patch.
+
+Prepare GetRngGuid() return values and add a gEfiRngAlgorithmArmRndr
+to describe a Rng algorithm accessed through Arm's RNDR instruction.
+[1] states that the implementation of this algorithm should be
+compliant to NIST SP900-80. The compliance is not guaranteed.
+
+[1] Arm Architecture Reference Manual Armv8, for A-profile architecture
+sK12.1 'Properties of the generated random number'
+
+Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
+Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>
+Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
+Acked-by: Ard Biesheuvel <ardb@kernel.org>
+Tested-by: Kun Qin <kun.qin@microsoft.com>
+
+CVE: CVE-2023-45237
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/cf07238e5fa4f8b1138ac1c9e80530b4d4e59f1c]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ MdePkg/Include/Protocol/Rng.h | 10 ++++++++++
+ MdePkg/MdePkg.dec | 1 +
+ 2 files changed, 11 insertions(+)
+
+diff --git a/MdePkg/Include/Protocol/Rng.h b/MdePkg/Include/Protocol/Rng.h
+index baf425587b..38bde53240 100644
+--- a/MdePkg/Include/Protocol/Rng.h
++++ b/MdePkg/Include/Protocol/Rng.h
+@@ -67,6 +67,15 @@ typedef EFI_GUID EFI_RNG_ALGORITHM;
+ { \
+ 0xe43176d7, 0xb6e8, 0x4827, {0xb7, 0x84, 0x7f, 0xfd, 0xc4, 0xb6, 0x85, 0x61 } \
+ }
++///
++/// The Arm Architecture states the RNDR that the DRBG algorithm should be compliant
++/// with NIST SP800-90A, while not mandating a particular algorithm, so as to be
++/// inclusive of different geographies.
++///
++#define EFI_RNG_ALGORITHM_ARM_RNDR \
++ { \
++ 0x43d2fde3, 0x9d4e, 0x4d79, {0x02, 0x96, 0xa8, 0x9b, 0xca, 0x78, 0x08, 0x41} \
++ }
+
+ /**
+ Returns information about the random number generation implementation.
+@@ -146,5 +155,6 @@ extern EFI_GUID gEfiRngAlgorithmSp80090Ctr256Guid;
+ extern EFI_GUID gEfiRngAlgorithmX9313DesGuid;
+ extern EFI_GUID gEfiRngAlgorithmX931AesGuid;
+ extern EFI_GUID gEfiRngAlgorithmRaw;
++extern EFI_GUID gEfiRngAlgorithmArmRndr;
+
+ #endif
+diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec
+index 59b405928b..a449dbc556 100644
+--- a/MdePkg/MdePkg.dec
++++ b/MdePkg/MdePkg.dec
+@@ -594,6 +594,7 @@
+ gEfiRngAlgorithmX9313DesGuid = { 0x63c4785a, 0xca34, 0x4012, {0xa3, 0xc8, 0x0b, 0x6a, 0x32, 0x4f, 0x55, 0x46 }}
+ gEfiRngAlgorithmX931AesGuid = { 0xacd03321, 0x777e, 0x4d3d, {0xb1, 0xc8, 0x20, 0xcf, 0xd8, 0x88, 0x20, 0xc9 }}
+ gEfiRngAlgorithmRaw = { 0xe43176d7, 0xb6e8, 0x4827, {0xb7, 0x84, 0x7f, 0xfd, 0xc4, 0xb6, 0x85, 0x61 }}
++ gEfiRngAlgorithmArmRndr = { 0x43d2fde3, 0x9d4e, 0x4d79, {0x02, 0x96, 0xa8, 0x9b, 0xca, 0x78, 0x08, 0x41 }}
+
+ ## Include/Protocol/AdapterInformation.h
+ gEfiAdapterInfoMediaStateGuid = { 0xD7C74207, 0xA831, 0x4A26, {0xB1, 0xF5, 0xD1, 0x93, 0x06, 0x5C, 0xE8, 0xB6 }}
+--
+2.40.0
+
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2023-45237-0002.patch b/meta/recipes-core/ovmf/ovmf/CVE-2023-45237-0002.patch
new file mode 100644
index 0000000000..722a6cd530
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/CVE-2023-45237-0002.patch
@@ -0,0 +1,1288 @@
+From 4c4ceb2ceb80c42fd5545b2a4bd80321f07f4345 Mon Sep 17 00:00:00 2001
+From: Doug Flick <dougflick@microsoft.com>
+Date: Wed, 8 May 2024 22:56:28 -0700
+Subject: [PATCH] NetworkPkg: SECURITY PATCH CVE-2023-45237
+
+REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4542
+
+Bug Overview:
+PixieFail Bug #9
+CVE-2023-45237
+CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
+CWE-338 Use of Cryptographically Weak Pseudo-Random Number Generator (PRNG)
+
+Use of a Weak PseudoRandom Number Generator
+
+Change Overview:
+
+Updates all Instances of NET_RANDOM (NetRandomInitSeed ()) to either
+
+>
+> EFI_STATUS
+> EFIAPI
+> PseudoRandomU32 (
+> OUT UINT32 *Output
+> );
+>
+
+or (depending on the use case)
+
+>
+> EFI_STATUS
+> EFIAPI
+> PseudoRandom (
+> OUT VOID *Output,
+> IN UINTN OutputLength
+> );
+>
+
+This is because the use of
+
+Example:
+
+The following code snippet PseudoRandomU32 () function is used:
+
+>
+> UINT32 Random;
+>
+> Status = PseudoRandomU32 (&Random);
+> if (EFI_ERROR (Status)) {
+> DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n",
+__func__, Status));
+> return Status;
+> }
+>
+
+This also introduces a new PCD to enable/disable the use of the
+secure implementation of algorithms for PseudoRandom () and
+instead depend on the default implementation. This may be required for
+some platforms where the UEFI Spec defined algorithms are not available.
+
+>
+> PcdEnforceSecureRngAlgorithms
+>
+
+If the platform does not have any one of the UEFI defined
+secure RNG algorithms then the driver will assert.
+
+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-45237
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/4c4ceb2ceb80c42fd5545b2a4bd80321f07f4345]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ NetworkPkg/Dhcp4Dxe/Dhcp4Driver.c | 10 +-
+ NetworkPkg/Dhcp6Dxe/Dhcp6Driver.c | 11 +-
+ NetworkPkg/DnsDxe/DnsDhcp.c | 10 +-
+ NetworkPkg/DnsDxe/DnsImpl.c | 11 +-
+ NetworkPkg/HttpBootDxe/HttpBootDhcp6.c | 10 +-
+ NetworkPkg/IScsiDxe/IScsiCHAP.c | 19 ++-
+ NetworkPkg/IScsiDxe/IScsiMisc.c | 14 +--
+ NetworkPkg/IScsiDxe/IScsiMisc.h | 6 +-
+ NetworkPkg/Include/Library/NetLib.h | 40 +++++--
+ NetworkPkg/Ip4Dxe/Ip4Driver.c | 10 +-
+ NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c | 9 +-
+ NetworkPkg/Ip6Dxe/Ip6Driver.c | 17 ++-
+ NetworkPkg/Ip6Dxe/Ip6If.c | 12 +-
+ NetworkPkg/Ip6Dxe/Ip6Mld.c | 12 +-
+ NetworkPkg/Ip6Dxe/Ip6Nd.c | 33 +++++-
+ NetworkPkg/Ip6Dxe/Ip6Nd.h | 8 +-
+ NetworkPkg/Library/DxeNetLib/DxeNetLib.c | 130 ++++++++++++++++++---
+ NetworkPkg/Library/DxeNetLib/DxeNetLib.inf | 14 ++-
+ NetworkPkg/NetworkPkg.dec | 7 ++
+ NetworkPkg/SecurityFixes.yaml | 39 +++++++
+ NetworkPkg/TcpDxe/TcpDriver.c | 15 ++-
+ NetworkPkg/TcpDxe/TcpDxe.inf | 3 +
+ NetworkPkg/Udp4Dxe/Udp4Driver.c | 10 +-
+ NetworkPkg/Udp6Dxe/Udp6Driver.c | 11 +-
+ NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c | 9 +-
+ NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c | 11 +-
+ NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c | 12 +-
+ 27 files changed, 410 insertions(+), 83 deletions(-)
+
+diff --git a/NetworkPkg/Dhcp4Dxe/Dhcp4Driver.c b/NetworkPkg/Dhcp4Dxe/Dhcp4Driver.c
+index 8c37e93be3..892caee368 100644
+--- a/NetworkPkg/Dhcp4Dxe/Dhcp4Driver.c
++++ b/NetworkPkg/Dhcp4Dxe/Dhcp4Driver.c
+@@ -1,6 +1,7 @@
+ /** @file
+
+ Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
++Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+@@ -189,6 +190,13 @@ Dhcp4CreateService (
+ {
+ DHCP_SERVICE *DhcpSb;
+ EFI_STATUS Status;
++ UINT32 Random;
++
++ Status = PseudoRandomU32 (&Random);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++ return Status;
++ }
+
+ *Service = NULL;
+ DhcpSb = AllocateZeroPool (sizeof (DHCP_SERVICE));
+@@ -203,7 +211,7 @@ Dhcp4CreateService (
+ DhcpSb->Image = ImageHandle;
+ InitializeListHead (&DhcpSb->Children);
+ DhcpSb->DhcpState = Dhcp4Stopped;
+- DhcpSb->Xid = NET_RANDOM (NetRandomInitSeed ());
++ DhcpSb->Xid = Random;
+ CopyMem (
+ &DhcpSb->ServiceBinding,
+ &mDhcp4ServiceBindingTemplate,
+diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Driver.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Driver.c
+index b591a4605b..e7f2787a98 100644
+--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Driver.c
++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Driver.c
+@@ -3,7 +3,7 @@
+ implementation for Dhcp6 Driver.
+
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+-
++ Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+@@ -123,6 +123,13 @@ Dhcp6CreateService (
+ {
+ DHCP6_SERVICE *Dhcp6Srv;
+ EFI_STATUS Status;
++ UINT32 Random;
++
++ Status = PseudoRandomU32 (&Random);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++ return Status;
++ }
+
+ *Service = NULL;
+ Dhcp6Srv = AllocateZeroPool (sizeof (DHCP6_SERVICE));
+@@ -147,7 +154,7 @@ Dhcp6CreateService (
+ Dhcp6Srv->Signature = DHCP6_SERVICE_SIGNATURE;
+ Dhcp6Srv->Controller = Controller;
+ Dhcp6Srv->Image = ImageHandle;
+- Dhcp6Srv->Xid = (0xffffff & NET_RANDOM (NetRandomInitSeed ()));
++ Dhcp6Srv->Xid = (0xffffff & Random);
+
+ CopyMem (
+ &Dhcp6Srv->ServiceBinding,
+diff --git a/NetworkPkg/DnsDxe/DnsDhcp.c b/NetworkPkg/DnsDxe/DnsDhcp.c
+index 933565a32d..9eb3c1d2d8 100644
+--- a/NetworkPkg/DnsDxe/DnsDhcp.c
++++ b/NetworkPkg/DnsDxe/DnsDhcp.c
+@@ -2,6 +2,7 @@
+ Functions implementation related with DHCPv4/v6 for DNS driver.
+
+ Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
++Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+@@ -277,6 +278,7 @@ GetDns4ServerFromDhcp4 (
+ EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN Token;
+ BOOLEAN IsDone;
+ UINTN Index;
++ UINT32 Random;
+
+ Image = Instance->Service->ImageHandle;
+ Controller = Instance->Service->ControllerHandle;
+@@ -292,6 +294,12 @@ GetDns4ServerFromDhcp4 (
+ Data = NULL;
+ InterfaceInfo = NULL;
+
++ Status = PseudoRandomU32 (&Random);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++ return Status;
++ }
++
+ ZeroMem ((UINT8 *)ParaList, sizeof (ParaList));
+
+ ZeroMem (&MnpConfigData, sizeof (EFI_MANAGED_NETWORK_CONFIG_DATA));
+@@ -467,7 +475,7 @@ GetDns4ServerFromDhcp4 (
+
+ Status = Dhcp4->Build (Dhcp4, &SeedPacket, 0, NULL, 2, ParaList, &Token.Packet);
+
+- Token.Packet->Dhcp4.Header.Xid = HTONL (NET_RANDOM (NetRandomInitSeed ()));
++ Token.Packet->Dhcp4.Header.Xid = Random;
+
+ Token.Packet->Dhcp4.Header.Reserved = HTONS ((UINT16)0x8000);
+
+diff --git a/NetworkPkg/DnsDxe/DnsImpl.c b/NetworkPkg/DnsDxe/DnsImpl.c
+index d311812800..c2629bb8df 100644
+--- a/NetworkPkg/DnsDxe/DnsImpl.c
++++ b/NetworkPkg/DnsDxe/DnsImpl.c
+@@ -2,6 +2,7 @@
+ DnsDxe support functions implementation.
+
+ Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
++Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+@@ -1963,6 +1964,14 @@ ConstructDNSQuery (
+ NET_FRAGMENT Frag;
+ DNS_HEADER *DnsHeader;
+ DNS_QUERY_SECTION *DnsQuery;
++ EFI_STATUS Status;
++ UINT32 Random;
++
++ Status = PseudoRandomU32 (&Random);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++ return Status;
++ }
+
+ //
+ // Messages carried by UDP are restricted to 512 bytes (not counting the IP
+@@ -1977,7 +1986,7 @@ ConstructDNSQuery (
+ // Fill header
+ //
+ DnsHeader = (DNS_HEADER *)Frag.Bulk;
+- DnsHeader->Identification = (UINT16)NET_RANDOM (NetRandomInitSeed ());
++ DnsHeader->Identification = (UINT16)Random;
+ DnsHeader->Flags.Uint16 = 0x0000;
+ DnsHeader->Flags.Bits.RD = 1;
+ DnsHeader->Flags.Bits.OpCode = DNS_FLAGS_OPCODE_STANDARD;
+diff --git a/NetworkPkg/HttpBootDxe/HttpBootDhcp6.c b/NetworkPkg/HttpBootDxe/HttpBootDhcp6.c
+index b22cef4ff5..f964515b0f 100644
+--- a/NetworkPkg/HttpBootDxe/HttpBootDhcp6.c
++++ b/NetworkPkg/HttpBootDxe/HttpBootDhcp6.c
+@@ -2,6 +2,7 @@
+ Functions implementation related with DHCPv6 for HTTP boot driver.
+
+ Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
++Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+@@ -951,6 +952,7 @@ HttpBootDhcp6Sarr (
+ UINT32 OptCount;
+ UINT8 Buffer[HTTP_BOOT_DHCP6_OPTION_MAX_SIZE];
+ EFI_STATUS Status;
++ UINT32 Random;
+
+ Dhcp6 = Private->Dhcp6;
+ ASSERT (Dhcp6 != NULL);
+@@ -961,6 +963,12 @@ HttpBootDhcp6Sarr (
+ OptCount = HttpBootBuildDhcp6Options (Private, OptList, Buffer);
+ ASSERT (OptCount > 0);
+
++ Status = PseudoRandomU32 (&Random);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++ return Status;
++ }
++
+ Retransmit = AllocateZeroPool (sizeof (EFI_DHCP6_RETRANSMISSION));
+ if (Retransmit == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+@@ -976,7 +984,7 @@ HttpBootDhcp6Sarr (
+ Config.IaInfoEvent = NULL;
+ Config.RapidCommit = FALSE;
+ Config.ReconfigureAccept = FALSE;
+- Config.IaDescriptor.IaId = NET_RANDOM (NetRandomInitSeed ());
++ Config.IaDescriptor.IaId = Random;
+ Config.IaDescriptor.Type = EFI_DHCP6_IA_TYPE_NA;
+ Config.SolicitRetransmission = Retransmit;
+ Retransmit->Irt = 4;
+diff --git a/NetworkPkg/IScsiDxe/IScsiCHAP.c b/NetworkPkg/IScsiDxe/IScsiCHAP.c
+index b507f11cd4..bebb1ac29b 100644
+--- a/NetworkPkg/IScsiDxe/IScsiCHAP.c
++++ b/NetworkPkg/IScsiDxe/IScsiCHAP.c
+@@ -3,6 +3,7 @@
+ Configuration.
+
+ Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
++Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+@@ -576,16 +577,24 @@ IScsiCHAPToSendReq (
+ //
+ // CHAP_I=<I>
+ //
+- IScsiGenRandom ((UINT8 *)&AuthData->OutIdentifier, 1);
++ Status = IScsiGenRandom ((UINT8 *)&AuthData->OutIdentifier, 1);
++ if (EFI_ERROR (Status)) {
++ break;
++ }
++
+ AsciiSPrint (ValueStr, sizeof (ValueStr), "%d", AuthData->OutIdentifier);
+ IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_IDENTIFIER, ValueStr);
+ //
+ // CHAP_C=<C>
+ //
+- IScsiGenRandom (
+- (UINT8 *)AuthData->OutChallenge,
+- AuthData->Hash->DigestSize
+- );
++ Status = IScsiGenRandom (
++ (UINT8 *)AuthData->OutChallenge,
++ AuthData->Hash->DigestSize
++ );
++ if (EFI_ERROR (Status)) {
++ break;
++ }
++
+ BinToHexStatus = IScsiBinToHex (
+ (UINT8 *)AuthData->OutChallenge,
+ AuthData->Hash->DigestSize,
+diff --git a/NetworkPkg/IScsiDxe/IScsiMisc.c b/NetworkPkg/IScsiDxe/IScsiMisc.c
+index b3ea90158f..cd77f1a13e 100644
+--- a/NetworkPkg/IScsiDxe/IScsiMisc.c
++++ b/NetworkPkg/IScsiDxe/IScsiMisc.c
+@@ -2,6 +2,7 @@
+ Miscellaneous routines for iSCSI driver.
+
+ Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
++Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+@@ -474,20 +475,17 @@ IScsiNetNtoi (
+ @param[in, out] Rand The buffer to contain random numbers.
+ @param[in] RandLength The length of the Rand buffer.
+
++ @retval EFI_SUCCESS on success
++ @retval others on error
++
+ **/
+-VOID
++EFI_STATUS
+ IScsiGenRandom (
+ IN OUT UINT8 *Rand,
+ IN UINTN RandLength
+ )
+ {
+- UINT32 Random;
+-
+- while (RandLength > 0) {
+- Random = NET_RANDOM (NetRandomInitSeed ());
+- *Rand++ = (UINT8)(Random);
+- RandLength--;
+- }
++ return PseudoRandom (Rand, RandLength);
+ }
+
+ /**
+diff --git a/NetworkPkg/IScsiDxe/IScsiMisc.h b/NetworkPkg/IScsiDxe/IScsiMisc.h
+index a951eee70e..91b2cd2261 100644
+--- a/NetworkPkg/IScsiDxe/IScsiMisc.h
++++ b/NetworkPkg/IScsiDxe/IScsiMisc.h
+@@ -2,6 +2,7 @@
+ Miscellaneous definitions for iSCSI driver.
+
+ Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
++Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+@@ -202,8 +203,11 @@ IScsiNetNtoi (
+ @param[in, out] Rand The buffer to contain random numbers.
+ @param[in] RandLength The length of the Rand buffer.
+
++ @retval EFI_SUCCESS on success
++ @retval others on error
++
+ **/
+-VOID
++EFI_STATUS
+ IScsiGenRandom (
+ IN OUT UINT8 *Rand,
+ IN UINTN RandLength
+diff --git a/NetworkPkg/Include/Library/NetLib.h b/NetworkPkg/Include/Library/NetLib.h
+index 8c0e62b388..e8108b79db 100644
+--- a/NetworkPkg/Include/Library/NetLib.h
++++ b/NetworkPkg/Include/Library/NetLib.h
+@@ -3,6 +3,7 @@
+ It provides basic functions for the UEFI network stack.
+
+ Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
++Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+@@ -539,8 +540,6 @@ extern EFI_IPv4_ADDRESS mZeroIp4Addr;
+ #define TICKS_PER_MS 10000U
+ #define TICKS_PER_SECOND 10000000U
+
+-#define NET_RANDOM(Seed) ((UINT32) ((UINT32) (Seed) * 1103515245UL + 12345) % 4294967295UL)
+-
+ /**
+ Extract a UINT32 from a byte stream.
+
+@@ -580,19 +579,40 @@ NetPutUint32 (
+ );
+
+ /**
+- Initialize a random seed using current time and monotonic count.
++ Generate a Random output data given a length.
+
+- Get current time and monotonic count first. Then initialize a random seed
+- based on some basic mathematics operation on the hour, day, minute, second,
+- nanosecond and year of the current time and the monotonic count value.
++ @param[out] Output - The buffer to store the generated random data.
++ @param[in] OutputLength - The length of the output buffer.
+
+- @return The random seed initialized with current time.
++ @retval EFI_SUCCESS On Success
++ @retval EFI_INVALID_PARAMETER Pointer is null or size is zero
++ @retval EFI_NOT_FOUND RNG protocol not found
++ @retval Others Error from RngProtocol->GetRNG()
+
++ @return Status code
+ **/
+-UINT32
++EFI_STATUS
+ EFIAPI
+-NetRandomInitSeed (
+- VOID
++PseudoRandom (
++ OUT VOID *Output,
++ IN UINTN OutputLength
++ );
++
++/**
++ Generate a 32-bit pseudo-random number.
++
++ @param[out] Output - The buffer to store the generated random number.
++
++ @retval EFI_SUCCESS On Success
++ @retval EFI_NOT_FOUND RNG protocol not found
++ @retval Others Error from RngProtocol->GetRNG()
++
++ @return Status code
++**/
++EFI_STATUS
++EFIAPI
++PseudoRandomU32 (
++ OUT UINT32 *Output
+ );
+
+ #define NET_LIST_USER_STRUCT(Entry, Type, Field) \
+diff --git a/NetworkPkg/Ip4Dxe/Ip4Driver.c b/NetworkPkg/Ip4Dxe/Ip4Driver.c
+index ec483ff01f..683423f38d 100644
+--- a/NetworkPkg/Ip4Dxe/Ip4Driver.c
++++ b/NetworkPkg/Ip4Dxe/Ip4Driver.c
+@@ -2,6 +2,7 @@
+ The driver binding and service binding protocol for IP4 driver.
+
+ Copyright (c) 2005 - 2019, Intel Corporation. All rights reserved.<BR>
++Copyright (c) Microsoft Corporation
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+@@ -549,11 +550,18 @@ Ip4DriverBindingStart (
+ EFI_IP4_CONFIG2_PROTOCOL *Ip4Cfg2;
+ UINTN Index;
+ IP4_CONFIG2_DATA_ITEM *DataItem;
++ UINT32 Random;
+
+ IpSb = NULL;
+ Ip4Cfg2 = NULL;
+ DataItem = NULL;
+
++ Status = PseudoRandomU32 (&Random);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++ return Status;
++ }
++
+ //
+ // Test for the Ip4 service binding protocol
+ //
+@@ -653,7 +661,7 @@ Ip4DriverBindingStart (
+ //
+ // Initialize the IP4 ID
+ //
+- mIp4Id = (UINT16)NET_RANDOM (NetRandomInitSeed ());
++ mIp4Id = (UINT16)Random;
+
+ return Status;
+
+diff --git a/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c b/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c
+index 70e232ce6c..4c1354d26c 100644
+--- a/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c
++++ b/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c
+@@ -2276,6 +2276,13 @@ Ip6ConfigInitInstance (
+ UINTN Index;
+ UINT16 IfIndex;
+ IP6_CONFIG_DATA_ITEM *DataItem;
++ UINT32 Random;
++
++ Status = PseudoRandomU32 (&Random);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++ return Status;
++ }
+
+ IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);
+
+@@ -2381,7 +2388,7 @@ Ip6ConfigInitInstance (
+ // The NV variable is not set, so generate a random IAID, and write down the
+ // fresh new configuration as the NV variable now.
+ //
+- Instance->IaId = NET_RANDOM (NetRandomInitSeed ());
++ Instance->IaId = Random;
+
+ for (Index = 0; Index < IpSb->SnpMode.HwAddressSize; Index++) {
+ Instance->IaId |= (IpSb->SnpMode.CurrentAddress.Addr[Index] << ((Index << 3) & 31));
+diff --git a/NetworkPkg/Ip6Dxe/Ip6Driver.c b/NetworkPkg/Ip6Dxe/Ip6Driver.c
+index b483a7d136..cbe011dad4 100644
+--- a/NetworkPkg/Ip6Dxe/Ip6Driver.c
++++ b/NetworkPkg/Ip6Dxe/Ip6Driver.c
+@@ -3,7 +3,7 @@
+
+ Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+-
++ Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+@@ -316,7 +316,11 @@ Ip6CreateService (
+ IpSb->CurHopLimit = IP6_HOP_LIMIT;
+ IpSb->LinkMTU = IP6_MIN_LINK_MTU;
+ IpSb->BaseReachableTime = IP6_REACHABLE_TIME;
+- Ip6UpdateReachableTime (IpSb);
++ Status = Ip6UpdateReachableTime (IpSb);
++ if (EFI_ERROR (Status)) {
++ goto ON_ERROR;
++ }
++
+ //
+ // RFC4861 RETRANS_TIMER: 1,000 milliseconds
+ //
+@@ -516,11 +520,18 @@ Ip6DriverBindingStart (
+ EFI_STATUS Status;
+ EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg;
+ IP6_CONFIG_DATA_ITEM *DataItem;
++ UINT32 Random;
+
+ IpSb = NULL;
+ Ip6Cfg = NULL;
+ DataItem = NULL;
+
++ Status = PseudoRandomU32 (&Random);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++ return Status;
++ }
++
+ //
+ // Test for the Ip6 service binding protocol
+ //
+@@ -656,7 +667,7 @@ Ip6DriverBindingStart (
+ //
+ // Initialize the IP6 ID
+ //
+- mIp6Id = NET_RANDOM (NetRandomInitSeed ());
++ mIp6Id = Random;
+
+ return EFI_SUCCESS;
+
+diff --git a/NetworkPkg/Ip6Dxe/Ip6If.c b/NetworkPkg/Ip6Dxe/Ip6If.c
+index 4629c05f25..f3d11c4d21 100644
+--- a/NetworkPkg/Ip6Dxe/Ip6If.c
++++ b/NetworkPkg/Ip6Dxe/Ip6If.c
+@@ -2,7 +2,7 @@
+ Implement IP6 pseudo interface.
+
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+-
++ Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+@@ -89,6 +89,14 @@ Ip6SetAddress (
+ IP6_PREFIX_LIST_ENTRY *PrefixEntry;
+ UINT64 Delay;
+ IP6_DELAY_JOIN_LIST *DelayNode;
++ EFI_STATUS Status;
++ UINT32 Random;
++
++ Status = PseudoRandomU32 (&Random);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++ return Status;
++ }
+
+ NET_CHECK_SIGNATURE (Interface, IP6_INTERFACE_SIGNATURE);
+
+@@ -164,7 +172,7 @@ Ip6SetAddress (
+ // Thus queue the address to be processed in Duplicate Address Detection module
+ // after the delay time (in milliseconds).
+ //
+- Delay = (UINT64)NET_RANDOM (NetRandomInitSeed ());
++ Delay = (UINT64)Random;
+ Delay = MultU64x32 (Delay, IP6_ONE_SECOND_IN_MS);
+ Delay = RShiftU64 (Delay, 32);
+
+diff --git a/NetworkPkg/Ip6Dxe/Ip6Mld.c b/NetworkPkg/Ip6Dxe/Ip6Mld.c
+index e6b2b653e2..498a118543 100644
+--- a/NetworkPkg/Ip6Dxe/Ip6Mld.c
++++ b/NetworkPkg/Ip6Dxe/Ip6Mld.c
+@@ -696,7 +696,15 @@ Ip6UpdateDelayTimer (
+ IN OUT IP6_MLD_GROUP *Group
+ )
+ {
+- UINT32 Delay;
++ UINT32 Delay;
++ EFI_STATUS Status;
++ UINT32 Random;
++
++ Status = PseudoRandomU32 (&Random);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++ return Status;
++ }
+
+ //
+ // If the Query packet specifies a Maximum Response Delay of zero, perform timer
+@@ -715,7 +723,7 @@ Ip6UpdateDelayTimer (
+ // is less than the remaining value of the running timer.
+ //
+ if ((Group->DelayTimer == 0) || (Delay < Group->DelayTimer)) {
+- Group->DelayTimer = Delay / 4294967295UL * NET_RANDOM (NetRandomInitSeed ());
++ Group->DelayTimer = Delay / 4294967295UL * Random;
+ }
+
+ return EFI_SUCCESS;
+diff --git a/NetworkPkg/Ip6Dxe/Ip6Nd.c b/NetworkPkg/Ip6Dxe/Ip6Nd.c
+index c10c7017f8..72aa45c10f 100644
+--- a/NetworkPkg/Ip6Dxe/Ip6Nd.c
++++ b/NetworkPkg/Ip6Dxe/Ip6Nd.c
+@@ -2,7 +2,7 @@
+ Implementation of Neighbor Discovery support routines.
+
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+-
++ Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+@@ -16,17 +16,28 @@ EFI_MAC_ADDRESS mZeroMacAddress;
+
+ @param[in, out] IpSb Points to the IP6_SERVICE.
+
++ @retval EFI_SUCCESS ReachableTime Updated
++ @retval others Failed to update ReachableTime
+ **/
+-VOID
++EFI_STATUS
+ Ip6UpdateReachableTime (
+ IN OUT IP6_SERVICE *IpSb
+ )
+ {
+- UINT32 Random;
++ UINT32 Random;
++ EFI_STATUS Status;
+
+- Random = (NetRandomInitSeed () / 4294967295UL) * IP6_RANDOM_FACTOR_SCALE;
++ Status = PseudoRandomU32 (&Random);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++ return Status;
++ }
++
++ Random = (Random / 4294967295UL) * IP6_RANDOM_FACTOR_SCALE;
+ Random = Random + IP6_MIN_RANDOM_FACTOR_SCALED;
+ IpSb->ReachableTime = (IpSb->BaseReachableTime * Random) / IP6_RANDOM_FACTOR_SCALE;
++
++ return EFI_SUCCESS;
+ }
+
+ /**
+@@ -972,10 +983,17 @@ Ip6InitDADProcess (
+ IP6_SERVICE *IpSb;
+ EFI_STATUS Status;
+ UINT32 MaxDelayTick;
++ UINT32 Random;
+
+ NET_CHECK_SIGNATURE (IpIf, IP6_INTERFACE_SIGNATURE);
+ ASSERT (AddressInfo != NULL);
+
++ Status = PseudoRandomU32 (&Random);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++ return Status;
++ }
++
+ //
+ // Do nothing if we have already started DAD on the address.
+ //
+@@ -1014,7 +1032,7 @@ Ip6InitDADProcess (
+ Entry->Transmit = 0;
+ Entry->Receive = 0;
+ MaxDelayTick = IP6_MAX_RTR_SOLICITATION_DELAY / IP6_TIMER_INTERVAL_IN_MS;
+- Entry->RetransTick = (MaxDelayTick * ((NET_RANDOM (NetRandomInitSeed ()) % 5) + 1)) / 5;
++ Entry->RetransTick = (MaxDelayTick * ((Random % 5) + 1)) / 5;
+ Entry->AddressInfo = AddressInfo;
+ Entry->Callback = Callback;
+ Entry->Context = Context;
+@@ -2078,7 +2096,10 @@ Ip6ProcessRouterAdvertise (
+ // in BaseReachableTime and recompute a ReachableTime.
+ //
+ IpSb->BaseReachableTime = ReachableTime;
+- Ip6UpdateReachableTime (IpSb);
++ Status = Ip6UpdateReachableTime (IpSb);
++ if (EFI_ERROR (Status)) {
++ goto Exit;
++ }
+ }
+
+ if (RetransTimer != 0) {
+diff --git a/NetworkPkg/Ip6Dxe/Ip6Nd.h b/NetworkPkg/Ip6Dxe/Ip6Nd.h
+index bf64e9114e..5795e23c7d 100644
+--- a/NetworkPkg/Ip6Dxe/Ip6Nd.h
++++ b/NetworkPkg/Ip6Dxe/Ip6Nd.h
+@@ -2,7 +2,7 @@
+ Definition of Neighbor Discovery support routines.
+
+ Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
+-
++ Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+@@ -780,10 +780,10 @@ Ip6OnArpResolved (
+ /**
+ Update the ReachableTime in IP6 service binding instance data, in milliseconds.
+
+- @param[in, out] IpSb Points to the IP6_SERVICE.
+-
++ @retval EFI_SUCCESS ReachableTime Updated
++ @retval others Failed to update ReachableTime
+ **/
+-VOID
++EFI_STATUS
+ Ip6UpdateReachableTime (
+ IN OUT IP6_SERVICE *IpSb
+ );
+diff --git a/NetworkPkg/Library/DxeNetLib/DxeNetLib.c b/NetworkPkg/Library/DxeNetLib/DxeNetLib.c
+index fd4a9e15a8..01c13c08d2 100644
+--- a/NetworkPkg/Library/DxeNetLib/DxeNetLib.c
++++ b/NetworkPkg/Library/DxeNetLib/DxeNetLib.c
+@@ -3,6 +3,7 @@
+
+ Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
++Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+ **/
+
+@@ -31,6 +32,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
+ #include <Library/DevicePathLib.h>
+ #include <Library/PrintLib.h>
+ #include <Library/UefiLib.h>
++#include <Protocol/Rng.h>
+
+ #define NIC_ITEM_CONFIG_SIZE (sizeof (NIC_IP4_CONFIG_INFO) + sizeof (EFI_IP4_ROUTE_TABLE) * MAX_IP4_CONFIG_IN_VARIABLE)
+ #define DEFAULT_ZERO_START ((UINTN) ~0)
+@@ -127,6 +129,25 @@ GLOBAL_REMOVE_IF_UNREFERENCED VLAN_DEVICE_PATH mNetVlanDevicePathTemplate = {
+ 0
+ };
+
++//
++// These represent UEFI SPEC defined algorithms that should be supported by
++// the RNG protocol and are generally considered secure.
++//
++// The order of the algorithms in this array is important. This order is the order
++// in which the algorithms will be tried by the RNG protocol.
++// If your platform needs to use a specific algorithm for the random number generator,
++// then you should place that algorithm first in the array.
++//
++GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID *mSecureHashAlgorithms[] = {
++ &gEfiRngAlgorithmSp80090Ctr256Guid, // SP800-90A DRBG CTR using AES-256
++ &gEfiRngAlgorithmSp80090Hmac256Guid, // SP800-90A DRBG HMAC using SHA-256
++ &gEfiRngAlgorithmSp80090Hash256Guid, // SP800-90A DRBG Hash using SHA-256
++ &gEfiRngAlgorithmArmRndr, // unspecified SP800-90A DRBG via ARM RNDR register
++ &gEfiRngAlgorithmRaw, // Raw data from NRBG (or TRNG)
++};
++
++#define SECURE_HASH_ALGORITHMS_SIZE (sizeof (mSecureHashAlgorithms) / sizeof (EFI_GUID *))
++
+ /**
+ Locate the handles that support SNP, then open one of them
+ to send the syslog packets. The caller isn't required to close
+@@ -884,34 +905,107 @@ Ip6Swap128 (
+ }
+
+ /**
+- Initialize a random seed using current time and monotonic count.
++ Generate a Random output data given a length.
+
+- Get current time and monotonic count first. Then initialize a random seed
+- based on some basic mathematics operation on the hour, day, minute, second,
+- nanosecond and year of the current time and the monotonic count value.
++ @param[out] Output - The buffer to store the generated random data.
++ @param[in] OutputLength - The length of the output buffer.
+
+- @return The random seed initialized with current time.
++ @retval EFI_SUCCESS On Success
++ @retval EFI_INVALID_PARAMETER Pointer is null or size is zero
++ @retval EFI_NOT_FOUND RNG protocol not found
++ @retval Others Error from RngProtocol->GetRNG()
+
++ @return Status code
+ **/
+-UINT32
++EFI_STATUS
+ EFIAPI
+-NetRandomInitSeed (
+- VOID
++PseudoRandom (
++ OUT VOID *Output,
++ IN UINTN OutputLength
+ )
+ {
+- EFI_TIME Time;
+- UINT32 Seed;
+- UINT64 MonotonicCount;
++ EFI_RNG_PROTOCOL *RngProtocol;
++ EFI_STATUS Status;
++ UINTN AlgorithmIndex;
++
++ if ((Output == NULL) || (OutputLength == 0)) {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ Status = gBS->LocateProtocol (&gEfiRngProtocolGuid, NULL, (VOID **)&RngProtocol);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "Failed to locate EFI_RNG_PROTOCOL: %r\n", Status));
++ ASSERT_EFI_ERROR (Status);
++ return Status;
++ }
++
++ if (PcdGetBool (PcdEnforceSecureRngAlgorithms)) {
++ for (AlgorithmIndex = 0; AlgorithmIndex < SECURE_HASH_ALGORITHMS_SIZE; AlgorithmIndex++) {
++ Status = RngProtocol->GetRNG (RngProtocol, mSecureHashAlgorithms[AlgorithmIndex], OutputLength, (UINT8 *)Output);
++ if (!EFI_ERROR (Status)) {
++ //
++ // Secure Algorithm was supported on this platform
++ //
++ return EFI_SUCCESS;
++ } else if (Status == EFI_UNSUPPORTED) {
++ //
++ // Secure Algorithm was not supported on this platform
++ //
++ DEBUG ((DEBUG_ERROR, "Failed to generate random data using secure algorithm %d: %r\n", AlgorithmIndex, Status));
++
++ //
++ // Try the next secure algorithm
++ //
++ continue;
++ } else {
++ //
++ // Some other error occurred
++ //
++ DEBUG ((DEBUG_ERROR, "Failed to generate random data using secure algorithm %d: %r\n", AlgorithmIndex, Status));
++ ASSERT_EFI_ERROR (Status);
++ return Status;
++ }
++ }
++
++ //
++ // If we get here, we failed to generate random data using any secure algorithm
++ // Platform owner should ensure that at least one secure algorithm is supported
++ //
++ ASSERT_EFI_ERROR (Status);
++ return Status;
++ }
++
++ //
++ // Lets try using the default algorithm (which may not be secure)
++ //
++ Status = RngProtocol->GetRNG (RngProtocol, NULL, OutputLength, (UINT8 *)Output);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "%a failed to generate random data: %r\n", __func__, Status));
++ ASSERT_EFI_ERROR (Status);
++ return Status;
++ }
+
+- gRT->GetTime (&Time, NULL);
+- Seed = (Time.Hour << 24 | Time.Day << 16 | Time.Minute << 8 | Time.Second);
+- Seed ^= Time.Nanosecond;
+- Seed ^= Time.Year << 7;
++ return EFI_SUCCESS;
++}
++
++/**
++ Generate a 32-bit pseudo-random number.
+
+- gBS->GetNextMonotonicCount (&MonotonicCount);
+- Seed += (UINT32)MonotonicCount;
++ @param[out] Output - The buffer to store the generated random number.
+
+- return Seed;
++ @retval EFI_SUCCESS On Success
++ @retval EFI_NOT_FOUND RNG protocol not found
++ @retval Others Error from RngProtocol->GetRNG()
++
++ @return Status code
++**/
++EFI_STATUS
++EFIAPI
++PseudoRandomU32 (
++ OUT UINT32 *Output
++ )
++{
++ return PseudoRandom (Output, sizeof (*Output));
+ }
+
+ /**
+diff --git a/NetworkPkg/Library/DxeNetLib/DxeNetLib.inf b/NetworkPkg/Library/DxeNetLib/DxeNetLib.inf
+index 8145d256ec..a8f534a293 100644
+--- a/NetworkPkg/Library/DxeNetLib/DxeNetLib.inf
++++ b/NetworkPkg/Library/DxeNetLib/DxeNetLib.inf
+@@ -3,6 +3,7 @@
+ #
+ # Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+ # (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
++# Copyright (c) Microsoft Corporation
+ # SPDX-License-Identifier: BSD-2-Clause-Patent
+ #
+ ##
+@@ -49,7 +50,11 @@
+ gEfiSmbiosTableGuid ## SOMETIMES_CONSUMES ## SystemTable
+ gEfiSmbios3TableGuid ## SOMETIMES_CONSUMES ## SystemTable
+ gEfiAdapterInfoMediaStateGuid ## SOMETIMES_CONSUMES
+-
++ gEfiRngAlgorithmRaw ## CONSUMES
++ gEfiRngAlgorithmSp80090Ctr256Guid ## CONSUMES
++ gEfiRngAlgorithmSp80090Hmac256Guid ## CONSUMES
++ gEfiRngAlgorithmSp80090Hash256Guid ## CONSUMES
++ gEfiRngAlgorithmArmRndr ## CONSUMES
+
+ [Protocols]
+ gEfiSimpleNetworkProtocolGuid ## SOMETIMES_CONSUMES
+@@ -59,3 +64,10 @@
+ gEfiComponentNameProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiComponentName2ProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiAdapterInformationProtocolGuid ## SOMETIMES_CONSUMES
++ gEfiRngProtocolGuid ## CONSUMES
++
++[FixedPcd]
++ gEfiNetworkPkgTokenSpaceGuid.PcdEnforceSecureRngAlgorithms ## CONSUMES
++
++[Depex]
++ gEfiRngProtocolGuid
+diff --git a/NetworkPkg/NetworkPkg.dec b/NetworkPkg/NetworkPkg.dec
+index 928e84fec4..ff335e957c 100644
+--- a/NetworkPkg/NetworkPkg.dec
++++ b/NetworkPkg/NetworkPkg.dec
+@@ -5,6 +5,7 @@
+ #
+ # Copyright (c) 2009 - 2021, Intel Corporation. All rights reserved.<BR>
+ # (C) Copyright 2015-2020 Hewlett Packard Enterprise Development LP<BR>
++# Copyright (c) Microsoft Corporation
+ #
+ # SPDX-License-Identifier: BSD-2-Clause-Patent
+ #
+@@ -127,6 +128,12 @@
+ # @Prompt Indicates whether SnpDxe creates event for ExitBootServices() call.
+ gEfiNetworkPkgTokenSpaceGuid.PcdSnpCreateExitBootServicesEvent|TRUE|BOOLEAN|0x1000000C
+
++ ## Enforces the use of Secure UEFI spec defined RNG algorithms for all network connections.
++ # TRUE - Enforce the use of Secure UEFI spec defined RNG algorithms.
++ # FALSE - Do not enforce and depend on the default implementation of RNG algorithm from the provider.
++ # @Prompt Enforce the use of Secure UEFI spec defined RNG algorithms.
++ gEfiNetworkPkgTokenSpaceGuid.PcdEnforceSecureRngAlgorithms|TRUE|BOOLEAN|0x1000000D
++
+ [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
+ ## IPv6 DHCP Unique Identifier (DUID) Type configuration (From RFCs 3315 and 6355).
+ # 01 = DUID Based on Link-layer Address Plus Time [DUID-LLT]
+diff --git a/NetworkPkg/SecurityFixes.yaml b/NetworkPkg/SecurityFixes.yaml
+index 7e900483fe..2b2c794697 100644
+--- a/NetworkPkg/SecurityFixes.yaml
++++ b/NetworkPkg/SecurityFixes.yaml
+@@ -121,3 +121,42 @@ CVE_2023_45235:
+ - http://www.openwall.com/lists/oss-security/2024/01/16/2
+ - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html
+ - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html
++CVE_2023_45237:
++ commit_titles:
++ - "NetworkPkg:: SECURITY PATCH CVE 2023-45237"
++ cve: CVE-2023-45237
++ date_reported: 2023-08-28 13:56 UTC
++ description: "Bug 09 - Use of a Weak PseudoRandom Number Generator"
++ note:
++ files_impacted:
++ - NetworkPkg/Dhcp4Dxe/Dhcp4Driver.c
++ - NetworkPkg/Dhcp6Dxe/Dhcp6Driver.c
++ - NetworkPkg/DnsDxe/DnsDhcp.c
++ - NetworkPkg/DnsDxe/DnsImpl.c
++ - NetworkPkg/HttpBootDxe/HttpBootDhcp6.c
++ - NetworkPkg/IScsiDxe/IScsiCHAP.c
++ - NetworkPkg/IScsiDxe/IScsiMisc.c
++ - NetworkPkg/IScsiDxe/IScsiMisc.h
++ - NetworkPkg/Include/Library/NetLib.h
++ - NetworkPkg/Ip4Dxe/Ip4Driver.c
++ - NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c
++ - NetworkPkg/Ip6Dxe/Ip6Driver.c
++ - NetworkPkg/Ip6Dxe/Ip6If.c
++ - NetworkPkg/Ip6Dxe/Ip6Mld.c
++ - NetworkPkg/Ip6Dxe/Ip6Nd.c
++ - NetworkPkg/Ip6Dxe/Ip6Nd.h
++ - NetworkPkg/Library/DxeNetLib/DxeNetLib.c
++ - NetworkPkg/Library/DxeNetLib/DxeNetLib.inf
++ - NetworkPkg/NetworkPkg.dec
++ - NetworkPkg/TcpDxe/TcpDriver.c
++ - NetworkPkg/Udp4Dxe/Udp4Driver.c
++ - NetworkPkg/Udp6Dxe/Udp6Driver.c
++ - NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c
++ - NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
++ - NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c
++ links:
++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4542
++ - https://nvd.nist.gov/vuln/detail/CVE-2023-45237
++ - http://www.openwall.com/lists/oss-security/2024/01/16/2
++ - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html
++ - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html
+diff --git a/NetworkPkg/TcpDxe/TcpDriver.c b/NetworkPkg/TcpDxe/TcpDriver.c
+index 98a90e0210..8fe6badd68 100644
+--- a/NetworkPkg/TcpDxe/TcpDriver.c
++++ b/NetworkPkg/TcpDxe/TcpDriver.c
+@@ -2,7 +2,7 @@
+ The driver binding and service binding protocol for the TCP driver.
+
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+-
++ Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+@@ -163,7 +163,13 @@ TcpDriverEntryPoint (
+ )
+ {
+ EFI_STATUS Status;
+- UINT32 Seed;
++ UINT32 Random;
++
++ Status = PseudoRandomU32 (&Random);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "%a Failed to generate random number: %r\n", __func__, Status));
++ return Status;
++ }
+
+ //
+ // Install the TCP Driver Binding Protocol
+@@ -203,9 +209,8 @@ TcpDriverEntryPoint (
+ //
+ // Initialize ISS and random port.
+ //
+- Seed = NetRandomInitSeed ();
+- mTcpGlobalIss = NET_RANDOM (Seed) % mTcpGlobalIss;
+- mTcp4RandomPort = (UINT16)(TCP_PORT_KNOWN + (NET_RANDOM (Seed) % TCP_PORT_KNOWN));
++ mTcpGlobalIss = Random % mTcpGlobalIss;
++ mTcp4RandomPort = (UINT16)(TCP_PORT_KNOWN + (Random % TCP_PORT_KNOWN));
+ mTcp6RandomPort = mTcp4RandomPort;
+
+ return EFI_SUCCESS;
+diff --git a/NetworkPkg/TcpDxe/TcpDxe.inf b/NetworkPkg/TcpDxe/TcpDxe.inf
+index c0acbdca57..cf5423f4c5 100644
+--- a/NetworkPkg/TcpDxe/TcpDxe.inf
++++ b/NetworkPkg/TcpDxe/TcpDxe.inf
+@@ -82,5 +82,8 @@
+ gEfiTcp6ProtocolGuid ## BY_START
+ gEfiTcp6ServiceBindingProtocolGuid ## BY_START
+
++[Depex]
++ gEfiHash2ServiceBindingProtocolGuid
++
+ [UserExtensions.TianoCore."ExtraFiles"]
+ TcpDxeExtra.uni
+diff --git a/NetworkPkg/Udp4Dxe/Udp4Driver.c b/NetworkPkg/Udp4Dxe/Udp4Driver.c
+index cb917fcfc9..c7ea16f4cd 100644
+--- a/NetworkPkg/Udp4Dxe/Udp4Driver.c
++++ b/NetworkPkg/Udp4Dxe/Udp4Driver.c
+@@ -1,6 +1,7 @@
+ /** @file
+
+ Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
++Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+@@ -555,6 +556,13 @@ Udp4DriverEntryPoint (
+ )
+ {
+ EFI_STATUS Status;
++ UINT32 Random;
++
++ Status = PseudoRandomU32 (&Random);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++ return Status;
++ }
+
+ //
+ // Install the Udp4DriverBinding and Udp4ComponentName protocols.
+@@ -571,7 +579,7 @@ Udp4DriverEntryPoint (
+ //
+ // Initialize the UDP random port.
+ //
+- mUdp4RandomPort = (UINT16)(((UINT16)NetRandomInitSeed ()) % UDP4_PORT_KNOWN + UDP4_PORT_KNOWN);
++ mUdp4RandomPort = (UINT16)(((UINT16)Random) % UDP4_PORT_KNOWN + UDP4_PORT_KNOWN);
+ }
+
+ return Status;
+diff --git a/NetworkPkg/Udp6Dxe/Udp6Driver.c b/NetworkPkg/Udp6Dxe/Udp6Driver.c
+index ae96fb9966..edb758d57c 100644
+--- a/NetworkPkg/Udp6Dxe/Udp6Driver.c
++++ b/NetworkPkg/Udp6Dxe/Udp6Driver.c
+@@ -2,7 +2,7 @@
+ Driver Binding functions and Service Binding functions for the Network driver module.
+
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+-
++ Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+@@ -596,6 +596,13 @@ Udp6DriverEntryPoint (
+ )
+ {
+ EFI_STATUS Status;
++ UINT32 Random;
++
++ Status = PseudoRandomU32 (&Random);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++ return Status;
++ }
+
+ //
+ // Install the Udp6DriverBinding and Udp6ComponentName protocols.
+@@ -614,7 +621,7 @@ Udp6DriverEntryPoint (
+ // Initialize the UDP random port.
+ //
+ mUdp6RandomPort = (UINT16)(
+- ((UINT16)NetRandomInitSeed ()) %
++ ((UINT16)Random) %
+ UDP6_PORT_KNOWN +
+ UDP6_PORT_KNOWN
+ );
+diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c
+index 91146b78cb..452038c219 100644
+--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c
++++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c
+@@ -2,7 +2,7 @@
+ Functions implementation related with DHCPv4 for UefiPxeBc Driver.
+
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+-
++ Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+@@ -1381,6 +1381,12 @@ PxeBcDhcp4Discover (
+ UINT8 VendorOptLen;
+ UINT32 Xid;
+
++ Status = PseudoRandomU32 (&Xid);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++ return Status;
++ }
++
+ Mode = Private->PxeBc.Mode;
+ Dhcp4 = Private->Dhcp4;
+ Status = EFI_SUCCESS;
+@@ -1471,7 +1477,6 @@ PxeBcDhcp4Discover (
+ //
+ // Set fields of the token for the request packet.
+ //
+- Xid = NET_RANDOM (NetRandomInitSeed ());
+ Token.Packet->Dhcp4.Header.Xid = HTONL (Xid);
+ Token.Packet->Dhcp4.Header.Reserved = HTONS ((UINT16)((IsBCast) ? 0x8000 : 0x0));
+ CopyMem (&Token.Packet->Dhcp4.Header.ClientAddr, &Private->StationIp, sizeof (EFI_IPv4_ADDRESS));
+diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
+index 7fd1281c11..bcabbd2219 100644
+--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
++++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
+@@ -2180,7 +2180,7 @@ PxeBcDhcp6Discover (
+ UINTN ReadSize;
+ UINT16 OpCode;
+ UINT16 OpLen;
+- UINT32 Xid;
++ UINT32 Random;
+ EFI_STATUS Status;
+ UINTN DiscoverLenNeeded;
+
+@@ -2198,6 +2198,12 @@ PxeBcDhcp6Discover (
+ return EFI_DEVICE_ERROR;
+ }
+
++ Status = PseudoRandomU32 (&Random);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++ return Status;
++ }
++
+ DiscoverLenNeeded = sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET);
+ Discover = AllocateZeroPool (DiscoverLenNeeded);
+ if (Discover == NULL) {
+@@ -2207,8 +2213,7 @@ PxeBcDhcp6Discover (
+ //
+ // Build the discover packet by the cached request packet before.
+ //
+- Xid = NET_RANDOM (NetRandomInitSeed ());
+- Discover->TransactionId = HTONL (Xid);
++ Discover->TransactionId = HTONL (Random);
+ Discover->MessageType = Request->Dhcp6.Header.MessageType;
+ RequestOpt = Request->Dhcp6.Option;
+ DiscoverOpt = Discover->DhcpOptions;
+diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c
+index d84aca7e85..4cd915b411 100644
+--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c
++++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c
+@@ -3,6 +3,7 @@
+
+ (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
++ Copyright (c) Microsoft Corporation
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+@@ -892,6 +893,13 @@ PxeBcCreateIp6Children (
+ PXEBC_PRIVATE_PROTOCOL *Id;
+ EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
+ UINTN Index;
++ UINT32 Random;
++
++ Status = PseudoRandomU32 (&Random);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "Failed to generate random number using EFI_RNG_PROTOCOL: %r\n", Status));
++ return Status;
++ }
+
+ if (Private->Ip6Nic != NULL) {
+ //
+@@ -935,9 +943,9 @@ PxeBcCreateIp6Children (
+ }
+
+ //
+- // Generate a random IAID for the Dhcp6 assigned address.
++ // Set a random IAID for the Dhcp6 assigned address.
+ //
+- Private->IaId = NET_RANDOM (NetRandomInitSeed ());
++ Private->IaId = Random;
+ if (Private->Snp != NULL) {
+ for (Index = 0; Index < Private->Snp->Mode->HwAddressSize; Index++) {
+ Private->IaId |= (Private->Snp->Mode->CurrentAddress.Addr[Index] << ((Index << 3) & 31));
+--
+2.40.0
+
diff --git a/meta/recipes-core/ovmf/ovmf_git.bb b/meta/recipes-core/ovmf/ovmf_git.bb
index 6ac72772d1..47ed2c7cd3 100644
--- a/meta/recipes-core/ovmf/ovmf_git.bb
+++ b/meta/recipes-core/ovmf/ovmf_git.bb
@@ -47,6 +47,8 @@ SRC_URI = "gitsm://github.com/tianocore/edk2.git;branch=master;protocol=https \
file://CVE-2023-45229-0002.patch \
file://CVE-2023-45229-0003.patch \
file://CVE-2023-45229-0004.patch \
+ file://CVE-2023-45237-0001.patch \
+ file://CVE-2023-45237-0002.patch \
"
PV = "edk2-stable202202"
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 10/38] ovmf: Fix CVE-2023-45236
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (8 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 09/38] ovmf: Fix CVE-2023-45237 Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 11/38] ovmf: Fix CVE-2022-36765 Steve Sakoman
` (27 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Soumya Sambu <soumya.sambu@windriver.com>
EDK2's Network Package is susceptible to a predictable TCP Initial
Sequence Number. This vulnerability can be exploited by an attacker
to gain unauthorized access and potentially lead to a loss of
Confidentiality.
References:
https://nvd.nist.gov/vuln/detail/CVE-2023-45236
Upstream-patch:
https://github.com/tianocore/edk2/commit/1904a64bcc18199738e5be183d28887ac5d837d7
Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
---
.../ovmf/ovmf/CVE-2023-45236.patch | 829 ++++++++++++++++++
meta/recipes-core/ovmf/ovmf_git.bb | 1 +
2 files changed, 830 insertions(+)
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45236.patch
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2023-45236.patch b/meta/recipes-core/ovmf/ovmf/CVE-2023-45236.patch
new file mode 100644
index 0000000000..ac43392ce6
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/CVE-2023-45236.patch
@@ -0,0 +1,829 @@
+From 1904a64bcc18199738e5be183d28887ac5d837d7 Mon Sep 17 00:00:00 2001
+From: Doug Flick <dougflick@microsoft.com>
+Date: Wed, 8 May 2024 22:56:29 -0700
+Subject: [PATCH] NetworkPkg TcpDxe: SECURITY PATCH CVE-2023-45236
+
+REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4541
+REF: https://www.rfc-editor.org/rfc/rfc1948.txt
+REF: https://www.rfc-editor.org/rfc/rfc6528.txt
+REF: https://www.rfc-editor.org/rfc/rfc9293.txt
+
+Bug Overview:
+PixieFail Bug #8
+CVE-2023-45236
+CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N
+CWE-200 Exposure of Sensitive Information to an Unauthorized Actor
+
+Updates TCP ISN generation to use a cryptographic hash of the
+connection's identifying parameters and a secret key.
+This prevents an attacker from guessing the ISN used for some other
+connection.
+
+This is follows the guidance in RFC 1948, RFC 6528, and RFC 9293.
+
+RFC: 9293 Section 3.4.1. Initial Sequence Number Selection
+
+ A TCP implementation MUST use the above type of "clock" for clock-
+ driven selection of initial sequence numbers (MUST-8), and SHOULD
+ generate its initial sequence numbers with the expression:
+
+ ISN = M + F(localip, localport, remoteip, remoteport, secretkey)
+
+ where M is the 4 microsecond timer, and F() is a pseudorandom
+ function (PRF) of the connection's identifying parameters ("localip,
+ localport, remoteip, remoteport") and a secret key ("secretkey")
+ (SHLD-1). F() MUST NOT be computable from the outside (MUST-9), or
+ an attacker could still guess at sequence numbers from the ISN used
+ for some other connection. The PRF could be implemented as a
+ cryptographic hash of the concatenation of the TCP connection
+ parameters and some secret data. For discussion of the selection of
+ a specific hash algorithm and management of the secret key data,
+ please see Section 3 of [42].
+
+ For each connection there is a send sequence number and a receive
+ sequence number. The initial send sequence number (ISS) is chosen by
+ the data sending TCP peer, and the initial receive sequence number
+ (IRS) is learned during the connection-establishing procedure.
+
+ For a connection to be established or initialized, the two TCP peers
+ must synchronize on each other's initial sequence numbers. This is
+ done in an exchange of connection-establishing segments carrying a
+ control bit called "SYN" (for synchronize) and the initial sequence
+ numbers. As a shorthand, segments carrying the SYN bit are also
+ called "SYNs". Hence, the solution requires a suitable mechanism for
+ picking an initial sequence number and a slightly involved handshake
+ to exchange the ISNs.
+
+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-45236
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/1904a64bcc18199738e5be183d28887ac5d837d7]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ NetworkPkg/SecurityFixes.yaml | 22 +++
+ NetworkPkg/TcpDxe/TcpDriver.c | 92 ++++++++++++-
+ NetworkPkg/TcpDxe/TcpDxe.inf | 8 +-
+ NetworkPkg/TcpDxe/TcpFunc.h | 23 ++--
+ NetworkPkg/TcpDxe/TcpInput.c | 13 +-
+ NetworkPkg/TcpDxe/TcpMain.h | 59 ++++++--
+ NetworkPkg/TcpDxe/TcpMisc.c | 244 ++++++++++++++++++++++++++++++++--
+ NetworkPkg/TcpDxe/TcpTimer.c | 3 +-
+ 8 files changed, 415 insertions(+), 49 deletions(-)
+
+diff --git a/NetworkPkg/SecurityFixes.yaml b/NetworkPkg/SecurityFixes.yaml
+index 2b2c794697..ab355419cc 100644
+--- a/NetworkPkg/SecurityFixes.yaml
++++ b/NetworkPkg/SecurityFixes.yaml
+@@ -121,6 +121,28 @@ CVE_2023_45235:
+ - http://www.openwall.com/lists/oss-security/2024/01/16/2
+ - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html
+ - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html
++CVE_2023_45236:
++ commit_titles:
++ - "NetworkPkg: TcpDxe: SECURITY PATCH CVE-2023-45236 Patch"
++ cve: CVE-2023-45236
++ date_reported: 2023-08-28 13:56 UTC
++ description: "Bug 08 - edk2/NetworkPkg: Predictable TCP Initial Sequence Numbers"
++ note:
++ files_impacted:
++ - NetworkPkg/Include/Library/NetLib.h
++ - NetworkPkg/TcpDxe/TcpDriver.c
++ - NetworkPkg/TcpDxe/TcpDxe.inf
++ - NetworkPkg/TcpDxe/TcpFunc.h
++ - NetworkPkg/TcpDxe/TcpInput.c
++ - NetworkPkg/TcpDxe/TcpMain.h
++ - NetworkPkg/TcpDxe/TcpMisc.c
++ - NetworkPkg/TcpDxe/TcpTimer.c
++ links:
++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4541
++ - https://nvd.nist.gov/vuln/detail/CVE-2023-45236
++ - http://www.openwall.com/lists/oss-security/2024/01/16/2
++ - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html
++ - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html
+ CVE_2023_45237:
+ commit_titles:
+ - "NetworkPkg:: SECURITY PATCH CVE 2023-45237"
+diff --git a/NetworkPkg/TcpDxe/TcpDriver.c b/NetworkPkg/TcpDxe/TcpDriver.c
+index 8fe6badd68..40bba4080c 100644
+--- a/NetworkPkg/TcpDxe/TcpDriver.c
++++ b/NetworkPkg/TcpDxe/TcpDriver.c
+@@ -83,6 +83,12 @@ EFI_SERVICE_BINDING_PROTOCOL gTcpServiceBinding = {
+ TcpServiceBindingDestroyChild
+ };
+
++//
++// This is the handle for the Hash2ServiceBinding Protocol instance this driver produces
++// if the platform does not provide one.
++//
++EFI_HANDLE mHash2ServiceHandle = NULL;
++
+ /**
+ Create and start the heartbeat timer for the TCP driver.
+
+@@ -165,6 +171,23 @@ TcpDriverEntryPoint (
+ EFI_STATUS Status;
+ UINT32 Random;
+
++ //
++ // Initialize the Secret used for hashing TCP sequence numbers
++ //
++ // Normally this should be regenerated periodically, but since
++ // this is only used for UEFI networking and not a general purpose
++ // operating system, it is not necessary to regenerate it.
++ //
++ Status = PseudoRandomU32 (&mTcpGlobalSecret);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++ return Status;
++ }
++
++ //
++ // Get a random number used to generate a random port number
++ // Intentionally not linking this to mTcpGlobalSecret to avoid leaking information about the secret
++ //
+ Status = PseudoRandomU32 (&Random);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a Failed to generate random number: %r\n", __func__, Status));
+@@ -207,9 +230,8 @@ TcpDriverEntryPoint (
+ }
+
+ //
+- // Initialize ISS and random port.
++ // Initialize the random port.
+ //
+- mTcpGlobalIss = Random % mTcpGlobalIss;
+ mTcp4RandomPort = (UINT16)(TCP_PORT_KNOWN + (Random % TCP_PORT_KNOWN));
+ mTcp6RandomPort = mTcp4RandomPort;
+
+@@ -224,6 +246,8 @@ TcpDriverEntryPoint (
+ @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate some resources.
++ @retval EFI_UNSUPPORTED Service Binding Protocols are unavailable.
++ @retval EFI_ALREADY_STARTED The TCP driver is already started on the controller.
+ @retval EFI_SUCCESS A new IP6 service binding private was created.
+
+ **/
+@@ -234,11 +258,13 @@ TcpCreateService (
+ IN UINT8 IpVersion
+ )
+ {
+- EFI_STATUS Status;
+- EFI_GUID *IpServiceBindingGuid;
+- EFI_GUID *TcpServiceBindingGuid;
+- TCP_SERVICE_DATA *TcpServiceData;
+- IP_IO_OPEN_DATA OpenData;
++ EFI_STATUS Status;
++ EFI_GUID *IpServiceBindingGuid;
++ EFI_GUID *TcpServiceBindingGuid;
++ TCP_SERVICE_DATA *TcpServiceData;
++ IP_IO_OPEN_DATA OpenData;
++ EFI_SERVICE_BINDING_PROTOCOL *Hash2ServiceBinding;
++ EFI_HASH2_PROTOCOL *Hash2Protocol;
+
+ if (IpVersion == IP_VERSION_4) {
+ IpServiceBindingGuid = &gEfiIp4ServiceBindingProtocolGuid;
+@@ -272,6 +298,33 @@ TcpCreateService (
+ return EFI_UNSUPPORTED;
+ }
+
++ Status = gBS->LocateProtocol (&gEfiHash2ProtocolGuid, NULL, (VOID **)&Hash2Protocol);
++ if (EFI_ERROR (Status)) {
++ //
++ // If we can't find the Hashing protocol, then we need to create one.
++ //
++
++ //
++ // Platform is expected to publish the hash service binding protocol to support TCP.
++ //
++ Status = gBS->LocateProtocol (
++ &gEfiHash2ServiceBindingProtocolGuid,
++ NULL,
++ (VOID **)&Hash2ServiceBinding
++ );
++ if (EFI_ERROR (Status) || (Hash2ServiceBinding == NULL) || (Hash2ServiceBinding->CreateChild == NULL)) {
++ return EFI_UNSUPPORTED;
++ }
++
++ //
++ // Create an instance of the hash protocol for this controller.
++ //
++ Status = Hash2ServiceBinding->CreateChild (Hash2ServiceBinding, &mHash2ServiceHandle);
++ if (EFI_ERROR (Status)) {
++ return EFI_UNSUPPORTED;
++ }
++ }
++
+ //
+ // Create the TCP service data.
+ //
+@@ -423,6 +476,7 @@ TcpDestroyService (
+ EFI_STATUS Status;
+ LIST_ENTRY *List;
+ TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;
++ EFI_SERVICE_BINDING_PROTOCOL *Hash2ServiceBinding;
+
+ ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));
+
+@@ -439,6 +493,30 @@ TcpDestroyService (
+ return EFI_SUCCESS;
+ }
+
++ //
++ // Destroy the Hash2ServiceBinding instance if it is created by Tcp driver.
++ //
++ if (mHash2ServiceHandle != NULL) {
++ Status = gBS->LocateProtocol (
++ &gEfiHash2ServiceBindingProtocolGuid,
++ NULL,
++ (VOID **)&Hash2ServiceBinding
++ );
++ if (EFI_ERROR (Status) || (Hash2ServiceBinding == NULL) || (Hash2ServiceBinding->DestroyChild == NULL)) {
++ return EFI_UNSUPPORTED;
++ }
++
++ //
++ // Destroy the instance of the hashing protocol for this controller.
++ //
++ Status = Hash2ServiceBinding->DestroyChild (Hash2ServiceBinding, &mHash2ServiceHandle);
++ if (EFI_ERROR (Status)) {
++ return EFI_UNSUPPORTED;
++ }
++
++ mHash2ServiceHandle = NULL;
++ }
++
+ Status = gBS->OpenProtocol (
+ NicHandle,
+ ServiceBindingGuid,
+diff --git a/NetworkPkg/TcpDxe/TcpDxe.inf b/NetworkPkg/TcpDxe/TcpDxe.inf
+index cf5423f4c5..76de4cf9ec 100644
+--- a/NetworkPkg/TcpDxe/TcpDxe.inf
++++ b/NetworkPkg/TcpDxe/TcpDxe.inf
+@@ -6,6 +6,7 @@
+ # stack has been loaded in system. This driver supports both IPv4 and IPv6 network stack.
+ #
+ # Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
++# Copyright (c) Microsoft Corporation
+ #
+ # SPDX-License-Identifier: BSD-2-Clause-Patent
+ #
+@@ -68,7 +69,6 @@
+ NetLib
+ IpIoLib
+
+-
+ [Protocols]
+ ## SOMETIMES_CONSUMES
+ ## SOMETIMES_PRODUCES
+@@ -81,6 +81,12 @@
+ gEfiIp6ServiceBindingProtocolGuid ## TO_START
+ gEfiTcp6ProtocolGuid ## BY_START
+ gEfiTcp6ServiceBindingProtocolGuid ## BY_START
++ gEfiHash2ProtocolGuid ## BY_START
++ gEfiHash2ServiceBindingProtocolGuid ## BY_START
++
++[Guids]
++ gEfiHashAlgorithmMD5Guid ## CONSUMES
++ gEfiHashAlgorithmSha256Guid ## CONSUMES
+
+ [Depex]
+ gEfiHash2ServiceBindingProtocolGuid
+diff --git a/NetworkPkg/TcpDxe/TcpFunc.h b/NetworkPkg/TcpDxe/TcpFunc.h
+index a7af01fff2..c707bee3e5 100644
+--- a/NetworkPkg/TcpDxe/TcpFunc.h
++++ b/NetworkPkg/TcpDxe/TcpFunc.h
+@@ -2,7 +2,7 @@
+ Declaration of external functions shared in TCP driver.
+
+ Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
+-
++ Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+@@ -36,8 +36,11 @@ VOID
+
+ @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
+
++ @retval EFI_SUCCESS The operation completed successfully
++ @retval others The underlying functions failed and could not complete the operation
++
+ **/
+-VOID
++EFI_STATUS
+ TcpInitTcbLocal (
+ IN OUT TCP_CB *Tcb
+ );
+@@ -128,17 +131,6 @@ TcpCloneTcb (
+ IN TCP_CB *Tcb
+ );
+
+-/**
+- Compute an ISS to be used by a new connection.
+-
+- @return The result ISS.
+-
+-**/
+-TCP_SEQNO
+-TcpGetIss (
+- VOID
+- );
+-
+ /**
+ Get the local mss.
+
+@@ -202,8 +194,11 @@ TcpFormatNetbuf (
+ @param[in, out] Tcb Pointer to the TCP_CB that wants to initiate a
+ connection.
+
++ @retval EFI_SUCCESS The operation completed successfully
++ @retval others The underlying functions failed and could not complete the operation
++
+ **/
+-VOID
++EFI_STATUS
+ TcpOnAppConnect (
+ IN OUT TCP_CB *Tcb
+ );
+diff --git a/NetworkPkg/TcpDxe/TcpInput.c b/NetworkPkg/TcpDxe/TcpInput.c
+index fb1aa827f8..0477a15d0c 100644
+--- a/NetworkPkg/TcpDxe/TcpInput.c
++++ b/NetworkPkg/TcpDxe/TcpInput.c
+@@ -724,6 +724,7 @@ TcpInput (
+ TCP_SEQNO Urg;
+ UINT16 Checksum;
+ INT32 Usable;
++ EFI_STATUS Status;
+
+ ASSERT ((Version == IP_VERSION_4) || (Version == IP_VERSION_6));
+
+@@ -872,7 +873,17 @@ TcpInput (
+ Tcb->LocalEnd.Port = Head->DstPort;
+ Tcb->RemoteEnd.Port = Head->SrcPort;
+
+- TcpInitTcbLocal (Tcb);
++ Status = TcpInitTcbLocal (Tcb);
++ if (EFI_ERROR (Status)) {
++ DEBUG (
++ (DEBUG_ERROR,
++ "TcpInput: discard a segment because failed to init local end for TCB %p\n",
++ Tcb)
++ );
++
++ goto DISCARD;
++ }
++
+ TcpInitTcbPeer (Tcb, Seg, &Option);
+
+ TcpSetState (Tcb, TCP_SYN_RCVD);
+diff --git a/NetworkPkg/TcpDxe/TcpMain.h b/NetworkPkg/TcpDxe/TcpMain.h
+index c0c9b7f46e..4d5566ab93 100644
+--- a/NetworkPkg/TcpDxe/TcpMain.h
++++ b/NetworkPkg/TcpDxe/TcpMain.h
+@@ -3,7 +3,7 @@
+ It is the common head file for all Tcp*.c in TCP driver.
+
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+-
++ Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+@@ -13,6 +13,7 @@
+
+ #include <Protocol/ServiceBinding.h>
+ #include <Protocol/DriverBinding.h>
++#include <Protocol/Hash2.h>
+ #include <Library/IpIoLib.h>
+ #include <Library/DevicePathLib.h>
+ #include <Library/PrintLib.h>
+@@ -31,7 +32,7 @@ extern EFI_UNICODE_STRING_TABLE *gTcpControllerNameTable;
+
+ extern LIST_ENTRY mTcpRunQue;
+ extern LIST_ENTRY mTcpListenQue;
+-extern TCP_SEQNO mTcpGlobalIss;
++extern TCP_SEQNO mTcpGlobalSecret;
+ extern UINT32 mTcpTick;
+
+ ///
+@@ -45,14 +46,6 @@ extern UINT32 mTcpTick;
+
+ #define TCP_EXPIRE_TIME 65535
+
+-///
+-/// The implementation selects the initial send sequence number and the unit to
+-/// be added when it is increased.
+-///
+-#define TCP_BASE_ISS 0x4d7e980b
+-#define TCP_ISS_INCREMENT_1 2048
+-#define TCP_ISS_INCREMENT_2 100
+-
+ typedef union {
+ EFI_TCP4_CONFIG_DATA Tcp4CfgData;
+ EFI_TCP6_CONFIG_DATA Tcp6CfgData;
+@@ -774,4 +767,50 @@ Tcp6Poll (
+ IN EFI_TCP6_PROTOCOL *This
+ );
+
++/**
++ Retrieves the Initial Sequence Number (ISN) for a TCP connection identified by local
++ and remote IP addresses and ports.
++
++ This method is based on https://datatracker.ietf.org/doc/html/rfc9293#section-3.4.1
++ Where the ISN is computed as follows:
++ ISN = TimeStamp + MD5(LocalIP, LocalPort, RemoteIP, RemotePort, Secret)
++
++ Otherwise:
++ ISN = M + F(localip, localport, remoteip, remoteport, secretkey)
++
++ "Here M is the 4 microsecond timer, and F() is a pseudorandom function (PRF) of the
++ connection's identifying parameters ("localip, localport, remoteip, remoteport")
++ and a secret key ("secretkey") (SHLD-1). F() MUST NOT be computable from the
++ outside (MUST-9), or an attacker could still guess at sequence numbers from the
++ ISN used for some other connection. The PRF could be implemented as a
++ cryptographic hash of the concatenation of the TCP connection parameters and some
++ secret data. For discussion of the selection of a specific hash algorithm and
++ management of the secret key data."
++
++ @param[in] LocalIp A pointer to the local IP address of the TCP connection.
++ @param[in] LocalIpSize The size, in bytes, of the LocalIp buffer.
++ @param[in] LocalPort The local port number of the TCP connection.
++ @param[in] RemoteIp A pointer to the remote IP address of the TCP connection.
++ @param[in] RemoteIpSize The size, in bytes, of the RemoteIp buffer.
++ @param[in] RemotePort The remote port number of the TCP connection.
++ @param[out] Isn A pointer to the variable that will receive the Initial
++ Sequence Number (ISN).
++
++ @retval EFI_SUCCESS The operation completed successfully, and the ISN was
++ retrieved.
++ @retval EFI_INVALID_PARAMETER One or more of the input parameters are invalid.
++ @retval EFI_UNSUPPORTED The operation is not supported.
++
++**/
++EFI_STATUS
++TcpGetIsn (
++ IN UINT8 *LocalIp,
++ IN UINTN LocalIpSize,
++ IN UINT16 LocalPort,
++ IN UINT8 *RemoteIp,
++ IN UINTN RemoteIpSize,
++ IN UINT16 RemotePort,
++ OUT TCP_SEQNO *Isn
++ );
++
+ #endif
+diff --git a/NetworkPkg/TcpDxe/TcpMisc.c b/NetworkPkg/TcpDxe/TcpMisc.c
+index c93212d47d..3310306f63 100644
+--- a/NetworkPkg/TcpDxe/TcpMisc.c
++++ b/NetworkPkg/TcpDxe/TcpMisc.c
+@@ -3,7 +3,7 @@
+
+ (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>
+-
++ Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+@@ -20,7 +20,34 @@ LIST_ENTRY mTcpListenQue = {
+ &mTcpListenQue
+ };
+
+-TCP_SEQNO mTcpGlobalIss = TCP_BASE_ISS;
++//
++// The Session secret
++// This must be initialized to a random value at boot time
++//
++TCP_SEQNO mTcpGlobalSecret;
++
++//
++// Union to hold either an IPv4 or IPv6 address
++// This is used to simplify the ISN hash computation
++//
++typedef union {
++ UINT8 IPv4[4];
++ UINT8 IPv6[16];
++} NETWORK_ADDRESS;
++
++//
++// The ISN is computed by hashing this structure
++// It is initialized with the local and remote IP addresses and ports
++// and the secret
++//
++//
++typedef struct {
++ UINT16 LocalPort;
++ UINT16 RemotePort;
++ NETWORK_ADDRESS LocalAddress;
++ NETWORK_ADDRESS RemoteAddress;
++ TCP_SEQNO Secret;
++} ISN_HASH_CTX;
+
+ CHAR16 *mTcpStateName[] = {
+ L"TCP_CLOSED",
+@@ -41,12 +68,18 @@ CHAR16 *mTcpStateName[] = {
+
+ @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
+
++ @retval EFI_SUCCESS The operation completed successfully
++ @retval others The underlying functions failed and could not complete the operation
++
+ **/
+-VOID
++EFI_STATUS
+ TcpInitTcbLocal (
+ IN OUT TCP_CB *Tcb
+ )
+ {
++ TCP_SEQNO Isn;
++ EFI_STATUS Status;
++
+ //
+ // Compute the checksum of the fixed parts of pseudo header
+ //
+@@ -57,6 +90,16 @@ TcpInitTcbLocal (
+ 0x06,
+ 0
+ );
++
++ Status = TcpGetIsn (
++ Tcb->LocalEnd.Ip.v4.Addr,
++ sizeof (IPv4_ADDRESS),
++ Tcb->LocalEnd.Port,
++ Tcb->RemoteEnd.Ip.v4.Addr,
++ sizeof (IPv4_ADDRESS),
++ Tcb->RemoteEnd.Port,
++ &Isn
++ );
+ } else {
+ Tcb->HeadSum = NetIp6PseudoHeadChecksum (
+ &Tcb->LocalEnd.Ip.v6,
+@@ -64,9 +107,25 @@ TcpInitTcbLocal (
+ 0x06,
+ 0
+ );
++
++ Status = TcpGetIsn (
++ Tcb->LocalEnd.Ip.v6.Addr,
++ sizeof (IPv6_ADDRESS),
++ Tcb->LocalEnd.Port,
++ Tcb->RemoteEnd.Ip.v6.Addr,
++ sizeof (IPv6_ADDRESS),
++ Tcb->RemoteEnd.Port,
++ &Isn
++ );
++ }
++
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_ERROR, "TcpInitTcbLocal: failed to get isn\n"));
++ ASSERT (FALSE);
++ return Status;
+ }
+
+- Tcb->Iss = TcpGetIss ();
++ Tcb->Iss = Isn;
+ Tcb->SndUna = Tcb->Iss;
+ Tcb->SndNxt = Tcb->Iss;
+
+@@ -82,6 +141,8 @@ TcpInitTcbLocal (
+ Tcb->RetxmitSeqMax = 0;
+
+ Tcb->ProbeTimerOn = FALSE;
++
++ return EFI_SUCCESS;
+ }
+
+ /**
+@@ -506,18 +567,162 @@ TcpCloneTcb (
+ }
+
+ /**
+- Compute an ISS to be used by a new connection.
+-
+- @return The resulting ISS.
++ Retrieves the Initial Sequence Number (ISN) for a TCP connection identified by local
++ and remote IP addresses and ports.
++
++ This method is based on https://datatracker.ietf.org/doc/html/rfc9293#section-3.4.1
++ Where the ISN is computed as follows:
++ ISN = TimeStamp + MD5(LocalIP, LocalPort, RemoteIP, RemotePort, Secret)
++
++ Otherwise:
++ ISN = M + F(localip, localport, remoteip, remoteport, secretkey)
++
++ "Here M is the 4 microsecond timer, and F() is a pseudorandom function (PRF) of the
++ connection's identifying parameters ("localip, localport, remoteip, remoteport")
++ and a secret key ("secretkey") (SHLD-1). F() MUST NOT be computable from the
++ outside (MUST-9), or an attacker could still guess at sequence numbers from the
++ ISN used for some other connection. The PRF could be implemented as a
++ cryptographic hash of the concatenation of the TCP connection parameters and some
++ secret data. For discussion of the selection of a specific hash algorithm and
++ management of the secret key data."
++
++ @param[in] LocalIp A pointer to the local IP address of the TCP connection.
++ @param[in] LocalIpSize The size, in bytes, of the LocalIp buffer.
++ @param[in] LocalPort The local port number of the TCP connection.
++ @param[in] RemoteIp A pointer to the remote IP address of the TCP connection.
++ @param[in] RemoteIpSize The size, in bytes, of the RemoteIp buffer.
++ @param[in] RemotePort The remote port number of the TCP connection.
++ @param[out] Isn A pointer to the variable that will receive the Initial
++ Sequence Number (ISN).
++
++ @retval EFI_SUCCESS The operation completed successfully, and the ISN was
++ retrieved.
++ @retval EFI_INVALID_PARAMETER One or more of the input parameters are invalid.
++ @retval EFI_UNSUPPORTED The operation is not supported.
+
+ **/
+-TCP_SEQNO
+-TcpGetIss (
+- VOID
++EFI_STATUS
++TcpGetIsn (
++ IN UINT8 *LocalIp,
++ IN UINTN LocalIpSize,
++ IN UINT16 LocalPort,
++ IN UINT8 *RemoteIp,
++ IN UINTN RemoteIpSize,
++ IN UINT16 RemotePort,
++ OUT TCP_SEQNO *Isn
+ )
+ {
+- mTcpGlobalIss += TCP_ISS_INCREMENT_1;
+- return mTcpGlobalIss;
++ EFI_STATUS Status;
++ EFI_HASH2_PROTOCOL *Hash2Protocol;
++ EFI_HASH2_OUTPUT HashResult;
++ ISN_HASH_CTX IsnHashCtx;
++ EFI_TIME TimeStamp;
++
++ //
++ // Check that the ISN pointer is valid
++ //
++ if (Isn == NULL) {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ //
++ // The local ip may be a v4 or v6 address and may not be NULL
++ //
++ if ((LocalIp == NULL) || (LocalIpSize == 0) || (RemoteIp == NULL) || (RemoteIpSize == 0)) {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ //
++ // the local ip may be a v4 or v6 address
++ //
++ if ((LocalIpSize != sizeof (EFI_IPv4_ADDRESS)) && (LocalIpSize != sizeof (EFI_IPv6_ADDRESS))) {
++ return EFI_INVALID_PARAMETER;
++ }
++
++ //
++ // Locate the Hash Protocol
++ //
++ Status = gBS->LocateProtocol (&gEfiHash2ProtocolGuid, NULL, (VOID **)&Hash2Protocol);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_NET, "Failed to locate Hash Protocol: %r\n", Status));
++
++ //
++ // TcpCreateService(..) is expected to be called prior to this function
++ //
++ ASSERT_EFI_ERROR (Status);
++ return Status;
++ }
++
++ //
++ // Initialize the hash algorithm
++ //
++ Status = Hash2Protocol->HashInit (Hash2Protocol, &gEfiHashAlgorithmSha256Guid);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_NET, "Failed to initialize sha256 hash algorithm: %r\n", Status));
++ return Status;
++ }
++
++ IsnHashCtx.LocalPort = LocalPort;
++ IsnHashCtx.RemotePort = RemotePort;
++ IsnHashCtx.Secret = mTcpGlobalSecret;
++
++ //
++ // Check the IP address family and copy accordingly
++ //
++ if (LocalIpSize == sizeof (EFI_IPv4_ADDRESS)) {
++ CopyMem (&IsnHashCtx.LocalAddress.IPv4, LocalIp, LocalIpSize);
++ } else if (LocalIpSize == sizeof (EFI_IPv6_ADDRESS)) {
++ CopyMem (&IsnHashCtx.LocalAddress.IPv6, LocalIp, LocalIpSize);
++ } else {
++ return EFI_INVALID_PARAMETER; // Unsupported address size
++ }
++
++ //
++ // Repeat the process for the remote IP address
++ //
++ if (RemoteIpSize == sizeof (EFI_IPv4_ADDRESS)) {
++ CopyMem (&IsnHashCtx.RemoteAddress.IPv4, RemoteIp, RemoteIpSize);
++ } else if (RemoteIpSize == sizeof (EFI_IPv6_ADDRESS)) {
++ CopyMem (&IsnHashCtx.RemoteAddress.IPv6, RemoteIp, RemoteIpSize);
++ } else {
++ return EFI_INVALID_PARAMETER; // Unsupported address size
++ }
++
++ //
++ // Compute the hash
++ // Update the hash with the data
++ //
++ Status = Hash2Protocol->HashUpdate (Hash2Protocol, (UINT8 *)&IsnHashCtx, sizeof (IsnHashCtx));
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_NET, "Failed to update hash: %r\n", Status));
++ return Status;
++ }
++
++ //
++ // Finalize the hash and retrieve the result
++ //
++ Status = Hash2Protocol->HashFinal (Hash2Protocol, &HashResult);
++ if (EFI_ERROR (Status)) {
++ DEBUG ((DEBUG_NET, "Failed to finalize hash: %r\n", Status));
++ return Status;
++ }
++
++ Status = gRT->GetTime (&TimeStamp, NULL);
++ if (EFI_ERROR (Status)) {
++ return Status;
++ }
++
++ //
++ // copy the first 4 bytes of the hash result into the ISN
++ //
++ CopyMem (Isn, HashResult.Md5Hash, sizeof (*Isn));
++
++ //
++ // now add the timestamp to the ISN as 4 microseconds units (1000 / 4 = 250)
++ //
++ *Isn += (TCP_SEQNO)TimeStamp.Nanosecond * 250;
++
++ return Status;
+ }
+
+ /**
+@@ -721,17 +926,28 @@ TcpFormatNetbuf (
+ @param[in, out] Tcb Pointer to the TCP_CB that wants to initiate a
+ connection.
+
++ @retval EFI_SUCCESS The operation completed successfully
++ @retval others The underlying functions failed and could not complete the operation
++
+ **/
+-VOID
++EFI_STATUS
+ TcpOnAppConnect (
+ IN OUT TCP_CB *Tcb
+ )
+ {
+- TcpInitTcbLocal (Tcb);
++ EFI_STATUS Status;
++
++ Status = TcpInitTcbLocal (Tcb);
++ if (EFI_ERROR (Status)) {
++ return Status;
++ }
++
+ TcpSetState (Tcb, TCP_SYN_SENT);
+
+ TcpSetTimer (Tcb, TCP_TIMER_CONNECT, Tcb->ConnectTimeout);
+ TcpToSendData (Tcb, 1);
++
++ return EFI_SUCCESS;
+ }
+
+ /**
+diff --git a/NetworkPkg/TcpDxe/TcpTimer.c b/NetworkPkg/TcpDxe/TcpTimer.c
+index 5d2e124977..065b1bdf5f 100644
+--- a/NetworkPkg/TcpDxe/TcpTimer.c
++++ b/NetworkPkg/TcpDxe/TcpTimer.c
+@@ -2,7 +2,7 @@
+ TCP timer related functions.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+-
++ Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+@@ -483,7 +483,6 @@ TcpTickingDpc (
+ INT16 Index;
+
+ mTcpTick++;
+- mTcpGlobalIss += TCP_ISS_INCREMENT_2;
+
+ //
+ // Don't use LIST_FOR_EACH, which isn't delete safe.
+--
+2.40.0
+
diff --git a/meta/recipes-core/ovmf/ovmf_git.bb b/meta/recipes-core/ovmf/ovmf_git.bb
index 47ed2c7cd3..dbfed086e4 100644
--- a/meta/recipes-core/ovmf/ovmf_git.bb
+++ b/meta/recipes-core/ovmf/ovmf_git.bb
@@ -49,6 +49,7 @@ SRC_URI = "gitsm://github.com/tianocore/edk2.git;branch=master;protocol=https \
file://CVE-2023-45229-0004.patch \
file://CVE-2023-45237-0001.patch \
file://CVE-2023-45237-0002.patch \
+ file://CVE-2023-45236.patch \
"
PV = "edk2-stable202202"
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 11/38] ovmf: Fix CVE-2022-36765
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (9 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 10/38] ovmf: Fix CVE-2023-45236 Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 12/38] ovmf: fix CVE-2024-38796 Steve Sakoman
` (26 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Soumya Sambu <soumya.sambu@windriver.com>
EDK2 is susceptible to a vulnerability in the CreateHob() function,
allowing a user to trigger a integer overflow to buffer overflow
via a local network. Successful exploitation of this vulnerability
may result in a compromise of confidentiality, integrity, and/or
availability.
References:
https://nvd.nist.gov/vuln/detail/CVE-2022-36765
Upstream-patches:
https://github.com/tianocore/edk2/commit/59f024c76ee57c2bec84794536302fc770cd6ec2
https://github.com/tianocore/edk2/commit/aeaee8944f0eaacbf4cdf39279785b9ba4836bb6
https://github.com/tianocore/edk2/commit/9a75b030cf27d2530444e9a2f9f11867f79bf679
Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
---
.../ovmf/ovmf/CVE-2022-36765-0001.patch | 179 ++++++++++++++++++
.../ovmf/ovmf/CVE-2022-36765-0002.patch | 157 +++++++++++++++
.../ovmf/ovmf/CVE-2022-36765-0003.patch | 135 +++++++++++++
meta/recipes-core/ovmf/ovmf_git.bb | 3 +
4 files changed, 474 insertions(+)
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2022-36765-0001.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2022-36765-0002.patch
create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2022-36765-0003.patch
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2022-36765-0001.patch b/meta/recipes-core/ovmf/ovmf/CVE-2022-36765-0001.patch
new file mode 100644
index 0000000000..120cf66f6a
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/CVE-2022-36765-0001.patch
@@ -0,0 +1,179 @@
+From 59f024c76ee57c2bec84794536302fc770cd6ec2 Mon Sep 17 00:00:00 2001
+From: Gua Guo <gua.guo@intel.com>
+Date: Thu, 11 Jan 2024 13:01:19 +0800
+Subject: [PATCH] UefiPayloadPkg/Hob: Integer Overflow in CreateHob()
+
+REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4166
+
+Fix integer overflow in various CreateHob instances.
+Fixes: CVE-2022-36765
+
+The CreateHob() function aligns the requested size to 8
+performing the following operation:
+```
+HobLength = (UINT16)((HobLength + 0x7) & (~0x7));
+```
+
+No checks are performed to ensure this value doesn't
+overflow, and could lead to CreateHob() returning a smaller
+HOB than requested, which could lead to OOB HOB accesses.
+
+Reported-by: Marc Beatove <mbeatove@google.com>
+Cc: Guo Dong <guo.dong@intel.com>
+Cc: Sean Rhodes <sean@starlabs.systems>
+Cc: James Lu <james.lu@intel.com>
+Reviewed-by: Gua Guo <gua.guo@intel.com>
+Cc: John Mathew <john.mathews@intel.com>
+Authored-by: Gerd Hoffmann <kraxel@redhat.com>
+Signed-off-by: Gua Guo <gua.guo@intel.com>
+
+CVE: CVE-2022-36765
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/59f024c76ee57c2bec84794536302fc770cd6ec2]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ .../Library/PayloadEntryHobLib/Hob.c | 43 +++++++++++++++++++
+ .../UefiPayloadEntry/UniversalPayloadEntry.c | 8 ++--
+ 2 files changed, 48 insertions(+), 3 deletions(-)
+
+diff --git a/UefiPayloadPkg/Library/PayloadEntryHobLib/Hob.c b/UefiPayloadPkg/Library/PayloadEntryHobLib/Hob.c
+index 2c3acbbc19..51c2e28d7d 100644
+--- a/UefiPayloadPkg/Library/PayloadEntryHobLib/Hob.c
++++ b/UefiPayloadPkg/Library/PayloadEntryHobLib/Hob.c
+@@ -110,6 +110,13 @@ CreateHob (
+
+ HandOffHob = GetHobList ();
+
++ //
++ // Check Length to avoid data overflow.
++ //
++ if (HobLength > MAX_UINT16 - 0x7) {
++ return NULL;
++ }
++
+ HobLength = (UINT16)((HobLength + 0x7) & (~0x7));
+
+ FreeMemory = HandOffHob->EfiFreeMemoryTop - HandOffHob->EfiFreeMemoryBottom;
+@@ -160,6 +167,9 @@ BuildResourceDescriptorHob (
+
+ Hob = CreateHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, sizeof (EFI_HOB_RESOURCE_DESCRIPTOR));
+ ASSERT (Hob != NULL);
++ if (Hob == NULL) {
++ return;
++ }
+
+ Hob->ResourceType = ResourceType;
+ Hob->ResourceAttribute = ResourceAttribute;
+@@ -330,6 +340,10 @@ BuildModuleHob (
+ );
+
+ Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION_MODULE));
++ ASSERT (Hob != NULL);
++ if (Hob == NULL) {
++ return;
++ }
+
+ CopyGuid (&(Hob->MemoryAllocationHeader.Name), &gEfiHobMemoryAllocModuleGuid);
+ Hob->MemoryAllocationHeader.MemoryBaseAddress = MemoryAllocationModule;
+@@ -378,6 +392,11 @@ BuildGuidHob (
+ ASSERT (DataLength <= (0xffff - sizeof (EFI_HOB_GUID_TYPE)));
+
+ Hob = CreateHob (EFI_HOB_TYPE_GUID_EXTENSION, (UINT16)(sizeof (EFI_HOB_GUID_TYPE) + DataLength));
++ ASSERT (Hob != NULL);
++ if (Hob == NULL) {
++ return NULL;
++ }
++
+ CopyGuid (&Hob->Name, Guid);
+ return Hob + 1;
+ }
+@@ -441,6 +460,10 @@ BuildFvHob (
+ EFI_HOB_FIRMWARE_VOLUME *Hob;
+
+ Hob = CreateHob (EFI_HOB_TYPE_FV, sizeof (EFI_HOB_FIRMWARE_VOLUME));
++ ASSERT (Hob != NULL);
++ if (Hob == NULL) {
++ return;
++ }
+
+ Hob->BaseAddress = BaseAddress;
+ Hob->Length = Length;
+@@ -472,6 +495,10 @@ BuildFv2Hob (
+ EFI_HOB_FIRMWARE_VOLUME2 *Hob;
+
+ Hob = CreateHob (EFI_HOB_TYPE_FV2, sizeof (EFI_HOB_FIRMWARE_VOLUME2));
++ ASSERT (Hob != NULL);
++ if (Hob == NULL) {
++ return;
++ }
+
+ Hob->BaseAddress = BaseAddress;
+ Hob->Length = Length;
+@@ -513,6 +540,10 @@ BuildFv3Hob (
+ EFI_HOB_FIRMWARE_VOLUME3 *Hob;
+
+ Hob = CreateHob (EFI_HOB_TYPE_FV3, sizeof (EFI_HOB_FIRMWARE_VOLUME3));
++ ASSERT (Hob != NULL);
++ if (Hob == NULL) {
++ return;
++ }
+
+ Hob->BaseAddress = BaseAddress;
+ Hob->Length = Length;
+@@ -546,6 +577,10 @@ BuildCpuHob (
+ EFI_HOB_CPU *Hob;
+
+ Hob = CreateHob (EFI_HOB_TYPE_CPU, sizeof (EFI_HOB_CPU));
++ ASSERT (Hob != NULL);
++ if (Hob == NULL) {
++ return;
++ }
+
+ Hob->SizeOfMemorySpace = SizeOfMemorySpace;
+ Hob->SizeOfIoSpace = SizeOfIoSpace;
+@@ -583,6 +618,10 @@ BuildStackHob (
+ );
+
+ Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION_STACK));
++ ASSERT (Hob != NULL);
++ if (Hob == NULL) {
++ return;
++ }
+
+ CopyGuid (&(Hob->AllocDescriptor.Name), &gEfiHobMemoryAllocStackGuid);
+ Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress;
+@@ -664,6 +703,10 @@ BuildMemoryAllocationHob (
+ );
+
+ Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION));
++ ASSERT (Hob != NULL);
++ if (Hob == NULL) {
++ return;
++ }
+
+ ZeroMem (&(Hob->AllocDescriptor.Name), sizeof (EFI_GUID));
+ Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress;
+diff --git a/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.c b/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.c
+index edb3c20471..abfe75bd7b 100644
+--- a/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.c
++++ b/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.c
+@@ -111,10 +111,12 @@ AddNewHob (
+ }
+
+ NewHob.Header = CreateHob (Hob->Header->HobType, Hob->Header->HobLength);
+-
+- if (NewHob.Header != NULL) {
+- CopyMem (NewHob.Header + 1, Hob->Header + 1, Hob->Header->HobLength - sizeof (EFI_HOB_GENERIC_HEADER));
++ ASSERT (NewHob.Header != NULL);
++ if (NewHob.Header == NULL) {
++ return;
+ }
++
++ CopyMem (NewHob.Header + 1, Hob->Header + 1, Hob->Header->HobLength - sizeof (EFI_HOB_GENERIC_HEADER));
+ }
+
+ /**
+--
+2.40.0
+
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2022-36765-0002.patch b/meta/recipes-core/ovmf/ovmf/CVE-2022-36765-0002.patch
new file mode 100644
index 0000000000..1209be27b5
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/CVE-2022-36765-0002.patch
@@ -0,0 +1,157 @@
+From aeaee8944f0eaacbf4cdf39279785b9ba4836bb6 Mon Sep 17 00:00:00 2001
+From: Gua Guo <gua.guo@intel.com>
+Date: Thu, 11 Jan 2024 13:07:50 +0800
+Subject: [PATCH] EmbeddedPkg/Hob: Integer Overflow in CreateHob()
+
+REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4166
+
+Fix integer overflow in various CreateHob instances.
+Fixes: CVE-2022-36765
+
+The CreateHob() function aligns the requested size to 8
+performing the following operation:
+```
+HobLength = (UINT16)((HobLength + 0x7) & (~0x7));
+```
+
+No checks are performed to ensure this value doesn't
+overflow, and could lead to CreateHob() returning a smaller
+HOB than requested, which could lead to OOB HOB accesses.
+
+Reported-by: Marc Beatove <mbeatove@google.com>
+Cc: Leif Lindholm <quic_llindhol@quicinc.com>
+Reviewed-by: Ard Biesheuvel <ardb+tianocore@kernel.org>
+Cc: Abner Chang <abner.chang@amd.com>
+Cc: John Mathew <john.mathews@intel.com>
+Authored-by: Gerd Hoffmann <kraxel@redhat.com>
+Signed-off-by: Gua Guo <gua.guo@intel.com>
+
+CVE: CVE-2022-36765
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/aeaee8944f0eaacbf4cdf39279785b9ba4836bb6]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ EmbeddedPkg/Library/PrePiHobLib/Hob.c | 43 +++++++++++++++++++++++++++
+ 1 file changed, 43 insertions(+)
+
+diff --git a/EmbeddedPkg/Library/PrePiHobLib/Hob.c b/EmbeddedPkg/Library/PrePiHobLib/Hob.c
+index 8eb175aa96..cbc35152cc 100644
+--- a/EmbeddedPkg/Library/PrePiHobLib/Hob.c
++++ b/EmbeddedPkg/Library/PrePiHobLib/Hob.c
+@@ -110,6 +110,13 @@ CreateHob (
+
+ HandOffHob = GetHobList ();
+
++ //
++ // Check Length to avoid data overflow.
++ //
++ if (HobLength > MAX_UINT16 - 0x7) {
++ return NULL;
++ }
++
+ HobLength = (UINT16)((HobLength + 0x7) & (~0x7));
+
+ FreeMemory = HandOffHob->EfiFreeMemoryTop - HandOffHob->EfiFreeMemoryBottom;
+@@ -160,6 +167,9 @@ BuildResourceDescriptorHob (
+
+ Hob = CreateHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, sizeof (EFI_HOB_RESOURCE_DESCRIPTOR));
+ ASSERT (Hob != NULL);
++ if (Hob == NULL) {
++ return;
++ }
+
+ Hob->ResourceType = ResourceType;
+ Hob->ResourceAttribute = ResourceAttribute;
+@@ -401,6 +411,10 @@ BuildModuleHob (
+ );
+
+ Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION_MODULE));
++ ASSERT (Hob != NULL);
++ if (Hob == NULL) {
++ return;
++ }
+
+ CopyGuid (&(Hob->MemoryAllocationHeader.Name), &gEfiHobMemoryAllocModuleGuid);
+ Hob->MemoryAllocationHeader.MemoryBaseAddress = MemoryAllocationModule;
+@@ -449,6 +463,11 @@ BuildGuidHob (
+ ASSERT (DataLength <= (0xffff - sizeof (EFI_HOB_GUID_TYPE)));
+
+ Hob = CreateHob (EFI_HOB_TYPE_GUID_EXTENSION, (UINT16)(sizeof (EFI_HOB_GUID_TYPE) + DataLength));
++ ASSERT (Hob != NULL);
++ if (Hob == NULL) {
++ return NULL;
++ }
++
+ CopyGuid (&Hob->Name, Guid);
+ return Hob + 1;
+ }
+@@ -512,6 +531,10 @@ BuildFvHob (
+ EFI_HOB_FIRMWARE_VOLUME *Hob;
+
+ Hob = CreateHob (EFI_HOB_TYPE_FV, sizeof (EFI_HOB_FIRMWARE_VOLUME));
++ ASSERT (Hob != NULL);
++ if (Hob == NULL) {
++ return;
++ }
+
+ Hob->BaseAddress = BaseAddress;
+ Hob->Length = Length;
+@@ -543,6 +566,10 @@ BuildFv2Hob (
+ EFI_HOB_FIRMWARE_VOLUME2 *Hob;
+
+ Hob = CreateHob (EFI_HOB_TYPE_FV2, sizeof (EFI_HOB_FIRMWARE_VOLUME2));
++ ASSERT (Hob != NULL);
++ if (Hob == NULL) {
++ return;
++ }
+
+ Hob->BaseAddress = BaseAddress;
+ Hob->Length = Length;
+@@ -584,6 +611,10 @@ BuildFv3Hob (
+ EFI_HOB_FIRMWARE_VOLUME3 *Hob;
+
+ Hob = CreateHob (EFI_HOB_TYPE_FV3, sizeof (EFI_HOB_FIRMWARE_VOLUME3));
++ ASSERT (Hob != NULL);
++ if (Hob == NULL) {
++ return;
++ }
+
+ Hob->BaseAddress = BaseAddress;
+ Hob->Length = Length;
+@@ -639,6 +670,10 @@ BuildCpuHob (
+ EFI_HOB_CPU *Hob;
+
+ Hob = CreateHob (EFI_HOB_TYPE_CPU, sizeof (EFI_HOB_CPU));
++ ASSERT (Hob != NULL);
++ if (Hob == NULL) {
++ return;
++ }
+
+ Hob->SizeOfMemorySpace = SizeOfMemorySpace;
+ Hob->SizeOfIoSpace = SizeOfIoSpace;
+@@ -676,6 +711,10 @@ BuildStackHob (
+ );
+
+ Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION_STACK));
++ ASSERT (Hob != NULL);
++ if (Hob == NULL) {
++ return;
++ }
+
+ CopyGuid (&(Hob->AllocDescriptor.Name), &gEfiHobMemoryAllocStackGuid);
+ Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress;
+@@ -756,6 +795,10 @@ BuildMemoryAllocationHob (
+ );
+
+ Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION));
++ ASSERT (Hob != NULL);
++ if (Hob == NULL) {
++ return;
++ }
+
+ ZeroMem (&(Hob->AllocDescriptor.Name), sizeof (EFI_GUID));
+ Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress;
+--
+2.40.0
+
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2022-36765-0003.patch b/meta/recipes-core/ovmf/ovmf/CVE-2022-36765-0003.patch
new file mode 100644
index 0000000000..9579205e09
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/CVE-2022-36765-0003.patch
@@ -0,0 +1,135 @@
+From 9a75b030cf27d2530444e9a2f9f11867f79bf679 Mon Sep 17 00:00:00 2001
+From: Gua Guo <gua.guo@intel.com>
+Date: Thu, 11 Jan 2024 13:03:26 +0800
+Subject: [PATCH] StandaloneMmPkg/Hob: Integer Overflow in CreateHob()
+
+REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4166
+
+Fix integer overflow in various CreateHob instances.
+Fixes: CVE-2022-36765
+
+The CreateHob() function aligns the requested size to 8
+performing the following operation:
+```
+HobLength = (UINT16)((HobLength + 0x7) & (~0x7));
+```
+
+No checks are performed to ensure this value doesn't
+overflow, and could lead to CreateHob() returning a smaller
+HOB than requested, which could lead to OOB HOB accesses.
+
+Reported-by: Marc Beatove <mbeatove@google.com>
+Reviewed-by: Ard Biesheuvel <ardb+tianocore@kernel.org>
+Cc: Sami Mujawar <sami.mujawar@arm.com>
+Reviewed-by: Ray Ni <ray.ni@intel.com>
+Cc: John Mathew <john.mathews@intel.com>
+Authored-by: Gerd Hoffmann <kraxel@redhat.com>
+Signed-off-by: Gua Guo <gua.guo@intel.com>
+
+CVE: CVE-2022-36765
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/9a75b030cf27d2530444e9a2f9f11867f79bf679]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ .../Arm/StandaloneMmCoreHobLib.c | 35 +++++++++++++++++++
+ 1 file changed, 35 insertions(+)
+
+diff --git a/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/Arm/StandaloneMmCoreHobLib.c b/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/Arm/StandaloneMmCoreHobLib.c
+index 1550e1babc..59473e28fe 100644
+--- a/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/Arm/StandaloneMmCoreHobLib.c
++++ b/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/Arm/StandaloneMmCoreHobLib.c
+@@ -34,6 +34,13 @@ CreateHob (
+
+ HandOffHob = GetHobList ();
+
++ //
++ // Check Length to avoid data overflow.
++ //
++ if (HobLength > MAX_UINT16 - 0x7) {
++ return NULL;
++ }
++
+ HobLength = (UINT16)((HobLength + 0x7) & (~0x7));
+
+ FreeMemory = HandOffHob->EfiFreeMemoryTop - HandOffHob->EfiFreeMemoryBottom;
+@@ -89,6 +96,10 @@ BuildModuleHob (
+ );
+
+ Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION_MODULE));
++ ASSERT (Hob != NULL);
++ if (Hob == NULL) {
++ return;
++ }
+
+ CopyGuid (&(Hob->MemoryAllocationHeader.Name), &gEfiHobMemoryAllocModuleGuid);
+ Hob->MemoryAllocationHeader.MemoryBaseAddress = MemoryAllocationModule;
+@@ -129,6 +140,9 @@ BuildResourceDescriptorHob (
+
+ Hob = CreateHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, sizeof (EFI_HOB_RESOURCE_DESCRIPTOR));
+ ASSERT (Hob != NULL);
++ if (Hob == NULL) {
++ return;
++ }
+
+ Hob->ResourceType = ResourceType;
+ Hob->ResourceAttribute = ResourceAttribute;
+@@ -167,6 +181,11 @@ BuildGuidHob (
+ ASSERT (DataLength <= (0xffff - sizeof (EFI_HOB_GUID_TYPE)));
+
+ Hob = CreateHob (EFI_HOB_TYPE_GUID_EXTENSION, (UINT16)(sizeof (EFI_HOB_GUID_TYPE) + DataLength));
++ ASSERT (Hob != NULL);
++ if (Hob == NULL) {
++ return NULL;
++ }
++
+ CopyGuid (&Hob->Name, Guid);
+ return Hob + 1;
+ }
+@@ -226,6 +245,10 @@ BuildFvHob (
+ EFI_HOB_FIRMWARE_VOLUME *Hob;
+
+ Hob = CreateHob (EFI_HOB_TYPE_FV, sizeof (EFI_HOB_FIRMWARE_VOLUME));
++ ASSERT (Hob != NULL);
++ if (Hob == NULL) {
++ return;
++ }
+
+ Hob->BaseAddress = BaseAddress;
+ Hob->Length = Length;
+@@ -255,6 +278,10 @@ BuildFv2Hob (
+ EFI_HOB_FIRMWARE_VOLUME2 *Hob;
+
+ Hob = CreateHob (EFI_HOB_TYPE_FV2, sizeof (EFI_HOB_FIRMWARE_VOLUME2));
++ ASSERT (Hob != NULL);
++ if (Hob == NULL) {
++ return;
++ }
+
+ Hob->BaseAddress = BaseAddress;
+ Hob->Length = Length;
+@@ -282,6 +309,10 @@ BuildCpuHob (
+ EFI_HOB_CPU *Hob;
+
+ Hob = CreateHob (EFI_HOB_TYPE_CPU, sizeof (EFI_HOB_CPU));
++ ASSERT (Hob != NULL);
++ if (Hob == NULL) {
++ return;
++ }
+
+ Hob->SizeOfMemorySpace = SizeOfMemorySpace;
+ Hob->SizeOfIoSpace = SizeOfIoSpace;
+@@ -319,6 +350,10 @@ BuildMemoryAllocationHob (
+ );
+
+ Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION));
++ ASSERT (Hob != NULL);
++ if (Hob == NULL) {
++ return;
++ }
+
+ ZeroMem (&(Hob->AllocDescriptor.Name), sizeof (EFI_GUID));
+ Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress;
+--
+2.40.0
+
diff --git a/meta/recipes-core/ovmf/ovmf_git.bb b/meta/recipes-core/ovmf/ovmf_git.bb
index dbfed086e4..1dba709824 100644
--- a/meta/recipes-core/ovmf/ovmf_git.bb
+++ b/meta/recipes-core/ovmf/ovmf_git.bb
@@ -50,6 +50,9 @@ SRC_URI = "gitsm://github.com/tianocore/edk2.git;branch=master;protocol=https \
file://CVE-2023-45237-0001.patch \
file://CVE-2023-45237-0002.patch \
file://CVE-2023-45236.patch \
+ file://CVE-2022-36765-0001.patch \
+ file://CVE-2022-36765-0002.patch \
+ file://CVE-2022-36765-0003.patch \
"
PV = "edk2-stable202202"
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 12/38] ovmf: fix CVE-2024-38796
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (10 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 11/38] ovmf: Fix CVE-2022-36765 Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 13/38] ovmf: fix CVE-2024-1298 Steve Sakoman
` (25 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Hongxu Jia <hongxu.jia@windriver.com>
Backport a fix from upstream to resolve CVE-2024-38796
https://github.com/tianocore/edk2/commit/c95233b8525ca6828921affd1496146cff262e65
Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
---
...-Fix-overflow-issue-in-BasePeCoffLib.patch | 37 +++++++++++++++++++
meta/recipes-core/ovmf/ovmf_git.bb | 1 +
2 files changed, 38 insertions(+)
create mode 100644 meta/recipes-core/ovmf/ovmf/0001-MdePkg-Fix-overflow-issue-in-BasePeCoffLib.patch
diff --git a/meta/recipes-core/ovmf/ovmf/0001-MdePkg-Fix-overflow-issue-in-BasePeCoffLib.patch b/meta/recipes-core/ovmf/ovmf/0001-MdePkg-Fix-overflow-issue-in-BasePeCoffLib.patch
new file mode 100644
index 0000000000..8d36bdf1c1
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/0001-MdePkg-Fix-overflow-issue-in-BasePeCoffLib.patch
@@ -0,0 +1,37 @@
+From c4d6af8428375c0343fcfd20bf1465e6d4be4690 Mon Sep 17 00:00:00 2001
+From: Doug Flick <dougflick@microsoft.com>
+Date: Fri, 22 Nov 2024 17:44:27 +0800
+Subject: [PATCH] MdePkg: Fix overflow issue in BasePeCoffLib
+
+The RelocDir->Size is a UINT32 value, and RelocDir->VirtualAddress is
+also a UINT32 value. The current code does not check for overflow when
+adding RelocDir->Size to RelocDir->VirtualAddress. This patch adds a
+check to ensure that the addition does not overflow.
+
+Signed-off-by: Doug Flick <dougflick@microsoft.com>
+Authored-by: sriraamx gobichettipalayam <sri..@intel.com>
+
+CVE: CVE-2024-38796
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/c95233b8525ca6828921affd1496146cff262e65]
+
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+---
+ MdePkg/Library/BasePeCoffLib/BasePeCoff.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/MdePkg/Library/BasePeCoffLib/BasePeCoff.c b/MdePkg/Library/BasePeCoffLib/BasePeCoff.c
+index 6d8d9faeb8..2339b111b5 100644
+--- a/MdePkg/Library/BasePeCoffLib/BasePeCoff.c
++++ b/MdePkg/Library/BasePeCoffLib/BasePeCoff.c
+@@ -1014,7 +1014,7 @@ PeCoffLoaderRelocateImage (
+ RelocDir = &Hdr.Te->DataDirectory[0];
+ }
+
+- if ((RelocDir != NULL) && (RelocDir->Size > 0)) {
++ if ((RelocDir != NULL) && (RelocDir->Size > 0) && (RelocDir->Size - 1 < MAX_UINT32 - RelocDir->VirtualAddress)) {
+ RelocBase = (EFI_IMAGE_BASE_RELOCATION *)PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress, TeStrippedOffset);
+ RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *)PeCoffLoaderImageAddress (
+ ImageContext,
+--
+2.34.1
+
diff --git a/meta/recipes-core/ovmf/ovmf_git.bb b/meta/recipes-core/ovmf/ovmf_git.bb
index 1dba709824..e626d306a4 100644
--- a/meta/recipes-core/ovmf/ovmf_git.bb
+++ b/meta/recipes-core/ovmf/ovmf_git.bb
@@ -53,6 +53,7 @@ SRC_URI = "gitsm://github.com/tianocore/edk2.git;branch=master;protocol=https \
file://CVE-2022-36765-0001.patch \
file://CVE-2022-36765-0002.patch \
file://CVE-2022-36765-0003.patch \
+ file://0001-MdePkg-Fix-overflow-issue-in-BasePeCoffLib.patch \
"
PV = "edk2-stable202202"
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 13/38] ovmf: fix CVE-2024-1298
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (11 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 12/38] ovmf: fix CVE-2024-38796 Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 14/38] libsoup: fix CVE-2024-52531 Steve Sakoman
` (24 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Hongxu Jia <hongxu.jia@windriver.com>
Backport a fix from upstream to resolve CVE-2024-1298
https://github.com/tianocore/edk2/commit/284dbac43da752ee34825c8b3f6f9e8281cb5a19
Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
---
...ential-UINT32-overflow-in-S3-ResumeC.patch | 51 +++++++++++++++++++
meta/recipes-core/ovmf/ovmf_git.bb | 1 +
2 files changed, 52 insertions(+)
create mode 100644 meta/recipes-core/ovmf/ovmf/0001-MdeModulePkg-Potential-UINT32-overflow-in-S3-ResumeC.patch
diff --git a/meta/recipes-core/ovmf/ovmf/0001-MdeModulePkg-Potential-UINT32-overflow-in-S3-ResumeC.patch b/meta/recipes-core/ovmf/ovmf/0001-MdeModulePkg-Potential-UINT32-overflow-in-S3-ResumeC.patch
new file mode 100644
index 0000000000..7480f8722e
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/0001-MdeModulePkg-Potential-UINT32-overflow-in-S3-ResumeC.patch
@@ -0,0 +1,51 @@
+From 63f29c180dd04d13614440740a8795ee422567b8 Mon Sep 17 00:00:00 2001
+From: Hongxu Jia <hongxu.jia@windriver.com>
+Date: Fri, 22 Nov 2024 17:43:28 +0800
+Subject: [PATCH] MdeModulePkg: Potential UINT32 overflow in S3 ResumeCount
+
+REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4677
+
+Attacker able to modify physical memory and ResumeCount.
+System will crash/DoS when ResumeCount reaches its MAX_UINT32.
+
+Cc: Zhiguang Liu <zhiguang.liu@intel.com>
+Cc: Dandan Bi <dandan.bi@intel.com>
+Cc: Liming Gao <gaoliming@byosoft.com.cn>
+
+Signed-off-by: Pakkirisamy ShanmugavelX <shanmugavelx.pakkirisamy@intel.com>
+Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
+
+CVE: CVE-2024-1298
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/284dbac43da752ee34825c8b3f6f9e8281cb5a19]
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+---
+ .../FirmwarePerformancePei.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.c b/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.c
+index 2f2b2a80b2..2ba9215226 100644
+--- a/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.c
++++ b/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.c
+@@ -112,11 +112,15 @@ FpdtStatusCodeListenerPei (
+ //
+ S3ResumeTotal = MultU64x32 (AcpiS3ResumeRecord->AverageResume, AcpiS3ResumeRecord->ResumeCount);
+ AcpiS3ResumeRecord->ResumeCount++;
+- AcpiS3ResumeRecord->AverageResume = DivU64x32 (S3ResumeTotal + AcpiS3ResumeRecord->FullResume, AcpiS3ResumeRecord->ResumeCount);
++ if (AcpiS3ResumeRecord->ResumeCount > 0) {
++ AcpiS3ResumeRecord->AverageResume = DivU64x32 (S3ResumeTotal + AcpiS3ResumeRecord->FullResume, AcpiS3ResumeRecord->ResumeCount);
++ DEBUG ((DEBUG_INFO, "\nFPDT: S3 Resume Performance - AverageResume = 0x%x\n", AcpiS3ResumeRecord->AverageResume));
++ } else {
++ DEBUG ((DEBUG_ERROR, "\nFPDT: S3 ResumeCount reaches the MAX_UINT32 value. S3 ResumeCount record reset to Zero."));
++ }
+
+- DEBUG ((DEBUG_INFO, "FPDT: S3 Resume Performance - ResumeCount = %d\n", AcpiS3ResumeRecord->ResumeCount));
+- DEBUG ((DEBUG_INFO, "FPDT: S3 Resume Performance - FullResume = %ld\n", AcpiS3ResumeRecord->FullResume));
+- DEBUG ((DEBUG_INFO, "FPDT: S3 Resume Performance - AverageResume = %ld\n", AcpiS3ResumeRecord->AverageResume));
++ DEBUG ((DEBUG_INFO, "FPDT: S3 Resume Performance - ResumeCount = 0x%x\n", AcpiS3ResumeRecord->ResumeCount));
++ DEBUG ((DEBUG_INFO, "FPDT: S3 Resume Performance - FullResume = 0x%x\n", AcpiS3ResumeRecord->FullResume));
+
+ //
+ // Update S3 Suspend Performance Record.
+--
+2.34.1
+
diff --git a/meta/recipes-core/ovmf/ovmf_git.bb b/meta/recipes-core/ovmf/ovmf_git.bb
index e626d306a4..a067dd017b 100644
--- a/meta/recipes-core/ovmf/ovmf_git.bb
+++ b/meta/recipes-core/ovmf/ovmf_git.bb
@@ -54,6 +54,7 @@ SRC_URI = "gitsm://github.com/tianocore/edk2.git;branch=master;protocol=https \
file://CVE-2022-36765-0002.patch \
file://CVE-2022-36765-0003.patch \
file://0001-MdePkg-Fix-overflow-issue-in-BasePeCoffLib.patch \
+ file://0001-MdeModulePkg-Potential-UINT32-overflow-in-S3-ResumeC.patch \
"
PV = "edk2-stable202202"
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 14/38] libsoup: fix CVE-2024-52531
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (12 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 13/38] ovmf: fix CVE-2024-1298 Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 15/38] python3-zipp: fix CVE-2024-5569 Steve Sakoman
` (23 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Changqing Li <changqing.li@windriver.com>
CVE-2024-52531:
GNOME libsoup before 3.6.1 allows a buffer overflow in applications that
perform conversion to UTF-8 in soup_header_parse_param_list_strict.
Input received over the network cannot trigger this.
Refer:
https://nvd.nist.gov/vuln/detail/CVE-2024-52531
https://gitlab.gnome.org/GNOME/libsoup/-/merge_requests/407/
Signed-off-by: Changqing Li <changqing.li@windriver.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
---
.../libsoup/libsoup/CVE-2024-52531-1.patch | 116 +++++++++++++++
.../libsoup/libsoup/CVE-2024-52531-2.patch | 40 ++++++
.../libsoup/libsoup/CVE-2024-52531-3.patch | 136 ++++++++++++++++++
meta/recipes-support/libsoup/libsoup_3.0.7.bb | 3 +
4 files changed, 295 insertions(+)
create mode 100644 meta/recipes-support/libsoup/libsoup/CVE-2024-52531-1.patch
create mode 100644 meta/recipes-support/libsoup/libsoup/CVE-2024-52531-2.patch
create mode 100644 meta/recipes-support/libsoup/libsoup/CVE-2024-52531-3.patch
diff --git a/meta/recipes-support/libsoup/libsoup/CVE-2024-52531-1.patch b/meta/recipes-support/libsoup/libsoup/CVE-2024-52531-1.patch
new file mode 100644
index 0000000000..c8e855c128
--- /dev/null
+++ b/meta/recipes-support/libsoup/libsoup/CVE-2024-52531-1.patch
@@ -0,0 +1,116 @@
+From 4ec9e3d286b6d3e982cb0fc3564dee0bf8d87ede Mon Sep 17 00:00:00 2001
+From: Patrick Griffis <pgriffis@igalia.com>
+Date: Tue, 27 Aug 2024 12:18:58 -0500
+Subject: [PATCH] fuzzing: Cover soup_header_parse_param_list
+
+CVE: CVE-2024-52531
+Upstream-Status: Backport
+[https://gitlab.gnome.org/GNOME/libsoup/-/merge_requests/407/diffs?commit_id=4ec9e3d286b6d3e982cb0fc3564dee0bf8d87ede]
+
+Signed-off-by: Changqing Li <changqing.li@windriver.com>
+
+---
+ fuzzing/fuzz.h | 9 +++++++--
+ fuzzing/fuzz_header_parsing.c | 19 +++++++++++++++++++
+ fuzzing/fuzz_header_parsing.dict | 8 ++++++++
+ fuzzing/meson.build | 2 ++
+ 4 files changed, 36 insertions(+), 2 deletions(-)
+ create mode 100644 fuzzing/fuzz_header_parsing.c
+ create mode 100644 fuzzing/fuzz_header_parsing.dict
+
+diff --git a/fuzzing/fuzz.h b/fuzzing/fuzz.h
+index 0d380285..f3bd28ee 100644
+--- a/fuzzing/fuzz.h
++++ b/fuzzing/fuzz.h
+@@ -1,13 +1,14 @@
+ #include "libsoup/soup.h"
+
+ int LLVMFuzzerTestOneInput (const unsigned char *data, size_t size);
++static int set_logger = 0;
+
+ #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ static GLogWriterOutput
+ empty_logging_func (GLogLevelFlags log_level, const GLogField *fields,
+ gsize n_fields, gpointer user_data)
+ {
+- return G_LOG_WRITER_HANDLED;
++ return G_LOG_WRITER_HANDLED;
+ }
+ #endif
+
+@@ -16,6 +17,10 @@ static void
+ fuzz_set_logging_func (void)
+ {
+ #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+- g_log_set_writer_func (empty_logging_func, NULL, NULL);
++ if (!set_logger)
++ {
++ set_logger = 1;
++ g_log_set_writer_func (empty_logging_func, NULL, NULL);
++ }
+ #endif
+ }
+diff --git a/fuzzing/fuzz_header_parsing.c b/fuzzing/fuzz_header_parsing.c
+new file mode 100644
+index 00000000..a8e5c1f9
+--- /dev/null
++++ b/fuzzing/fuzz_header_parsing.c
+@@ -0,0 +1,19 @@
++#include "fuzz.h"
++
++int
++LLVMFuzzerTestOneInput (const unsigned char *data, size_t size)
++{
++ GHashTable *elements;
++
++ // We only accept NUL terminated strings
++ if (!size || data[size - 1] != '\0')
++ return 0;
++
++ fuzz_set_logging_func ();
++
++ elements = soup_header_parse_param_list((char*)data);
++
++ g_hash_table_unref(elements);
++
++ return 0;
++}
+\ No newline at end of file
+diff --git a/fuzzing/fuzz_header_parsing.dict b/fuzzing/fuzz_header_parsing.dict
+new file mode 100644
+index 00000000..1562ca3a
+--- /dev/null
++++ b/fuzzing/fuzz_header_parsing.dict
+@@ -0,0 +1,8 @@
++"*=UTF-8''"
++"*=iso-8859-1''"
++"'"
++"''"
++"="
++"*="
++"""
++";"
+\ No newline at end of file
+diff --git a/fuzzing/meson.build b/fuzzing/meson.build
+index b14cbb50..5dd0f417 100644
+--- a/fuzzing/meson.build
++++ b/fuzzing/meson.build
+@@ -5,6 +5,7 @@ fuzz_targets = [
+ 'fuzz_cookie_parse',
+ 'fuzz_content_sniffer',
+ 'fuzz_date_time',
++ 'fuzz_header_parsing',
+ ]
+
+ fuzzing_args = '-fsanitize=fuzzer,address,undefined'
+@@ -34,6 +35,7 @@ if have_fuzzing and (fuzzing_feature.enabled() or fuzzing_feature.auto())
+ '-runs=200000',
+ '-artifact_prefix=meson-logs/' + target + '-',
+ '-print_final_stats=1',
++ '-max_len=4096',
+ ] + extra_args,
+ env: [
+ 'ASAN_OPTIONS=fast_unwind_on_malloc=0',
+--
+2.25.1
+
diff --git a/meta/recipes-support/libsoup/libsoup/CVE-2024-52531-2.patch b/meta/recipes-support/libsoup/libsoup/CVE-2024-52531-2.patch
new file mode 100644
index 0000000000..7e0d81ba4c
--- /dev/null
+++ b/meta/recipes-support/libsoup/libsoup/CVE-2024-52531-2.patch
@@ -0,0 +1,40 @@
+From 825fda3425546847b42ad5270544e9388ff349fe Mon Sep 17 00:00:00 2001
+From: Patrick Griffis <pgriffis@igalia.com>
+Date: Tue, 27 Aug 2024 13:52:08 -0500
+Subject: [PATCH] tests: Add test for passing invalid UTF-8 to
+ soup_header_parse_semi_param_list()
+
+CVE: CVE-2024-52531
+Upstream-Status: Backport
+[https://gitlab.gnome.org/GNOME/libsoup/-/merge_requests/407/diffs?commit_id=825fda3425546847b42ad5270544e9388ff349fe]
+
+Signed-off-by: Changqing Li <changqing.li@windriver.com>
+---
+ tests/header-parsing-test.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/tests/header-parsing-test.c b/tests/header-parsing-test.c
+index 715c2c6f..5e423d2b 100644
+--- a/tests/header-parsing-test.c
++++ b/tests/header-parsing-test.c
+@@ -825,6 +825,17 @@ static struct ParamListTest {
+ { "filename", "t\xC3\xA9st.txt" },
+ },
+ },
++
++ /* This tests invalid UTF-8 data which *should* never be passed here but it was designed to be robust against it. */
++ { TRUE,
++ "invalid*=\x69\x27\x27\x93\x93\x93\x93\xff\x61\x61\x61\x61\x61\x61\x61\x62\x63\x64\x65\x0a; filename*=iso-8859-1''\x69\x27\x27\x93\x93\x93\x93\xff\x61\x61\x61\x61\x61\x61\x61\x62\x63\x64\x65\x0a; foo",
++ {
++ { "filename", "i''\302\223\302\223\302\223\302\223\303\277aaaaaaabcde" },
++ { "invalid", "\302\223\302\223\302\223\302\223\303\277aaaaaaabcde" },
++ { "foo", NULL },
++
++ },
++ }
+ };
+ static const int num_paramlisttests = G_N_ELEMENTS (paramlisttests);
+
+--
+2.25.1
+
diff --git a/meta/recipes-support/libsoup/libsoup/CVE-2024-52531-3.patch b/meta/recipes-support/libsoup/libsoup/CVE-2024-52531-3.patch
new file mode 100644
index 0000000000..a47c8747c5
--- /dev/null
+++ b/meta/recipes-support/libsoup/libsoup/CVE-2024-52531-3.patch
@@ -0,0 +1,136 @@
+From a35222dd0bfab2ac97c10e86b95f762456628283 Mon Sep 17 00:00:00 2001
+From: Patrick Griffis <pgriffis@igalia.com>
+Date: Tue, 27 Aug 2024 13:53:26 -0500
+Subject: [PATCH] headers: Be more robust against invalid input when parsing
+ params
+
+If you pass invalid input to a function such as soup_header_parse_param_list_strict()
+it can cause an overflow if it decodes the input to UTF-8.
+
+This should never happen with valid UTF-8 input which libsoup's client API
+ensures, however it's server API does not currently.
+
+CVE: CVE-2024-52531
+Upstream-Status: Backport
+[https://gitlab.gnome.org/GNOME/libsoup/-/merge_requests/407/diffs?commit_id=a35222dd0bfab2ac97c10e86b95f762456628283]
+
+Signed-off-by: Changqing Li <changqing.li@windriver.com>
+
+---
+ libsoup/soup-headers.c | 46 ++++++++++++++++++++++--------------------
+ 1 file changed, 24 insertions(+), 22 deletions(-)
+
+diff --git a/libsoup/soup-headers.c b/libsoup/soup-headers.c
+index f30ee467..613e1905 100644
+--- a/libsoup/soup-headers.c
++++ b/libsoup/soup-headers.c
+@@ -646,8 +646,9 @@ soup_header_contains (const char *header, const char *token)
+ }
+
+ static void
+-decode_quoted_string (char *quoted_string)
++decode_quoted_string_inplace (GString *quoted_gstring)
+ {
++ char *quoted_string = quoted_gstring->str;
+ char *src, *dst;
+
+ src = quoted_string + 1;
+@@ -661,10 +662,11 @@ decode_quoted_string (char *quoted_string)
+ }
+
+ static gboolean
+-decode_rfc5987 (char *encoded_string)
++decode_rfc5987_inplace (GString *encoded_gstring)
+ {
+ char *q, *decoded;
+ gboolean iso_8859_1 = FALSE;
++ const char *encoded_string = encoded_gstring->str;
+
+ q = strchr (encoded_string, '\'');
+ if (!q)
+@@ -696,14 +698,7 @@ decode_rfc5987 (char *encoded_string)
+ decoded = utf8;
+ }
+
+- /* If encoded_string was UTF-8, then each 3-character %-escape
+- * will be converted to a single byte, and so decoded is
+- * shorter than encoded_string. If encoded_string was
+- * iso-8859-1, then each 3-character %-escape will be
+- * converted into at most 2 bytes in UTF-8, and so it's still
+- * shorter.
+- */
+- strcpy (encoded_string, decoded);
++ g_string_assign (encoded_gstring, decoded);
+ g_free (decoded);
+ return TRUE;
+ }
+@@ -713,15 +708,17 @@ parse_param_list (const char *header, char delim, gboolean strict)
+ {
+ GHashTable *params;
+ GSList *list, *iter;
+- char *item, *eq, *name_end, *value;
+- gboolean override, duplicated;
+
+ params = g_hash_table_new_full (soup_str_case_hash,
+ soup_str_case_equal,
+- g_free, NULL);
++ g_free, g_free);
+
+ list = parse_list (header, delim);
+ for (iter = list; iter; iter = iter->next) {
++ char *item, *eq, *name_end;
++ gboolean override, duplicated;
++ GString *parsed_value = NULL;
++
+ item = iter->data;
+ override = FALSE;
+
+@@ -736,19 +733,19 @@ parse_param_list (const char *header, char delim, gboolean strict)
+
+ *name_end = '\0';
+
+- value = (char *)skip_lws (eq + 1);
++ parsed_value = g_string_new ((char *)skip_lws (eq + 1));
+
+ if (name_end[-1] == '*' && name_end > item + 1) {
+ name_end[-1] = '\0';
+- if (!decode_rfc5987 (value)) {
++ if (!decode_rfc5987_inplace (parsed_value)) {
++ g_string_free (parsed_value, TRUE);
+ g_free (item);
+ continue;
+ }
+ override = TRUE;
+- } else if (*value == '"')
+- decode_quoted_string (value);
+- } else
+- value = NULL;
++ } else if (parsed_value->str[0] == '"')
++ decode_quoted_string_inplace (parsed_value);
++ }
+
+ duplicated = g_hash_table_lookup_extended (params, item, NULL, NULL);
+
+@@ -756,11 +753,16 @@ parse_param_list (const char *header, char delim, gboolean strict)
+ soup_header_free_param_list (params);
+ params = NULL;
+ g_slist_foreach (iter, (GFunc)g_free, NULL);
++ if (parsed_value)
++ g_string_free (parsed_value, TRUE);
+ break;
+- } else if (override || !duplicated)
+- g_hash_table_replace (params, item, value);
+- else
++ } else if (override || !duplicated) {
++ g_hash_table_replace (params, item, parsed_value ? g_string_free (parsed_value, FALSE) : NULL);
++ } else {
++ if (parsed_value)
++ g_string_free (parsed_value, TRUE);
+ g_free (item);
++ }
+ }
+
+ g_slist_free (list);
+--
+2.25.1
+
diff --git a/meta/recipes-support/libsoup/libsoup_3.0.7.bb b/meta/recipes-support/libsoup/libsoup_3.0.7.bb
index 919fef5107..869f0f1696 100644
--- a/meta/recipes-support/libsoup/libsoup_3.0.7.bb
+++ b/meta/recipes-support/libsoup/libsoup_3.0.7.bb
@@ -15,6 +15,9 @@ SRC_URI = "${GNOME_MIRROR}/libsoup/${SHRT_VER}/libsoup-${PV}.tar.xz \
file://CVE-2024-52530.patch \
file://CVE-2024-52532-1.patch \
file://CVE-2024-52532-2.patch \
+ file://CVE-2024-52531-1.patch \
+ file://CVE-2024-52531-2.patch \
+ file://CVE-2024-52531-3.patch \
"
SRC_URI[sha256sum] = "ebdf90cf3599c11acbb6818a9d9e3fc9d2c68e56eb829b93962972683e1bf7c8"
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 15/38] python3-zipp: fix CVE-2024-5569
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (13 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 14/38] libsoup: fix CVE-2024-52531 Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 16/38] libsoup-2.4: Backport fix for CVE-2024-52531 Steve Sakoman
` (22 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Hongxu Jia <hongxu.jia@windriver.com>
According to [1] which provided the fix link [2], but upstream author
reworked it later [3][4][5]
Backport and rebase all the patches for tracing
[1] https://nvd.nist.gov/vuln/detail/CVE-2024-5569
[2] https://github.com/jaraco/zipp/commit/fd604bd34f0343472521a36da1fbd22e793e14fd
[3] https://github.com/jaraco/zipp/commit/3cb5609002263eb19f7b5efda82d96f1f57fe876
[4] https://github.com/jaraco/zipp/commit/f89b93f0370dd85d23d243e25dfc1f99f4d8de48
[5] https://github.com/jaraco/zipp/commit/cc61e6140f0dfde2ff372db932442cf6df890f09
Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
---
.../0001-Add-SanitizedNames-mixin.patch | 89 +++++++++++++++++
...Names-in-CompleteDirs.-Fixes-broken-.patch | 30 ++++++
.../0003-Removed-SanitizedNames.patch | 95 +++++++++++++++++++
...-loop-when-zipfile-begins-with-more-.patch | 48 ++++++++++
...ath.rstrip-to-consolidate-checks-for.patch | 30 ++++++
.../python/python3-zipp_3.7.0.bb | 8 ++
6 files changed, 300 insertions(+)
create mode 100644 meta/recipes-devtools/python/python3-zipp/0001-Add-SanitizedNames-mixin.patch
create mode 100644 meta/recipes-devtools/python/python3-zipp/0002-Employ-SanitizedNames-in-CompleteDirs.-Fixes-broken-.patch
create mode 100644 meta/recipes-devtools/python/python3-zipp/0003-Removed-SanitizedNames.patch
create mode 100644 meta/recipes-devtools/python/python3-zipp/0004-Address-infinite-loop-when-zipfile-begins-with-more-.patch
create mode 100644 meta/recipes-devtools/python/python3-zipp/0005-Prefer-simpler-path.rstrip-to-consolidate-checks-for.patch
diff --git a/meta/recipes-devtools/python/python3-zipp/0001-Add-SanitizedNames-mixin.patch b/meta/recipes-devtools/python/python3-zipp/0001-Add-SanitizedNames-mixin.patch
new file mode 100644
index 0000000000..a352e7b9bd
--- /dev/null
+++ b/meta/recipes-devtools/python/python3-zipp/0001-Add-SanitizedNames-mixin.patch
@@ -0,0 +1,89 @@
+From ef2227e35d1ae833b7bfa1674a45f58c732ae1a6 Mon Sep 17 00:00:00 2001
+From: "Jason R. Coombs" <jaraco@jaraco.com>
+Date: Wed, 27 Nov 2024 23:27:57 -0800
+Subject: [PATCH 1/5] Add SanitizedNames mixin.
+
+Upstream-Status: Backport [https://github.com/jaraco/zipp/commit/564fcc10cdbfdaecdb33688e149827465931c9e0]
+CVE: CVE-2024-5569
+Rebase to v3.7.0
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+---
+ zipp.py | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 62 insertions(+)
+
+diff --git a/zipp.py b/zipp.py
+index 26b723c..8f0950f 100644
+--- a/zipp.py
++++ b/zipp.py
+@@ -68,6 +68,68 @@ def _difference(minuend, subtrahend):
+ return itertools.filterfalse(set(subtrahend).__contains__, minuend)
+
+
++class SanitizedNames:
++ """
++ ZipFile mix-in to ensure names are sanitized.
++ """
++
++ def namelist(self):
++ return list(map(self._sanitize, super().namelist()))
++
++ @staticmethod
++ def _sanitize(name):
++ r"""
++ Ensure a relative path with posix separators and no dot names.
++
++ Modeled after
++ https://github.com/python/cpython/blob/bcc1be39cb1d04ad9fc0bd1b9193d3972835a57c/Lib/zipfile/__init__.py#L1799-L1813
++ but provides consistent cross-platform behavior.
++
++ >>> san = SanitizedNames._sanitize
++ >>> san('/foo/bar')
++ 'foo/bar'
++ >>> san('//foo.txt')
++ 'foo.txt'
++ >>> san('foo/.././bar.txt')
++ 'foo/bar.txt'
++ >>> san('foo../.bar.txt')
++ 'foo../.bar.txt'
++ >>> san('\\foo\\bar.txt')
++ 'foo/bar.txt'
++ >>> san('D:\\foo.txt')
++ 'D/foo.txt'
++ >>> san('\\\\server\\share\\file.txt')
++ 'server/share/file.txt'
++ >>> san('\\\\?\\GLOBALROOT\\Volume3')
++ '?/GLOBALROOT/Volume3'
++ >>> san('\\\\.\\PhysicalDrive1\\root')
++ 'PhysicalDrive1/root'
++
++ Retain any trailing slash.
++ >>> san('abc/')
++ 'abc/'
++
++ Raises a ValueError if the result is empty.
++ >>> san('../..')
++ Traceback (most recent call last):
++ ...
++ ValueError: Empty filename
++ """
++
++ def allowed(part):
++ return part and part not in {'..', '.'}
++
++ # Remove the drive letter.
++ # Don't use ntpath.splitdrive, because that also strips UNC paths
++ bare = re.sub('^([A-Z]):', r'\1', name, flags=re.IGNORECASE)
++ clean = bare.replace('\\', '/')
++ parts = clean.split('/')
++ joined = '/'.join(filter(allowed, parts))
++ if not joined:
++ raise ValueError("Empty filename")
++ return joined + '/' * name.endswith('/')
++
++
+ class CompleteDirs(zipfile.ZipFile):
+ """
+ A ZipFile subclass that ensures that implied directories
+--
+2.25.1
+
diff --git a/meta/recipes-devtools/python/python3-zipp/0002-Employ-SanitizedNames-in-CompleteDirs.-Fixes-broken-.patch b/meta/recipes-devtools/python/python3-zipp/0002-Employ-SanitizedNames-in-CompleteDirs.-Fixes-broken-.patch
new file mode 100644
index 0000000000..d2ea4d49a1
--- /dev/null
+++ b/meta/recipes-devtools/python/python3-zipp/0002-Employ-SanitizedNames-in-CompleteDirs.-Fixes-broken-.patch
@@ -0,0 +1,30 @@
+From 8b09dbf95b3ba78a63f220941e31ac92f4ad192c Mon Sep 17 00:00:00 2001
+From: "Jason R. Coombs" <jaraco@jaraco.com>
+Date: Wed, 27 Nov 2024 23:31:57 -0800
+Subject: [PATCH 2/5] Employ SanitizedNames in CompleteDirs. Fixes broken test.
+
+Upstream-Status: Backport [https://github.com/jaraco/zipp/commit/58115d2be968644ce71ce6bcc9b79826c82a1806]
+Remove test code
+Rebase to v3.7.0
+CVE: CVE-2024-5569
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+---
+ zipp.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/zipp.py b/zipp.py
+index 8f0950f..29d2572 100644
+--- a/zipp.py
++++ b/zipp.py
+@@ -130,7 +130,7 @@ class SanitizedNames:
+ return joined + '/' * name.endswith('/')
+
+
+-class CompleteDirs(zipfile.ZipFile):
++class CompleteDirs(SanitizedNames, zipfile.ZipFile):
+ """
+ A ZipFile subclass that ensures that implied directories
+ are always included in the namelist.
+--
+2.25.1
+
diff --git a/meta/recipes-devtools/python/python3-zipp/0003-Removed-SanitizedNames.patch b/meta/recipes-devtools/python/python3-zipp/0003-Removed-SanitizedNames.patch
new file mode 100644
index 0000000000..45a7dc5bb1
--- /dev/null
+++ b/meta/recipes-devtools/python/python3-zipp/0003-Removed-SanitizedNames.patch
@@ -0,0 +1,95 @@
+From b52b8af403e64607ae8d5e4cd18d4099d63e7264 Mon Sep 17 00:00:00 2001
+From: "Jason R. Coombs" <jaraco@jaraco.com>
+Date: Wed, 27 Nov 2024 23:33:11 -0800
+Subject: [PATCH 3/5] Removed SanitizedNames.
+
+Restores expectations around special characters in zipfiles, but also restores the infinite loop.
+
+Upstream-Status: Backport [https://github.com/jaraco/zipp/commit/3cb5609002263eb19f7b5efda82d96f1f57fe876]
+Remove test codes
+Rebase to v3.7.0
+CVE: CVE-2024-5569
+
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+---
+ zipp.py | 64 +--------------------------------------------------------
+ 1 file changed, 1 insertion(+), 63 deletions(-)
+
+diff --git a/zipp.py b/zipp.py
+index 29d2572..26b723c 100644
+--- a/zipp.py
++++ b/zipp.py
+@@ -68,69 +68,7 @@ def _difference(minuend, subtrahend):
+ return itertools.filterfalse(set(subtrahend).__contains__, minuend)
+
+
+-class SanitizedNames:
+- """
+- ZipFile mix-in to ensure names are sanitized.
+- """
+-
+- def namelist(self):
+- return list(map(self._sanitize, super().namelist()))
+-
+- @staticmethod
+- def _sanitize(name):
+- r"""
+- Ensure a relative path with posix separators and no dot names.
+-
+- Modeled after
+- https://github.com/python/cpython/blob/bcc1be39cb1d04ad9fc0bd1b9193d3972835a57c/Lib/zipfile/__init__.py#L1799-L1813
+- but provides consistent cross-platform behavior.
+-
+- >>> san = SanitizedNames._sanitize
+- >>> san('/foo/bar')
+- 'foo/bar'
+- >>> san('//foo.txt')
+- 'foo.txt'
+- >>> san('foo/.././bar.txt')
+- 'foo/bar.txt'
+- >>> san('foo../.bar.txt')
+- 'foo../.bar.txt'
+- >>> san('\\foo\\bar.txt')
+- 'foo/bar.txt'
+- >>> san('D:\\foo.txt')
+- 'D/foo.txt'
+- >>> san('\\\\server\\share\\file.txt')
+- 'server/share/file.txt'
+- >>> san('\\\\?\\GLOBALROOT\\Volume3')
+- '?/GLOBALROOT/Volume3'
+- >>> san('\\\\.\\PhysicalDrive1\\root')
+- 'PhysicalDrive1/root'
+-
+- Retain any trailing slash.
+- >>> san('abc/')
+- 'abc/'
+-
+- Raises a ValueError if the result is empty.
+- >>> san('../..')
+- Traceback (most recent call last):
+- ...
+- ValueError: Empty filename
+- """
+-
+- def allowed(part):
+- return part and part not in {'..', '.'}
+-
+- # Remove the drive letter.
+- # Don't use ntpath.splitdrive, because that also strips UNC paths
+- bare = re.sub('^([A-Z]):', r'\1', name, flags=re.IGNORECASE)
+- clean = bare.replace('\\', '/')
+- parts = clean.split('/')
+- joined = '/'.join(filter(allowed, parts))
+- if not joined:
+- raise ValueError("Empty filename")
+- return joined + '/' * name.endswith('/')
+-
+-
+-class CompleteDirs(SanitizedNames, zipfile.ZipFile):
++class CompleteDirs(zipfile.ZipFile):
+ """
+ A ZipFile subclass that ensures that implied directories
+ are always included in the namelist.
+--
+2.25.1
+
diff --git a/meta/recipes-devtools/python/python3-zipp/0004-Address-infinite-loop-when-zipfile-begins-with-more-.patch b/meta/recipes-devtools/python/python3-zipp/0004-Address-infinite-loop-when-zipfile-begins-with-more-.patch
new file mode 100644
index 0000000000..46871122a9
--- /dev/null
+++ b/meta/recipes-devtools/python/python3-zipp/0004-Address-infinite-loop-when-zipfile-begins-with-more-.patch
@@ -0,0 +1,48 @@
+From ef4ee19919bd49a9c1207ff8d87f83dd48aed436 Mon Sep 17 00:00:00 2001
+From: "Jason R. Coombs" <jaraco@jaraco.com>
+Date: Wed, 27 Nov 2024 23:35:28 -0800
+Subject: [PATCH 4/5] Address infinite loop when zipfile begins with more than
+ one leading slash.
+
+Alternate and more surgical fix for jaraco/zipp#119. Ref python/cpython#123270
+
+Upstream-Status: Backport [https://github.com/jaraco/zipp/commit/f89b93f0370dd85d23d243e25dfc1f99f4d8de48]
+Remove test codes
+Rebase to v3.7.0
+CVE: CVE-2024-5569
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+---
+ zipp.py | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/zipp.py b/zipp.py
+index 26b723c..236af49 100644
+--- a/zipp.py
++++ b/zipp.py
+@@ -37,7 +37,7 @@ def _parents(path):
+ def _ancestry(path):
+ """
+ Given a path with elements separated by
+- posixpath.sep, generate all elements of that path
++ posixpath.sep, generate all elements of that path.
+
+ >>> list(_ancestry('b/d'))
+ ['b/d', 'b']
+@@ -49,9 +49,13 @@ def _ancestry(path):
+ ['b']
+ >>> list(_ancestry(''))
+ []
++ Multiple separators are treated like a single.
++
++ >>> list(_ancestry('//b//d///f//'))
++ ['//b//d///f', '//b//d', '//b']
+ """
+ path = path.rstrip(posixpath.sep)
+- while path and path != posixpath.sep:
++ while path and not path.endswith(posixpath.sep):
+ yield path
+ path, tail = posixpath.split(path)
+
+--
+2.25.1
+
diff --git a/meta/recipes-devtools/python/python3-zipp/0005-Prefer-simpler-path.rstrip-to-consolidate-checks-for.patch b/meta/recipes-devtools/python/python3-zipp/0005-Prefer-simpler-path.rstrip-to-consolidate-checks-for.patch
new file mode 100644
index 0000000000..de91c68361
--- /dev/null
+++ b/meta/recipes-devtools/python/python3-zipp/0005-Prefer-simpler-path.rstrip-to-consolidate-checks-for.patch
@@ -0,0 +1,30 @@
+From 9084bc59784cb240628996c1cb95f4f786ebedcc Mon Sep 17 00:00:00 2001
+From: "Jason R. Coombs" <jaraco@jaraco.com>
+Date: Wed, 27 Nov 2024 23:38:28 -0800
+Subject: [PATCH 5/5] Prefer simpler path.rstrip to consolidate checks for
+ empty or only paths.
+
+Upstream-Status: Backport [https://github.com/jaraco/zipp/commit/cc61e6140f0dfde2ff372db932442cf6df890f09]
+Rebase to v3.7.0
+CVE: CVE-2024-5569
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+---
+ zipp.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/zipp.py b/zipp.py
+index 236af49..87c4219 100644
+--- a/zipp.py
++++ b/zipp.py
+@@ -55,7 +55,7 @@ def _ancestry(path):
+ ['//b//d///f', '//b//d', '//b']
+ """
+ path = path.rstrip(posixpath.sep)
+- while path and not path.endswith(posixpath.sep):
++ while path.rstrip(posixpath.sep):
+ yield path
+ path, tail = posixpath.split(path)
+
+--
+2.25.1
+
diff --git a/meta/recipes-devtools/python/python3-zipp_3.7.0.bb b/meta/recipes-devtools/python/python3-zipp_3.7.0.bb
index 495e7f51f0..d9db1b4408 100644
--- a/meta/recipes-devtools/python/python3-zipp_3.7.0.bb
+++ b/meta/recipes-devtools/python/python3-zipp_3.7.0.bb
@@ -9,6 +9,14 @@ DEPENDS += "${PYTHON_PN}-setuptools-scm-native"
inherit pypi python_setuptools_build_meta
+SRC_URI += " \
+ file://0001-Add-SanitizedNames-mixin.patch \
+ file://0002-Employ-SanitizedNames-in-CompleteDirs.-Fixes-broken-.patch \
+ file://0003-Removed-SanitizedNames.patch \
+ file://0004-Address-infinite-loop-when-zipfile-begins-with-more-.patch \
+ file://0005-Prefer-simpler-path.rstrip-to-consolidate-checks-for.patch \
+"
+
DEPENDS += "${PYTHON_PN}-toml-native"
RDEPENDS:${PN} += "${PYTHON_PN}-compression \
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 16/38] libsoup-2.4: Backport fix for CVE-2024-52531
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (14 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 15/38] python3-zipp: fix CVE-2024-5569 Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 17/38] cpio: ignore CVE-2023-7216 Steve Sakoman
` (21 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Vijay Anusuri <vanusuri@mvista.com>
import patch from ubuntu to fix
CVE-2024-52531
Upstream-Status: Backport [import from ubuntu https://git.launchpad.net/ubuntu/+source/libsoup2.4/tree/debian/patches?h=ubuntu/jammy-security
Upstream commit
https://gitlab.gnome.org/GNOME/libsoup/-/commit/a35222dd0bfab2ac97c10e86b95f762456628283
&
https://gitlab.gnome.org/GNOME/libsoup/-/commit/825fda3425546847b42ad5270544e9388ff349fe]
Reference:
https://gitlab.gnome.org/GNOME/libsoup/-/merge_requests/407/
https://ubuntu.com/security/CVE-2024-52531
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
---
.../libsoup-2.4/CVE-2024-52531-1.patch | 131 ++++++++++++++++++
.../libsoup-2.4/CVE-2024-52531-2.patch | 36 +++++
.../libsoup/libsoup-2.4_2.74.2.bb | 2 +
3 files changed, 169 insertions(+)
create mode 100644 meta/recipes-support/libsoup/libsoup-2.4/CVE-2024-52531-1.patch
create mode 100644 meta/recipes-support/libsoup/libsoup-2.4/CVE-2024-52531-2.patch
diff --git a/meta/recipes-support/libsoup/libsoup-2.4/CVE-2024-52531-1.patch b/meta/recipes-support/libsoup/libsoup-2.4/CVE-2024-52531-1.patch
new file mode 100644
index 0000000000..d56ad0ff5e
--- /dev/null
+++ b/meta/recipes-support/libsoup/libsoup-2.4/CVE-2024-52531-1.patch
@@ -0,0 +1,131 @@
+From a35222dd0bfab2ac97c10e86b95f762456628283 Mon Sep 17 00:00:00 2001
+From: Patrick Griffis <pgriffis@igalia.com>
+Date: Tue, 27 Aug 2024 13:53:26 -0500
+Subject: [PATCH 1/2] headers: Be more robust against invalid input when
+ parsing params
+
+If you pass invalid input to a function such as soup_header_parse_param_list_strict()
+it can cause an overflow if it decodes the input to UTF-8.
+
+This should never happen with valid UTF-8 input which libsoup's client API
+ensures, however it's server API does not currently.
+
+Upstream-Status: Backport [import from ubuntu https://git.launchpad.net/ubuntu/+source/libsoup2.4/tree/debian/patches/CVE-2024-52531-1.patch?h=ubuntu/jammy-security
+Upstream commit https://gitlab.gnome.org/GNOME/libsoup/-/commit/a35222dd0bfab2ac97c10e86b95f762456628283]
+CVE: CVE-2024-52531
+Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
+---
+ libsoup/soup-headers.c | 46 ++++++++++++++++++++++--------------------
+ 1 file changed, 24 insertions(+), 22 deletions(-)
+
+Index: libsoup2.4-2.74.2/libsoup/soup-headers.c
+===================================================================
+--- libsoup2.4-2.74.2.orig/libsoup/soup-headers.c
++++ libsoup2.4-2.74.2/libsoup/soup-headers.c
+@@ -643,8 +643,9 @@ soup_header_contains (const char *header
+ }
+
+ static void
+-decode_quoted_string (char *quoted_string)
++decode_quoted_string_inplace (GString *quoted_gstring)
+ {
++ char *quoted_string = quoted_gstring->str;
+ char *src, *dst;
+
+ src = quoted_string + 1;
+@@ -658,10 +659,11 @@ decode_quoted_string (char *quoted_strin
+ }
+
+ static gboolean
+-decode_rfc5987 (char *encoded_string)
++decode_rfc5987_inplace (GString *encoded_gstring)
+ {
+ char *q, *decoded;
+ gboolean iso_8859_1 = FALSE;
++ const char *encoded_string = encoded_gstring->str;
+
+ q = strchr (encoded_string, '\'');
+ if (!q)
+@@ -690,14 +692,7 @@ decode_rfc5987 (char *encoded_string)
+ decoded = utf8;
+ }
+
+- /* If encoded_string was UTF-8, then each 3-character %-escape
+- * will be converted to a single byte, and so decoded is
+- * shorter than encoded_string. If encoded_string was
+- * iso-8859-1, then each 3-character %-escape will be
+- * converted into at most 2 bytes in UTF-8, and so it's still
+- * shorter.
+- */
+- strcpy (encoded_string, decoded);
++ g_string_assign (encoded_gstring, decoded);
+ g_free (decoded);
+ return TRUE;
+ }
+@@ -707,15 +702,17 @@ parse_param_list (const char *header, ch
+ {
+ GHashTable *params;
+ GSList *list, *iter;
+- char *item, *eq, *name_end, *value;
+- gboolean override, duplicated;
+
+ params = g_hash_table_new_full (soup_str_case_hash,
+ soup_str_case_equal,
+- g_free, NULL);
++ g_free, g_free);
+
+ list = parse_list (header, delim);
+ for (iter = list; iter; iter = iter->next) {
++ char *item, *eq, *name_end;
++ gboolean override, duplicated;
++ GString *parsed_value = NULL;
++
+ item = iter->data;
+ override = FALSE;
+
+@@ -730,19 +727,19 @@ parse_param_list (const char *header, ch
+
+ *name_end = '\0';
+
+- value = (char *)skip_lws (eq + 1);
++ parsed_value = g_string_new ((char *)skip_lws (eq + 1));
+
+ if (name_end[-1] == '*' && name_end > item + 1) {
+ name_end[-1] = '\0';
+- if (!decode_rfc5987 (value)) {
++ if (!decode_rfc5987_inplace (parsed_value)) {
++ g_string_free (parsed_value, TRUE);
+ g_free (item);
+ continue;
+ }
+ override = TRUE;
+- } else if (*value == '"')
+- decode_quoted_string (value);
+- } else
+- value = NULL;
++ } else if (parsed_value->str[0] == '"')
++ decode_quoted_string_inplace (parsed_value);
++ }
+
+ duplicated = g_hash_table_lookup_extended (params, item, NULL, NULL);
+
+@@ -750,11 +747,16 @@ parse_param_list (const char *header, ch
+ soup_header_free_param_list (params);
+ params = NULL;
+ g_slist_foreach (iter, (GFunc)g_free, NULL);
++ if (parsed_value)
++ g_string_free (parsed_value, TRUE);
+ break;
+- } else if (override || !duplicated)
+- g_hash_table_replace (params, item, value);
+- else
++ } else if (override || !duplicated) {
++ g_hash_table_replace (params, item, parsed_value ? g_string_free (parsed_value, FALSE) : NULL);
++ } else {
++ if (parsed_value)
++ g_string_free (parsed_value, TRUE);
+ g_free (item);
++ }
+ }
+
+ g_slist_free (list);
diff --git a/meta/recipes-support/libsoup/libsoup-2.4/CVE-2024-52531-2.patch b/meta/recipes-support/libsoup/libsoup-2.4/CVE-2024-52531-2.patch
new file mode 100644
index 0000000000..19b1872866
--- /dev/null
+++ b/meta/recipes-support/libsoup/libsoup-2.4/CVE-2024-52531-2.patch
@@ -0,0 +1,36 @@
+From 825fda3425546847b42ad5270544e9388ff349fe Mon Sep 17 00:00:00 2001
+From: Patrick Griffis <pgriffis@igalia.com>
+Date: Tue, 27 Aug 2024 13:52:08 -0500
+Subject: [PATCH 2/2] tests: Add test for passing invalid UTF-8 to
+ soup_header_parse_semi_param_list()
+
+Upstream-Status: Backport [import from ubuntu https://git.launchpad.net/ubuntu/+source/libsoup2.4/tree/debian/patches/CVE-2024-52531-2.patch?h=ubuntu/jammy-security
+Upstream commit https://gitlab.gnome.org/GNOME/libsoup/-/commit/825fda3425546847b42ad5270544e9388ff349fe]
+CVE: CVE-2024-52531
+Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
+---
+ tests/header-parsing-test.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+Index: libsoup2.4-2.74.2/tests/header-parsing-test.c
+===================================================================
+--- libsoup2.4-2.74.2.orig/tests/header-parsing-test.c
++++ libsoup2.4-2.74.2/tests/header-parsing-test.c
+@@ -825,6 +825,17 @@ static struct ParamListTest {
+ { "filename", "t\xC3\xA9st.txt" },
+ },
+ },
++
++ /* This tests invalid UTF-8 data which *should* never be passed here but it was designed to be robust against it. */
++ { TRUE,
++ "invalid*=\x69\x27\x27\x93\x93\x93\x93\xff\x61\x61\x61\x61\x61\x61\x61\x62\x63\x64\x65\x0a; filename*=iso-8859-1''\x69\x27\x27\x93\x93\x93\x93\xff\x61\x61\x61\x61\x61\x61\x61\x62\x63\x64\x65\x0a; foo",
++ {
++ { "filename", "i''\302\223\302\223\302\223\302\223\303\277aaaaaaabcde" },
++ { "invalid", "\302\223\302\223\302\223\302\223\303\277aaaaaaabcde" },
++ { "foo", NULL },
++
++ },
++ }
+ };
+ static const int num_paramlisttests = G_N_ELEMENTS (paramlisttests);
+
diff --git a/meta/recipes-support/libsoup/libsoup-2.4_2.74.2.bb b/meta/recipes-support/libsoup/libsoup-2.4_2.74.2.bb
index b1962961ce..88d08ad0ec 100644
--- a/meta/recipes-support/libsoup/libsoup-2.4_2.74.2.bb
+++ b/meta/recipes-support/libsoup/libsoup-2.4_2.74.2.bb
@@ -16,6 +16,8 @@ SRC_URI = "${GNOME_MIRROR}/libsoup/${SHRT_VER}/libsoup-${PV}.tar.xz \
file://CVE-2024-52530.patch \
file://CVE-2024-52532-1.patch \
file://CVE-2024-52532-2.patch \
+ file://CVE-2024-52531-1.patch \
+ file://CVE-2024-52531-2.patch \
"
SRC_URI[sha256sum] = "f0a427656e5fe19e1df71c107e88dfa1b2e673c25c547b7823b6018b40d01159"
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 17/38] cpio: ignore CVE-2023-7216
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (15 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 16/38] libsoup-2.4: Backport fix for CVE-2024-52531 Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 18/38] gnupg: ignore CVE-2022-3515 Steve Sakoman
` (20 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Peter Marko <peter.marko@siemens.com>
Same was done in newer Yocto releases.
See commit See commit 0f2cd2bbaddba3b8c80d71db274bbcd941d0e60e
Signed-off-by: Peter Marko <peter.marko@siemens.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
---
meta/recipes-extended/cpio/cpio_2.14.bb | 2 ++
1 file changed, 2 insertions(+)
diff --git a/meta/recipes-extended/cpio/cpio_2.14.bb b/meta/recipes-extended/cpio/cpio_2.14.bb
index c0b97ee166..0fbab82cca 100644
--- a/meta/recipes-extended/cpio/cpio_2.14.bb
+++ b/meta/recipes-extended/cpio/cpio_2.14.bb
@@ -16,6 +16,8 @@ inherit autotools gettext texinfo
# Issue applies to use of cpio in SUSE/OBS, doesn't apply to us
CVE_CHECK_IGNORE += "CVE-2010-4226"
+# disputed: intended behaviour, see https://lists.gnu.org/archive/html/bug-cpio/2024-03/msg00000.html
+CVE_CHECK_IGNORE += "CVE-2023-7216"
EXTRA_OECONF += "DEFAULT_RMT_DIR=${sbindir}"
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 18/38] gnupg: ignore CVE-2022-3515
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (16 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 17/38] cpio: ignore CVE-2023-7216 Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 19/38] qemu: ignore CVE-2022-36648 Steve Sakoman
` (19 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Peter Marko <peter.marko@siemens.com>
This is vulnerability of libksba and we use fixed libksba version
(currently 1.6.4).
Signed-off-by: Peter Marko <peter.marko@siemens.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
---
meta/recipes-support/gnupg/gnupg_2.3.7.bb | 2 ++
1 file changed, 2 insertions(+)
diff --git a/meta/recipes-support/gnupg/gnupg_2.3.7.bb b/meta/recipes-support/gnupg/gnupg_2.3.7.bb
index 7a29a5659a..7075a61898 100644
--- a/meta/recipes-support/gnupg/gnupg_2.3.7.bb
+++ b/meta/recipes-support/gnupg/gnupg_2.3.7.bb
@@ -87,3 +87,5 @@ lcl_maybe_fortify:mipsarch = ""
# upstream-wontfix: Upstream doesn't seem to be keen on merging the proposed commit - https://dev.gnupg.org/T5993
CVE_CHECK_IGNORE += "CVE-2022-3219"
+# cpe-incorrect: this is vulnerability of libksba and we use fixed libksba version
+CVE_CHECK_IGNORE += "CVE-2022-3515"
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 19/38] qemu: ignore CVE-2022-36648
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (17 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 18/38] gnupg: ignore CVE-2022-3515 Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 20/38] grub: ignore CVE-2024-1048 and CVE-2023-4001 Steve Sakoman
` (18 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Peter Marko <peter.marko@siemens.com>
The CVE has disputed flag in NVD DB.
Signed-off-by: Peter Marko <peter.marko@siemens.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
---
meta/recipes-devtools/qemu/qemu.inc | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/meta/recipes-devtools/qemu/qemu.inc b/meta/recipes-devtools/qemu/qemu.inc
index 1c0e8a93f1..cc78d7db06 100644
--- a/meta/recipes-devtools/qemu/qemu.inc
+++ b/meta/recipes-devtools/qemu/qemu.inc
@@ -148,6 +148,11 @@ CVE_CHECK_IGNORE += "CVE-2023-0664"
# RHEL specific issue
CVE_CHECK_IGNORE += "CVE-2023-2680"
+# The CVE has disputed flag in NVD DB and also descrition contains:
+# Note: This has been disputed by multiple third parties as not a valid vulnerability
+# due to the rocker device not falling within the virtualization use case.
+CVE_CHECK_IGNORE += "CVE-2022-36648"
+
COMPATIBLE_HOST:mipsarchn32 = "null"
COMPATIBLE_HOST:mipsarchn64 = "null"
COMPATIBLE_HOST:riscv32 = "null"
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 20/38] grub: ignore CVE-2024-1048 and CVE-2023-4001
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (18 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 19/38] qemu: ignore CVE-2022-36648 Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 21/38] pixman: ignore CVE-2023-37769 Steve Sakoman
` (17 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Peter Marko <peter.marko@siemens.com>
Same was done in newer Yocto releases.
See commit: f99b25355133fe8f65a55737270e67ea10b79d52
See commit: 40cd768368167f81de5bb55e9ff0584035f4c1b4
Signed-off-by: Peter Marko <peter.marko@siemens.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
---
meta/recipes-bsp/grub/grub2.inc | 2 ++
1 file changed, 2 insertions(+)
diff --git a/meta/recipes-bsp/grub/grub2.inc b/meta/recipes-bsp/grub/grub2.inc
index 2718379474..3e96426b82 100644
--- a/meta/recipes-bsp/grub/grub2.inc
+++ b/meta/recipes-bsp/grub/grub2.inc
@@ -49,6 +49,8 @@ SRC_URI[sha256sum] = "23b64b4c741569f9426ed2e3d0e6780796fca081bee4c99f62aa3f53ae
CVE_CHECK_IGNORE += "CVE-2019-14865"
# Applies only to SUSE
CVE_CHECK_IGNORE += "CVE-2021-46705"
+# not-applicable-platform: Applies only to RHEL/Fedora
+CVE_CHECK_IGNORE += "CVE-2024-1048 CVE-2023-4001"
DEPENDS = "flex-native bison-native gettext-native"
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 21/38] pixman: ignore CVE-2023-37769
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (19 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 20/38] grub: ignore CVE-2024-1048 and CVE-2023-4001 Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 22/38] qemu: patch CVE-2024-6505 Steve Sakoman
` (16 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Peter Marko <peter.marko@siemens.com>
Same was done in newer Yocto releases.
See commit 72f2d4cf44b795f766ecdee0b8362c7e162c5efc
Signed-off-by: Peter Marko <peter.marko@siemens.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
---
meta/recipes-graphics/xorg-lib/pixman_0.40.0.bb | 3 +++
1 file changed, 3 insertions(+)
diff --git a/meta/recipes-graphics/xorg-lib/pixman_0.40.0.bb b/meta/recipes-graphics/xorg-lib/pixman_0.40.0.bb
index 63fd6d2978..51728078fb 100644
--- a/meta/recipes-graphics/xorg-lib/pixman_0.40.0.bb
+++ b/meta/recipes-graphics/xorg-lib/pixman_0.40.0.bb
@@ -40,3 +40,6 @@ EXTRA_OEMESON:append:class-target:powerpc64 = " ${@bb.utils.contains("TUNE_FEATU
EXTRA_OEMESON:append:class-target:powerpc64le = " ${@bb.utils.contains("TUNE_FEATURES", "altivec", "-Dvmx=enabled", "-Dvmx=disabled", d)}"
BBCLASSEXTEND = "native nativesdk"
+
+# not-applicable-config: stress-test is an uninstalled test
+CVE_CHECK_IGNORE += "CVE-2023-37769"
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 22/38] qemu: patch CVE-2024-6505
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (20 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 21/38] pixman: ignore CVE-2023-37769 Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 23/38] qemu: fix CVE-2024-3446 Steve Sakoman
` (15 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Peter Marko <peter.marko@siemens.com>
Backport patch [3] as linked from [1] via [2].
[1] https://nvd.nist.gov/vuln/detail/CVE-2024-6505
[2] https://bugzilla.redhat.com/show_bug.cgi?id=2295760
[3] https://gitlab.com/qemu-project/qemu/-/commit/f1595ceb
Signed-off-by: Peter Marko <peter.marko@siemens.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
---
meta/recipes-devtools/qemu/qemu.inc | 1 +
.../qemu/qemu/CVE-2024-6505.patch | 40 +++++++++++++++++++
2 files changed, 41 insertions(+)
create mode 100644 meta/recipes-devtools/qemu/qemu/CVE-2024-6505.patch
diff --git a/meta/recipes-devtools/qemu/qemu.inc b/meta/recipes-devtools/qemu/qemu.inc
index cc78d7db06..a43785c79d 100644
--- a/meta/recipes-devtools/qemu/qemu.inc
+++ b/meta/recipes-devtools/qemu/qemu.inc
@@ -120,6 +120,7 @@ SRC_URI = "https://download.qemu.org/${BPN}-${PV}.tar.xz \
file://CVE-2024-4467-0005.patch \
file://CVE-2023-3019-0001.patch \
file://CVE-2023-3019-0002.patch \
+ file://CVE-2024-6505.patch \
"
UPSTREAM_CHECK_REGEX = "qemu-(?P<pver>\d+(\.\d+)+)\.tar"
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2024-6505.patch b/meta/recipes-devtools/qemu/qemu/CVE-2024-6505.patch
new file mode 100644
index 0000000000..f9ee36f8ed
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu/CVE-2024-6505.patch
@@ -0,0 +1,40 @@
+From f1595ceb9aad36a6c1da95bcb77ab9509b38822d Mon Sep 17 00:00:00 2001
+From: Akihiko Odaki <akihiko.odaki@daynix.com>
+Date: Mon, 1 Jul 2024 20:58:04 +0900
+Subject: [PATCH] virtio-net: Ensure queue index fits with RSS
+
+Ensure the queue index points to a valid queue when software RSS
+enabled. The new calculation matches with the behavior of Linux's TAP
+device with the RSS eBPF program.
+
+Fixes: 4474e37a5b3a ("virtio-net: implement RX RSS processing")
+Reported-by: Zhibin Hu <huzhibin5@huawei.com>
+Cc: qemu-stable@nongnu.org
+Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
+Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Jason Wang <jasowang@redhat.com>
+
+CVE: CVE-2024-6505
+Upstream-Status: Backport [https://gitlab.com/qemu-project/qemu/-/commit/f1595ceb9aad36a6c1da95bcb77ab9509b38822d]
+Signed-off-by: Peter Marko <peter.marko@siemens.com>
+---
+ hw/net/virtio-net.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
+index 8f30972708..5635620a31 100644
+--- a/hw/net/virtio-net.c
++++ b/hw/net/virtio-net.c
+@@ -1752,7 +1752,8 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
+ if (!no_rss && n->rss_data.enabled && n->rss_data.enabled_software_rss) {
+ int index = virtio_net_process_rss(nc, buf, size);
+ if (index >= 0) {
+- NetClientState *nc2 = qemu_get_subqueue(n->nic, index);
++ NetClientState *nc2 =
++ qemu_get_subqueue(n->nic, index % n->curr_queue_pairs);
+ return virtio_net_receive_rcu(nc2, buf, size, true);
+ }
+ }
+--
+2.30.2
+
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 23/38] qemu: fix CVE-2024-3446
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (21 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 22/38] qemu: patch CVE-2024-6505 Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 24/38] qemu: fix CVE-2024-3447 Steve Sakoman
` (14 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Divya Chellam <divya.chellam@windriver.com>
A double free vulnerability was found in QEMU virtio devices
(virtio-gpu, virtio-serial-bus, virtio-crypto), where the
mem_reentrancy_guard flag insufficiently protects against DMA
reentrancy issues. This issue could allow a malicious privileged
guest to crash the QEMU process on the host, resulting in a d
enial of service or allow arbitrary code execution within the
context of the QEMU process on the host.
CVE-2024-3446-0004, CVE-2024-3446-0005, CVE-2024-3446-0006
are CVE fix and CVE-2024-3446-0001, CVE-2024-3446-0002,
CVE-2024-3446-0003 are dependent commits to fix the CVE.
References:
https://nvd.nist.gov/vuln/detail/CVE-2024-3446
Upstream patches:
https://gitlab.com/qemu-project/qemu/-/commit/9c86c97f12c060bf7484dd931f38634e166a81f0
https://gitlab.com/qemu-project/qemu/-/commit/f63192b0544af5d3e4d5edfd85ab520fcf671377
https://gitlab.com/qemu-project/qemu/-/commit/ec0504b989ca61e03636384d3602b7bf07ffe4da
https://gitlab.com/qemu-project/qemu/-/commit/ba28e0ff4d95b56dc334aac2730ab3651ffc3132
https://gitlab.com/qemu-project/qemu/-/commit/b4295bff25f7b50de1d9cc94a9c6effd40056bca
https://gitlab.com/qemu-project/qemu/-/commit/f4729ec39ad97a42ceaa7b5697f84f440ea6e5dc
Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
---
meta/recipes-devtools/qemu/qemu.inc | 6 +
.../qemu/qemu/CVE-2024-3446-0001.patch | 218 +++++++++
.../qemu/qemu/CVE-2024-3446-0002.patch | 427 ++++++++++++++++++
.../qemu/qemu/CVE-2024-3446-0003.patch | 68 +++
.../qemu/qemu/CVE-2024-3446-0004.patch | 144 ++++++
.../qemu/qemu/CVE-2024-3446-0005.patch | 42 ++
.../qemu/qemu/CVE-2024-3446-0006.patch | 43 ++
7 files changed, 948 insertions(+)
create mode 100644 meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0001.patch
create mode 100644 meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0002.patch
create mode 100644 meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0003.patch
create mode 100644 meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0004.patch
create mode 100644 meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0005.patch
create mode 100644 meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0006.patch
diff --git a/meta/recipes-devtools/qemu/qemu.inc b/meta/recipes-devtools/qemu/qemu.inc
index a43785c79d..16eb30e572 100644
--- a/meta/recipes-devtools/qemu/qemu.inc
+++ b/meta/recipes-devtools/qemu/qemu.inc
@@ -121,6 +121,12 @@ SRC_URI = "https://download.qemu.org/${BPN}-${PV}.tar.xz \
file://CVE-2023-3019-0001.patch \
file://CVE-2023-3019-0002.patch \
file://CVE-2024-6505.patch \
+ file://CVE-2024-3446-0001.patch \
+ file://CVE-2024-3446-0002.patch \
+ file://CVE-2024-3446-0003.patch \
+ file://CVE-2024-3446-0004.patch \
+ file://CVE-2024-3446-0005.patch \
+ file://CVE-2024-3446-0006.patch \
"
UPSTREAM_CHECK_REGEX = "qemu-(?P<pver>\d+(\.\d+)+)\.tar"
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0001.patch b/meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0001.patch
new file mode 100644
index 0000000000..f33934bf85
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0001.patch
@@ -0,0 +1,218 @@
+From 9c86c97f12c060bf7484dd931f38634e166a81f0 Mon Sep 17 00:00:00 2001
+From: Alexander Bulekov <alxndr@bu.edu>
+Date: Mon, 27 May 2024 07:29:20 +0000
+Subject: [PATCH] async: Add an optional reentrancy guard to the BH API
+
+Devices can pass their MemoryReentrancyGuard (from their DeviceState),
+when creating new BHes. Then, the async API will toggle the guard
+before/after calling the BH call-back. This prevents bh->mmio reentrancy
+issues.
+
+Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
+Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
+Message-Id: <20230427211013.2994127-3-alxndr@bu.edu>
+[thuth: Fix "line over 90 characters" checkpatch.pl error]
+Signed-off-by: Thomas Huth <thuth@redhat.com>
+
+CVE: CVE-2024-3446
+Upstream-Status: Backport [https://gitlab.com/qemu-project/qemu/-/commit/9c86c97f12c060bf7484dd931f38634e166a81f0]
+
+Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
+---
+ docs/devel/multiple-iothreads.txt | 7 +++++++
+ include/block/aio.h | 18 ++++++++++++++++--
+ include/qemu/main-loop.h | 8 +++++---
+ tests/unit/ptimer-test-stubs.c | 3 ++-
+ util/async.c | 18 +++++++++++++++++-
+ util/main-loop.c | 6 ++++--
+ util/trace-events | 1 +
+ 7 files changed, 52 insertions(+), 9 deletions(-)
+
+diff --git a/docs/devel/multiple-iothreads.txt b/docs/devel/multiple-iothreads.txt
+index aeb997bed..a11576bc7 100644
+--- a/docs/devel/multiple-iothreads.txt
++++ b/docs/devel/multiple-iothreads.txt
+@@ -61,6 +61,7 @@ There are several old APIs that use the main loop AioContext:
+ * LEGACY qemu_aio_set_event_notifier() - monitor an event notifier
+ * LEGACY timer_new_ms() - create a timer
+ * LEGACY qemu_bh_new() - create a BH
++ * LEGACY qemu_bh_new_guarded() - create a BH with a device re-entrancy guard
+ * LEGACY qemu_aio_wait() - run an event loop iteration
+
+ Since they implicitly work on the main loop they cannot be used in code that
+@@ -72,8 +73,14 @@ Instead, use the AioContext functions directly (see include/block/aio.h):
+ * aio_set_event_notifier() - monitor an event notifier
+ * aio_timer_new() - create a timer
+ * aio_bh_new() - create a BH
++ * aio_bh_new_guarded() - create a BH with a device re-entrancy guard
+ * aio_poll() - run an event loop iteration
+
++The qemu_bh_new_guarded/aio_bh_new_guarded APIs accept a "MemReentrancyGuard"
++argument, which is used to check for and prevent re-entrancy problems. For
++BHs associated with devices, the reentrancy-guard is contained in the
++corresponding DeviceState and named "mem_reentrancy_guard".
++
+ The AioContext can be obtained from the IOThread using
+ iothread_get_aio_context() or for the main loop using qemu_get_aio_context().
+ Code that takes an AioContext argument works both in IOThreads or the main
+diff --git a/include/block/aio.h b/include/block/aio.h
+index 47fbe9d81..c7da15298 100644
+--- a/include/block/aio.h
++++ b/include/block/aio.h
+@@ -22,6 +22,8 @@
+ #include "qemu/event_notifier.h"
+ #include "qemu/thread.h"
+ #include "qemu/timer.h"
++#include "hw/qdev-core.h"
++
+
+ typedef struct BlockAIOCB BlockAIOCB;
+ typedef void BlockCompletionFunc(void *opaque, int ret);
+@@ -321,9 +323,11 @@ void aio_bh_schedule_oneshot_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque,
+ * is opaque and must be allocated prior to its use.
+ *
+ * @name: A human-readable identifier for debugging purposes.
++ * @reentrancy_guard: A guard set when entering a cb to prevent
++ * device-reentrancy issues
+ */
+ QEMUBH *aio_bh_new_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque,
+- const char *name);
++ const char *name, MemReentrancyGuard *reentrancy_guard);
+
+ /**
+ * aio_bh_new: Allocate a new bottom half structure
+@@ -332,7 +336,17 @@ QEMUBH *aio_bh_new_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque,
+ * string.
+ */
+ #define aio_bh_new(ctx, cb, opaque) \
+- aio_bh_new_full((ctx), (cb), (opaque), (stringify(cb)))
++ aio_bh_new_full((ctx), (cb), (opaque), (stringify(cb)), NULL)
++
++/**
++ * aio_bh_new_guarded: Allocate a new bottom half structure with a
++ * reentrancy_guard
++ *
++ * A convenience wrapper for aio_bh_new_full() that uses the cb as the name
++ * string.
++ */
++#define aio_bh_new_guarded(ctx, cb, opaque, guard) \
++ aio_bh_new_full((ctx), (cb), (opaque), (stringify(cb)), guard)
+
+ /**
+ * aio_notify: Force processing of pending events.
+diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h
+index 8dbc6fcb8..0a8f512be 100644
+--- a/include/qemu/main-loop.h
++++ b/include/qemu/main-loop.h
+@@ -293,10 +293,12 @@ void qemu_cond_timedwait_iothread(QemuCond *cond, int ms);
+ /* internal interfaces */
+
+ void qemu_fd_register(int fd);
+-
++#define qemu_bh_new_guarded(cb, opaque, guard) \
++ qemu_bh_new_full((cb), (opaque), (stringify(cb)), guard)
+ #define qemu_bh_new(cb, opaque) \
+- qemu_bh_new_full((cb), (opaque), (stringify(cb)))
+-QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name);
++ qemu_bh_new_full((cb), (opaque), (stringify(cb)), NULL)
++QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name,
++ MemReentrancyGuard *reentrancy_guard);
+ void qemu_bh_schedule_idle(QEMUBH *bh);
+
+ enum {
+diff --git a/tests/unit/ptimer-test-stubs.c b/tests/unit/ptimer-test-stubs.c
+index 2a3ef5879..a7a2d08e7 100644
+--- a/tests/unit/ptimer-test-stubs.c
++++ b/tests/unit/ptimer-test-stubs.c
+@@ -108,7 +108,8 @@ int64_t qemu_clock_deadline_ns_all(QEMUClockType type, int attr_mask)
+ return deadline;
+ }
+
+-QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name)
++QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name,
++ MemReentrancyGuard *reentrancy_guard)
+ {
+ QEMUBH *bh = g_new(QEMUBH, 1);
+
+diff --git a/util/async.c b/util/async.c
+index 6f6717a34..3eb6b5016 100644
+--- a/util/async.c
++++ b/util/async.c
+@@ -62,6 +62,7 @@ struct QEMUBH {
+ void *opaque;
+ QSLIST_ENTRY(QEMUBH) next;
+ unsigned flags;
++ MemReentrancyGuard *reentrancy_guard;
+ };
+
+ /* Called concurrently from any thread */
+@@ -123,7 +124,7 @@ void aio_bh_schedule_oneshot_full(AioContext *ctx, QEMUBHFunc *cb,
+ }
+
+ QEMUBH *aio_bh_new_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque,
+- const char *name)
++ const char *name, MemReentrancyGuard *reentrancy_guard)
+ {
+ QEMUBH *bh;
+ bh = g_new(QEMUBH, 1);
+@@ -132,13 +133,28 @@ QEMUBH *aio_bh_new_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque,
+ .cb = cb,
+ .opaque = opaque,
+ .name = name,
++ .reentrancy_guard = reentrancy_guard,
+ };
+ return bh;
+ }
+
+ void aio_bh_call(QEMUBH *bh)
+ {
++ bool last_engaged_in_io = false;
++
++ if (bh->reentrancy_guard) {
++ last_engaged_in_io = bh->reentrancy_guard->engaged_in_io;
++ if (bh->reentrancy_guard->engaged_in_io) {
++ trace_reentrant_aio(bh->ctx, bh->name);
++ }
++ bh->reentrancy_guard->engaged_in_io = true;
++ }
++
+ bh->cb(bh->opaque);
++
++ if (bh->reentrancy_guard) {
++ bh->reentrancy_guard->engaged_in_io = last_engaged_in_io;
++ }
+ }
+
+ /* Multiple occurrences of aio_bh_poll cannot be called concurrently. */
+diff --git a/util/main-loop.c b/util/main-loop.c
+index 06b18b195..1eacf0469 100644
+--- a/util/main-loop.c
++++ b/util/main-loop.c
+@@ -544,9 +544,11 @@ void main_loop_wait(int nonblocking)
+
+ /* Functions to operate on the main QEMU AioContext. */
+
+-QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name)
++QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name,
++ MemReentrancyGuard *reentrancy_guard)
+ {
+- return aio_bh_new_full(qemu_aio_context, cb, opaque, name);
++ return aio_bh_new_full(qemu_aio_context, cb, opaque, name,
++ reentrancy_guard);
+ }
+
+ /*
+diff --git a/util/trace-events b/util/trace-events
+index c8f53d7d9..dc3b1eb3b 100644
+--- a/util/trace-events
++++ b/util/trace-events
+@@ -11,6 +11,7 @@ poll_remove(void *ctx, void *node, int fd) "ctx %p node %p fd %d"
+ # async.c
+ aio_co_schedule(void *ctx, void *co) "ctx %p co %p"
+ aio_co_schedule_bh_cb(void *ctx, void *co) "ctx %p co %p"
++reentrant_aio(void *ctx, const char *name) "ctx %p name %s"
+
+ # thread-pool.c
+ thread_pool_submit(void *pool, void *req, void *opaque) "pool %p req %p opaque %p"
+--
+2.40.0
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0002.patch b/meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0002.patch
new file mode 100644
index 0000000000..68a6e737da
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0002.patch
@@ -0,0 +1,427 @@
+From f63192b0544af5d3e4d5edfd85ab520fcf671377 Mon Sep 17 00:00:00 2001
+From: Alexander Bulekov <alxndr@bu.edu>
+Date: Thu, 27 Apr 2023 17:10:09 -0400
+Subject: [PATCH] hw: replace most qemu_bh_new calls with qemu_bh_new_guarded
+
+This protects devices from bh->mmio reentrancy issues.
+
+Thanks: Thomas Huth <thuth@redhat.com> for diagnosing OS X test failure.
+Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
+Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
+Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
+Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
+Reviewed-by: Paul Durrant <paul@xen.org>
+Reviewed-by: Thomas Huth <thuth@redhat.com>
+Message-Id: <20230427211013.2994127-5-alxndr@bu.edu>
+Signed-off-by: Thomas Huth <thuth@redhat.com>
+
+CVE: CVE-2024-3446
+Upstream-Status: Backport [https://gitlab.com/qemu-project/qemu/-/commit/f63192b0544af5d3e4d5edfd85ab520fcf671377]
+
+Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
+---
+ hw/9pfs/xen-9p-backend.c | 5 ++++-
+ hw/block/dataplane/virtio-blk.c | 3 ++-
+ hw/block/dataplane/xen-block.c | 5 +++--
+ hw/char/virtio-serial-bus.c | 3 ++-
+ hw/display/qxl.c | 9 ++++++---
+ hw/display/virtio-gpu.c | 6 ++++--
+ hw/ide/ahci.c | 3 ++-
+ hw/ide/ahci_internal.h | 1 +
+ hw/ide/core.c | 4 +++-
+ hw/misc/imx_rngc.c | 6 ++++--
+ hw/misc/macio/mac_dbdma.c | 2 +-
+ hw/net/virtio-net.c | 3 ++-
+ hw/scsi/mptsas.c | 3 ++-
+ hw/scsi/scsi-bus.c | 3 ++-
+ hw/scsi/vmw_pvscsi.c | 3 ++-
+ hw/usb/dev-uas.c | 3 ++-
+ hw/usb/hcd-dwc2.c | 3 ++-
+ hw/usb/hcd-ehci.c | 3 ++-
+ hw/usb/hcd-uhci.c | 2 +-
+ hw/usb/host-libusb.c | 6 ++++--
+ hw/usb/redirect.c | 6 ++++--
+ hw/usb/xen-usb.c | 3 ++-
+ hw/virtio/virtio-balloon.c | 5 +++--
+ hw/virtio/virtio-crypto.c | 3 ++-
+ 24 files changed, 62 insertions(+), 31 deletions(-)
+
+diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c
+index 65c4979c3..09f7c1358 100644
+--- a/hw/9pfs/xen-9p-backend.c
++++ b/hw/9pfs/xen-9p-backend.c
+@@ -60,6 +60,7 @@ typedef struct Xen9pfsDev {
+
+ int num_rings;
+ Xen9pfsRing *rings;
++ MemReentrancyGuard mem_reentrancy_guard;
+ } Xen9pfsDev;
+
+ static void xen_9pfs_disconnect(struct XenLegacyDevice *xendev);
+@@ -441,7 +442,9 @@ static int xen_9pfs_connect(struct XenLegacyDevice *xendev)
+ xen_9pdev->rings[i].ring.out = xen_9pdev->rings[i].data +
+ XEN_FLEX_RING_SIZE(ring_order);
+
+- xen_9pdev->rings[i].bh = qemu_bh_new(xen_9pfs_bh, &xen_9pdev->rings[i]);
++ xen_9pdev->rings[i].bh = qemu_bh_new_guarded(xen_9pfs_bh,
++ &xen_9pdev->rings[i],
++ &xen_9pdev->mem_reentrancy_guard);
+ xen_9pdev->rings[i].out_cons = 0;
+ xen_9pdev->rings[i].out_size = 0;
+ xen_9pdev->rings[i].inprogress = false;
+diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
+index ee5a5352d..5f0de7da1 100644
+--- a/hw/block/dataplane/virtio-blk.c
++++ b/hw/block/dataplane/virtio-blk.c
+@@ -127,7 +127,8 @@ bool virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
+ } else {
+ s->ctx = qemu_get_aio_context();
+ }
+- s->bh = aio_bh_new(s->ctx, notify_guest_bh, s);
++ s->bh = aio_bh_new_guarded(s->ctx, notify_guest_bh, s,
++ &DEVICE(vdev)->mem_reentrancy_guard);
+ s->batch_notify_vqs = bitmap_new(conf->num_queues);
+
+ *dataplane = s;
+diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c
+index 860787580..07855feea 100644
+--- a/hw/block/dataplane/xen-block.c
++++ b/hw/block/dataplane/xen-block.c
+@@ -631,8 +631,9 @@ XenBlockDataPlane *xen_block_dataplane_create(XenDevice *xendev,
+ } else {
+ dataplane->ctx = qemu_get_aio_context();
+ }
+- dataplane->bh = aio_bh_new(dataplane->ctx, xen_block_dataplane_bh,
+- dataplane);
++ dataplane->bh = aio_bh_new_guarded(dataplane->ctx, xen_block_dataplane_bh,
++ dataplane,
++ &DEVICE(xendev)->mem_reentrancy_guard);
+
+ return dataplane;
+ }
+diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
+index f01ec2137..f18124b15 100644
+--- a/hw/char/virtio-serial-bus.c
++++ b/hw/char/virtio-serial-bus.c
+@@ -985,7 +985,8 @@ static void virtser_port_device_realize(DeviceState *dev, Error **errp)
+ return;
+ }
+
+- port->bh = qemu_bh_new(flush_queued_data_bh, port);
++ port->bh = qemu_bh_new_guarded(flush_queued_data_bh, port,
++ &dev->mem_reentrancy_guard);
+ port->elem = NULL;
+ }
+
+diff --git a/hw/display/qxl.c b/hw/display/qxl.c
+index 2a4b2d415..585254fc7 100644
+--- a/hw/display/qxl.c
++++ b/hw/display/qxl.c
+@@ -2205,11 +2205,14 @@ static void qxl_realize_common(PCIQXLDevice *qxl, Error **errp)
+
+ qemu_add_vm_change_state_handler(qxl_vm_change_state_handler, qxl);
+
+- qxl->update_irq = qemu_bh_new(qxl_update_irq_bh, qxl);
++ qxl->update_irq = qemu_bh_new_guarded(qxl_update_irq_bh, qxl,
++ &DEVICE(qxl)->mem_reentrancy_guard);
+ qxl_reset_state(qxl);
+
+- qxl->update_area_bh = qemu_bh_new(qxl_render_update_area_bh, qxl);
+- qxl->ssd.cursor_bh = qemu_bh_new(qemu_spice_cursor_refresh_bh, &qxl->ssd);
++ qxl->update_area_bh = qemu_bh_new_guarded(qxl_render_update_area_bh, qxl,
++ &DEVICE(qxl)->mem_reentrancy_guard);
++ qxl->ssd.cursor_bh = qemu_bh_new_guarded(qemu_spice_cursor_refresh_bh, &qxl->ssd,
++ &DEVICE(qxl)->mem_reentrancy_guard);
+ }
+
+ static void qxl_realize_primary(PCIDevice *dev, Error **errp)
+diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
+index c6dc81898..316469ab7 100644
+--- a/hw/display/virtio-gpu.c
++++ b/hw/display/virtio-gpu.c
+@@ -1334,8 +1334,10 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
+
+ g->ctrl_vq = virtio_get_queue(vdev, 0);
+ g->cursor_vq = virtio_get_queue(vdev, 1);
+- g->ctrl_bh = qemu_bh_new(virtio_gpu_ctrl_bh, g);
+- g->cursor_bh = qemu_bh_new(virtio_gpu_cursor_bh, g);
++ g->ctrl_bh = qemu_bh_new_guarded(virtio_gpu_ctrl_bh, g,
++ &qdev->mem_reentrancy_guard);
++ g->cursor_bh = qemu_bh_new_guarded(virtio_gpu_cursor_bh, g,
++ &qdev->mem_reentrancy_guard);
+ QTAILQ_INIT(&g->reslist);
+ QTAILQ_INIT(&g->cmdq);
+ QTAILQ_INIT(&g->fenceq);
+diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
+index 205dfdc66..f77d0faf0 100644
+--- a/hw/ide/ahci.c
++++ b/hw/ide/ahci.c
+@@ -1508,7 +1508,8 @@ static void ahci_cmd_done(const IDEDMA *dma)
+ ahci_write_fis_d2h(ad);
+
+ if (ad->port_regs.cmd_issue && !ad->check_bh) {
+- ad->check_bh = qemu_bh_new(ahci_check_cmd_bh, ad);
++ ad->check_bh = qemu_bh_new_guarded(ahci_check_cmd_bh, ad,
++ &ad->mem_reentrancy_guard);
+ qemu_bh_schedule(ad->check_bh);
+ }
+ }
+diff --git a/hw/ide/ahci_internal.h b/hw/ide/ahci_internal.h
+index 109de9e2d..a7768dd69 100644
+--- a/hw/ide/ahci_internal.h
++++ b/hw/ide/ahci_internal.h
+@@ -321,6 +321,7 @@ struct AHCIDevice {
+ bool init_d2h_sent;
+ AHCICmdHdr *cur_cmd;
+ NCQTransferState ncq_tfs[AHCI_MAX_CMDS];
++ MemReentrancyGuard mem_reentrancy_guard;
+ };
+
+ struct AHCIPCIState {
+diff --git a/hw/ide/core.c b/hw/ide/core.c
+index 63998410a..0416f45a6 100644
+--- a/hw/ide/core.c
++++ b/hw/ide/core.c
+@@ -506,11 +506,13 @@ BlockAIOCB *ide_issue_trim(
+ BlockCompletionFunc *cb, void *cb_opaque, void *opaque)
+ {
+ IDEState *s = opaque;
++ IDEDevice *dev = s->unit ? s->bus->slave : s->bus->master;
+ TrimAIOCB *iocb;
+
+ iocb = blk_aio_get(&trim_aiocb_info, s->blk, cb, cb_opaque);
+ iocb->s = s;
+- iocb->bh = qemu_bh_new(ide_trim_bh_cb, iocb);
++ iocb->bh = qemu_bh_new_guarded(ide_trim_bh_cb, iocb,
++ &DEVICE(dev)->mem_reentrancy_guard);
+ iocb->ret = 0;
+ iocb->qiov = qiov;
+ iocb->i = -1;
+diff --git a/hw/misc/imx_rngc.c b/hw/misc/imx_rngc.c
+index 632c03779..082c6980a 100644
+--- a/hw/misc/imx_rngc.c
++++ b/hw/misc/imx_rngc.c
+@@ -228,8 +228,10 @@ static void imx_rngc_realize(DeviceState *dev, Error **errp)
+ sysbus_init_mmio(sbd, &s->iomem);
+
+ sysbus_init_irq(sbd, &s->irq);
+- s->self_test_bh = qemu_bh_new(imx_rngc_self_test, s);
+- s->seed_bh = qemu_bh_new(imx_rngc_seed, s);
++ s->self_test_bh = qemu_bh_new_guarded(imx_rngc_self_test, s,
++ &dev->mem_reentrancy_guard);
++ s->seed_bh = qemu_bh_new_guarded(imx_rngc_seed, s,
++ &dev->mem_reentrancy_guard);
+ }
+
+ static void imx_rngc_reset(DeviceState *dev)
+diff --git a/hw/misc/macio/mac_dbdma.c b/hw/misc/macio/mac_dbdma.c
+index efcc02609..cc7e02203 100644
+--- a/hw/misc/macio/mac_dbdma.c
++++ b/hw/misc/macio/mac_dbdma.c
+@@ -914,7 +914,7 @@ static void mac_dbdma_realize(DeviceState *dev, Error **errp)
+ {
+ DBDMAState *s = MAC_DBDMA(dev);
+
+- s->bh = qemu_bh_new(DBDMA_run_bh, s);
++ s->bh = qemu_bh_new_guarded(DBDMA_run_bh, s, &dev->mem_reentrancy_guard);
+ }
+
+ static void mac_dbdma_class_init(ObjectClass *oc, void *data)
+diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
+index 9127d03db..a1d65b2f2 100644
+--- a/hw/net/virtio-net.c
++++ b/hw/net/virtio-net.c
+@@ -2744,7 +2744,8 @@ static void virtio_net_add_queue(VirtIONet *n, int index)
+ n->vqs[index].tx_vq =
+ virtio_add_queue(vdev, n->net_conf.tx_queue_size,
+ virtio_net_handle_tx_bh);
+- n->vqs[index].tx_bh = qemu_bh_new(virtio_net_tx_bh, &n->vqs[index]);
++ n->vqs[index].tx_bh = qemu_bh_new_guarded(virtio_net_tx_bh, &n->vqs[index],
++ &DEVICE(vdev)->mem_reentrancy_guard);
+ }
+
+ n->vqs[index].tx_waiting = 0;
+diff --git a/hw/scsi/mptsas.c b/hw/scsi/mptsas.c
+index 5181b0c0b..8487138cb 100644
+--- a/hw/scsi/mptsas.c
++++ b/hw/scsi/mptsas.c
+@@ -1321,7 +1321,8 @@ static void mptsas_scsi_realize(PCIDevice *dev, Error **errp)
+ }
+ s->max_devices = MPTSAS_NUM_PORTS;
+
+- s->request_bh = qemu_bh_new(mptsas_fetch_requests, s);
++ s->request_bh = qemu_bh_new_guarded(mptsas_fetch_requests, s,
++ &DEVICE(dev)->mem_reentrancy_guard);
+
+ scsi_bus_init(&s->bus, sizeof(s->bus), &dev->qdev, &mptsas_scsi_info);
+ }
+diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
+index 2b5e9dca3..54b9a8ce9 100644
+--- a/hw/scsi/scsi-bus.c
++++ b/hw/scsi/scsi-bus.c
+@@ -192,7 +192,8 @@ static void scsi_dma_restart_cb(void *opaque, bool running, RunState state)
+ AioContext *ctx = blk_get_aio_context(s->conf.blk);
+ /* The reference is dropped in scsi_dma_restart_bh.*/
+ object_ref(OBJECT(s));
+- s->bh = aio_bh_new(ctx, scsi_dma_restart_bh, s);
++ s->bh = aio_bh_new_guarded(ctx, scsi_dma_restart_bh, s,
++ &DEVICE(s)->mem_reentrancy_guard);
+ qemu_bh_schedule(s->bh);
+ }
+ }
+diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
+index 4d9969f3b..d5c6293a2 100644
+--- a/hw/scsi/vmw_pvscsi.c
++++ b/hw/scsi/vmw_pvscsi.c
+@@ -1184,7 +1184,8 @@ pvscsi_realizefn(PCIDevice *pci_dev, Error **errp)
+ pcie_endpoint_cap_init(pci_dev, PVSCSI_EXP_EP_OFFSET);
+ }
+
+- s->completion_worker = qemu_bh_new(pvscsi_process_completion_queue, s);
++ s->completion_worker = qemu_bh_new_guarded(pvscsi_process_completion_queue, s,
++ &DEVICE(pci_dev)->mem_reentrancy_guard);
+
+ scsi_bus_init(&s->bus, sizeof(s->bus), DEVICE(pci_dev), &pvscsi_scsi_info);
+ /* override default SCSI bus hotplug-handler, with pvscsi's one */
+diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c
+index 599d6b52a..a36a7c301 100644
+--- a/hw/usb/dev-uas.c
++++ b/hw/usb/dev-uas.c
+@@ -935,7 +935,8 @@ static void usb_uas_realize(USBDevice *dev, Error **errp)
+
+ QTAILQ_INIT(&uas->results);
+ QTAILQ_INIT(&uas->requests);
+- uas->status_bh = qemu_bh_new(usb_uas_send_status_bh, uas);
++ uas->status_bh = qemu_bh_new_guarded(usb_uas_send_status_bh, uas,
++ &d->mem_reentrancy_guard);
+
+ dev->flags |= (1 << USB_DEV_FLAG_IS_SCSI_STORAGE);
+ scsi_bus_init(&uas->bus, sizeof(uas->bus), DEVICE(dev), &usb_uas_scsi_info);
+diff --git a/hw/usb/hcd-dwc2.c b/hw/usb/hcd-dwc2.c
+index 8755e9cbb..a0c4e782b 100644
+--- a/hw/usb/hcd-dwc2.c
++++ b/hw/usb/hcd-dwc2.c
+@@ -1364,7 +1364,8 @@ static void dwc2_realize(DeviceState *dev, Error **errp)
+ s->fi = USB_FRMINTVL - 1;
+ s->eof_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, dwc2_frame_boundary, s);
+ s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, dwc2_work_timer, s);
+- s->async_bh = qemu_bh_new(dwc2_work_bh, s);
++ s->async_bh = qemu_bh_new_guarded(dwc2_work_bh, s,
++ &dev->mem_reentrancy_guard);
+
+ sysbus_init_irq(sbd, &s->irq);
+ }
+diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
+index 33a8a377b..7b0538810 100644
+--- a/hw/usb/hcd-ehci.c
++++ b/hw/usb/hcd-ehci.c
+@@ -2530,7 +2530,8 @@ void usb_ehci_realize(EHCIState *s, DeviceState *dev, Error **errp)
+ }
+
+ s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ehci_work_timer, s);
+- s->async_bh = qemu_bh_new(ehci_work_bh, s);
++ s->async_bh = qemu_bh_new_guarded(ehci_work_bh, s,
++ &dev->mem_reentrancy_guard);
+ s->device = dev;
+
+ s->vmstate = qemu_add_vm_change_state_handler(usb_ehci_vm_state_change, s);
+diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
+index d1b5657d7..ef967c42a 100644
+--- a/hw/usb/hcd-uhci.c
++++ b/hw/usb/hcd-uhci.c
+@@ -1193,7 +1193,7 @@ void usb_uhci_common_realize(PCIDevice *dev, Error **errp)
+ USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
+ }
+ }
+- s->bh = qemu_bh_new(uhci_bh, s);
++ s->bh = qemu_bh_new_guarded(uhci_bh, s, &DEVICE(dev)->mem_reentrancy_guard);
+ s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, uhci_frame_timer, s);
+ s->num_ports_vmstate = NB_PORTS;
+ QTAILQ_INIT(&s->queues);
+diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c
+index d0d46dd0a..09b961116 100644
+--- a/hw/usb/host-libusb.c
++++ b/hw/usb/host-libusb.c
+@@ -1141,7 +1141,8 @@ static void usb_host_nodev_bh(void *opaque)
+ static void usb_host_nodev(USBHostDevice *s)
+ {
+ if (!s->bh_nodev) {
+- s->bh_nodev = qemu_bh_new(usb_host_nodev_bh, s);
++ s->bh_nodev = qemu_bh_new_guarded(usb_host_nodev_bh, s,
++ &DEVICE(s)->mem_reentrancy_guard);
+ }
+ qemu_bh_schedule(s->bh_nodev);
+ }
+@@ -1739,7 +1740,8 @@ static int usb_host_post_load(void *opaque, int version_id)
+ USBHostDevice *dev = opaque;
+
+ if (!dev->bh_postld) {
+- dev->bh_postld = qemu_bh_new(usb_host_post_load_bh, dev);
++ dev->bh_postld = qemu_bh_new_guarded(usb_host_post_load_bh, dev,
++ &DEVICE(dev)->mem_reentrancy_guard);
+ }
+ qemu_bh_schedule(dev->bh_postld);
+ dev->bh_postld_pending = true;
+diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
+index 5f0ef9cb3..59cd3cd7c 100644
+--- a/hw/usb/redirect.c
++++ b/hw/usb/redirect.c
+@@ -1437,8 +1437,10 @@ static void usbredir_realize(USBDevice *udev, Error **errp)
+ }
+ }
+
+- dev->chardev_close_bh = qemu_bh_new(usbredir_chardev_close_bh, dev);
+- dev->device_reject_bh = qemu_bh_new(usbredir_device_reject_bh, dev);
++ dev->chardev_close_bh = qemu_bh_new_guarded(usbredir_chardev_close_bh, dev,
++ &DEVICE(dev)->mem_reentrancy_guard);
++ dev->device_reject_bh = qemu_bh_new_guarded(usbredir_device_reject_bh, dev,
++ &DEVICE(dev)->mem_reentrancy_guard);
+ dev->attach_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, usbredir_do_attach, dev);
+
+ packet_id_queue_init(&dev->cancelled, dev, "cancelled");
+diff --git a/hw/usb/xen-usb.c b/hw/usb/xen-usb.c
+index 0f7369e7e..dec91294a 100644
+--- a/hw/usb/xen-usb.c
++++ b/hw/usb/xen-usb.c
+@@ -1021,7 +1021,8 @@ static void usbback_alloc(struct XenLegacyDevice *xendev)
+
+ QTAILQ_INIT(&usbif->req_free_q);
+ QSIMPLEQ_INIT(&usbif->hotplug_q);
+- usbif->bh = qemu_bh_new(usbback_bh, usbif);
++ usbif->bh = qemu_bh_new_guarded(usbback_bh, usbif,
++ &DEVICE(xendev)->mem_reentrancy_guard);
+ }
+
+ static int usbback_free(struct XenLegacyDevice *xendev)
+diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
+index 9a4f491b5..f503572e2 100644
+--- a/hw/virtio/virtio-balloon.c
++++ b/hw/virtio/virtio-balloon.c
+@@ -917,8 +917,9 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp)
+ precopy_add_notifier(&s->free_page_hint_notify);
+
+ object_ref(OBJECT(s->iothread));
+- s->free_page_bh = aio_bh_new(iothread_get_aio_context(s->iothread),
+- virtio_ballloon_get_free_page_hints, s);
++ s->free_page_bh = aio_bh_new_guarded(iothread_get_aio_context(s->iothread),
++ virtio_ballloon_get_free_page_hints, s,
++ &dev->mem_reentrancy_guard);
+ }
+
+ if (virtio_has_feature(s->host_features, VIRTIO_BALLOON_F_REPORTING)) {
+diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c
+index 274c7b4de..cb3e6ed0e 100644
+--- a/hw/virtio/virtio-crypto.c
++++ b/hw/virtio/virtio-crypto.c
+@@ -822,7 +822,8 @@ static void virtio_crypto_device_realize(DeviceState *dev, Error **errp)
+ vcrypto->vqs[i].dataq =
+ virtio_add_queue(vdev, 1024, virtio_crypto_handle_dataq_bh);
+ vcrypto->vqs[i].dataq_bh =
+- qemu_bh_new(virtio_crypto_dataq_bh, &vcrypto->vqs[i]);
++ qemu_bh_new_guarded(virtio_crypto_dataq_bh, &vcrypto->vqs[i],
++ &dev->mem_reentrancy_guard);
+ vcrypto->vqs[i].vcrypto = vcrypto;
+ }
+
+--
+2.40.0
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0003.patch b/meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0003.patch
new file mode 100644
index 0000000000..8f7fa1a569
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0003.patch
@@ -0,0 +1,68 @@
+From ec0504b989ca61e03636384d3602b7bf07ffe4da Mon Sep 17 00:00:00 2001
+From: Philippe Mathieu-Daudé <philmd@linaro.org>
+Date: Mon, 27 May 2024 11:52:53 +0000
+Subject: [PATCH] hw/virtio: Introduce virtio_bh_new_guarded() helper
+
+Introduce virtio_bh_new_guarded(), similar to qemu_bh_new_guarded()
+but using the transport memory guard, instead of the device one
+(there can only be one virtio device per virtio bus).
+
+Inspired-by: Gerd Hoffmann <kraxel@redhat.com>
+Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
+Acked-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
+Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
+Message-Id: <20240409105537.18308-2-philmd@linaro.org>
+
+CVE: CVE-2024-3446
+Upstream-Status: Backport [https://gitlab.com/qemu-project/qemu/-/commit/ec0504b989ca61e03636384d3602b7bf07ffe4da]
+
+Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
+---
+ hw/virtio/virtio.c | 10 ++++++++++
+ include/hw/virtio/virtio.h | 7 +++++++
+ 2 files changed, 17 insertions(+)
+
+diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
+index e11a8a0db..be0b3ff9d 100644
+--- a/hw/virtio/virtio.c
++++ b/hw/virtio/virtio.c
+@@ -3876,3 +3876,13 @@ static void virtio_register_types(void)
+ }
+
+ type_init(virtio_register_types)
++
++QEMUBH *virtio_bh_new_guarded_full(DeviceState *dev,
++ QEMUBHFunc *cb, void *opaque,
++ const char *name)
++{
++ DeviceState *transport = qdev_get_parent_bus(dev)->parent;
++
++ return qemu_bh_new_full(cb, opaque, name,
++ &transport->mem_reentrancy_guard);
++}
+diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
+index 8bab9cfb7..731c631a8 100644
+--- a/include/hw/virtio/virtio.h
++++ b/include/hw/virtio/virtio.h
+@@ -22,6 +22,7 @@
+ #include "standard-headers/linux/virtio_config.h"
+ #include "standard-headers/linux/virtio_ring.h"
+ #include "qom/object.h"
++#include "block/aio.h"
+
+ /* A guest should never accept this. It implies negotiation is broken. */
+ #define VIRTIO_F_BAD_FEATURE 30
+@@ -397,4 +398,10 @@ static inline bool virtio_device_disabled(VirtIODevice *vdev)
+ bool virtio_legacy_allowed(VirtIODevice *vdev);
+ bool virtio_legacy_check_disabled(VirtIODevice *vdev);
+
++QEMUBH *virtio_bh_new_guarded_full(DeviceState *dev,
++ QEMUBHFunc *cb, void *opaque,
++ const char *name);
++#define virtio_bh_new_guarded(dev, cb, opaque) \
++ virtio_bh_new_guarded_full((dev), (cb), (opaque), (stringify(cb)))
++
+ #endif
+--
+2.40.0
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0004.patch b/meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0004.patch
new file mode 100644
index 0000000000..d833b8b1e1
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0004.patch
@@ -0,0 +1,144 @@
+From ba28e0ff4d95b56dc334aac2730ab3651ffc3132 Mon Sep 17 00:00:00 2001
+From: Philippe Mathieu-Daudé <philmd@linaro.org>
+Date: Tue, 28 May 2024 05:50:35 +0000
+Subject: [PATCH] virtio-gpu: Protect from DMA re-entrancy bugs
+
+Replace qemu_bh_new_guarded() by virtio_bh_new_guarded()
+so the bus and device use the same guard. Otherwise the
+DMA-reentrancy protection can be bypassed:
+
+ $ cat << EOF | qemu-system-i386 -display none -nodefaults \
+ -machine q35,accel=qtest \
+ -m 512M \
+ -device virtio-gpu \
+ -qtest stdio
+
+ outl 0xcf8 0x80000820
+ outl 0xcfc 0xe0004000
+ outl 0xcf8 0x80000804
+ outw 0xcfc 0x06
+ write 0xe0004030 0x4 0x024000e0
+ write 0xe0004028 0x1 0xff
+ write 0xe0004020 0x4 0x00009300
+ write 0xe000401c 0x1 0x01
+ write 0x101 0x1 0x04
+ write 0x103 0x1 0x1c
+ write 0x9301c8 0x1 0x18
+ write 0x105 0x1 0x1c
+ write 0x107 0x1 0x1c
+ write 0x109 0x1 0x1c
+ write 0x10b 0x1 0x00
+ write 0x10d 0x1 0x00
+ write 0x10f 0x1 0x00
+ write 0x111 0x1 0x00
+ write 0x113 0x1 0x00
+ write 0x115 0x1 0x00
+ write 0x117 0x1 0x00
+ write 0x119 0x1 0x00
+ write 0x11b 0x1 0x00
+ write 0x11d 0x1 0x00
+ write 0x11f 0x1 0x00
+ write 0x121 0x1 0x00
+ write 0x123 0x1 0x00
+ write 0x125 0x1 0x00
+ write 0x127 0x1 0x00
+ write 0x129 0x1 0x00
+ write 0x12b 0x1 0x00
+ write 0x12d 0x1 0x00
+ write 0x12f 0x1 0x00
+ write 0x131 0x1 0x00
+ write 0x133 0x1 0x00
+ write 0x135 0x1 0x00
+ write 0x137 0x1 0x00
+ write 0x139 0x1 0x00
+ write 0xe0007003 0x1 0x00
+ EOF
+ ...
+ =================================================================
+ ==276099==ERROR: AddressSanitizer: heap-use-after-free on address 0x60d000011178
+ at pc 0x562cc3b736c7 bp 0x7ffed49dee60 sp 0x7ffed49dee58
+ READ of size 8 at 0x60d000011178 thread T0
+ #0 0x562cc3b736c6 in virtio_gpu_ctrl_response hw/display/virtio-gpu.c:180:42
+ #1 0x562cc3b7c40b in virtio_gpu_ctrl_response_nodata hw/display/virtio-gpu.c:192:5
+ #2 0x562cc3b7c40b in virtio_gpu_simple_process_cmd hw/display/virtio-gpu.c:1015:13
+ #3 0x562cc3b82873 in virtio_gpu_process_cmdq hw/display/virtio-gpu.c:1050:9
+ #4 0x562cc4a85514 in aio_bh_call util/async.c:169:5
+ #5 0x562cc4a85c52 in aio_bh_poll util/async.c:216:13
+ #6 0x562cc4a1a79b in aio_dispatch util/aio-posix.c:423:5
+ #7 0x562cc4a8a2da in aio_ctx_dispatch util/async.c:358:5
+ #8 0x7f36840547a8 in g_main_context_dispatch (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x547a8)
+ #9 0x562cc4a8b753 in glib_pollfds_poll util/main-loop.c:290:9
+ #10 0x562cc4a8b753 in os_host_main_loop_wait util/main-loop.c:313:5
+ #11 0x562cc4a8b753 in main_loop_wait util/main-loop.c:592:11
+ #12 0x562cc3938186 in qemu_main_loop system/runstate.c:782:9
+ #13 0x562cc43b7af5 in qemu_default_main system/main.c:37:14
+ #14 0x7f3683a6c189 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
+ #15 0x7f3683a6c244 in __libc_start_main csu/../csu/libc-start.c:381:3
+ #16 0x562cc2a58ac0 in _start (qemu-system-i386+0x231bac0)
+
+ 0x60d000011178 is located 56 bytes inside of 136-byte region [0x60d000011140,0x60d0000111c8)
+ freed by thread T0 here:
+ #0 0x562cc2adb662 in __interceptor_free (qemu-system-i386+0x239e662)
+ #1 0x562cc3b86b21 in virtio_gpu_reset hw/display/virtio-gpu.c:1524:9
+ #2 0x562cc416e20e in virtio_reset hw/virtio/virtio.c:2145:9
+ #3 0x562cc37c5644 in virtio_pci_reset hw/virtio/virtio-pci.c:2249:5
+ #4 0x562cc4233758 in memory_region_write_accessor system/memory.c:497:5
+ #5 0x562cc4232eea in access_with_adjusted_size system/memory.c:573:18
+
+ previously allocated by thread T0 here:
+ #0 0x562cc2adb90e in malloc (qemu-system-i386+0x239e90e)
+ #1 0x7f368405a678 in g_malloc (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x5a678)
+ #2 0x562cc4163ffc in virtqueue_split_pop hw/virtio/virtio.c:1612:12
+ #3 0x562cc4163ffc in virtqueue_pop hw/virtio/virtio.c:1783:16
+ #4 0x562cc3b91a95 in virtio_gpu_handle_ctrl hw/display/virtio-gpu.c:1112:15
+ #5 0x562cc4a85514 in aio_bh_call util/async.c:169:5
+ #6 0x562cc4a85c52 in aio_bh_poll util/async.c:216:13
+ #7 0x562cc4a1a79b in aio_dispatch util/aio-posix.c:423:5
+
+ SUMMARY: AddressSanitizer: heap-use-after-free hw/display/virtio-gpu.c:180:42 in virtio_gpu_ctrl_response
+
+With this change, the same reproducer triggers:
+
+ qemu-system-i386: warning: Blocked re-entrant IO on MemoryRegion: virtio-pci-common-virtio-gpu at addr: 0x6
+
+Fixes: CVE-2024-3446
+Cc: qemu-stable@nongnu.org
+Reported-by: Alexander Bulekov <alxndr@bu.edu>
+Reported-by: Yongkang Jia <kangel@zju.edu.cn>
+Reported-by: Xiao Lei <nop.leixiao@gmail.com>
+Reported-by: Yiming Tao <taoym@zju.edu.cn>
+Buglink: https://bugs.launchpad.net/qemu/+bug/1888606
+
+Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
+Acked-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
+Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
+Message-Id: <20240409105537.18308-3-philmd@linaro.org>
+
+CVE: CVE-2024-3446
+Upstream-Status: Backport [https://gitlab.com/qemu-project/qemu/-/commit/ba28e0ff4d95b56dc334aac2730ab3651ffc3132]
+
+Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
+---
+ hw/display/virtio-gpu.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
+index 316469ab7..5719ef6f1 100644
+--- a/hw/display/virtio-gpu.c
++++ b/hw/display/virtio-gpu.c
+@@ -1334,10 +1334,8 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
+
+ g->ctrl_vq = virtio_get_queue(vdev, 0);
+ g->cursor_vq = virtio_get_queue(vdev, 1);
+- g->ctrl_bh = qemu_bh_new_guarded(virtio_gpu_ctrl_bh, g,
+- &qdev->mem_reentrancy_guard);
+- g->cursor_bh = qemu_bh_new_guarded(virtio_gpu_cursor_bh, g,
+- &qdev->mem_reentrancy_guard);
++ g->ctrl_bh = virtio_bh_new_guarded(qdev, virtio_gpu_ctrl_bh, g);
++ g->cursor_bh = virtio_bh_new_guarded(qdev, virtio_gpu_cursor_bh, g);
+ QTAILQ_INIT(&g->reslist);
+ QTAILQ_INIT(&g->cmdq);
+ QTAILQ_INIT(&g->fenceq);
+--
+2.40.0
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0005.patch b/meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0005.patch
new file mode 100644
index 0000000000..51aa8a4038
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0005.patch
@@ -0,0 +1,42 @@
+From b4295bff25f7b50de1d9cc94a9c6effd40056bca Mon Sep 17 00:00:00 2001
+From: Philippe Mathieu-Daudé <philmd@linaro.org>
+Date: Tue, 28 May 2024 06:55:51 +0000
+Subject: [PATCH] hw/char/virtio-serial-bus: Protect from DMA re-entrancy bugs
+
+Replace qemu_bh_new_guarded() by virtio_bh_new_guarded()
+so the bus and device use the same guard. Otherwise the
+DMA-reentrancy protection can be bypassed.
+
+Fixes: CVE-2024-3446
+Cc: qemu-stable@nongnu.org
+Suggested-by: Alexander Bulekov <alxndr@bu.edu>
+Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
+Acked-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
+Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
+Message-Id: <20240409105537.18308-4-philmd@linaro.org>
+
+CVE: CVE-2024-3446
+Upstream-Status: Backport [https://gitlab.com/qemu-project/qemu/-/commit/b4295bff25f7b50de1d9cc94a9c6effd40056bca]
+
+Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
+---
+ hw/char/virtio-serial-bus.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
+index f18124b15..791b7ac59 100644
+--- a/hw/char/virtio-serial-bus.c
++++ b/hw/char/virtio-serial-bus.c
+@@ -985,8 +985,7 @@ static void virtser_port_device_realize(DeviceState *dev, Error **errp)
+ return;
+ }
+
+- port->bh = qemu_bh_new_guarded(flush_queued_data_bh, port,
+- &dev->mem_reentrancy_guard);
++ port->bh = virtio_bh_new_guarded(dev, flush_queued_data_bh, port);
+ port->elem = NULL;
+ }
+
+--
+2.40.0
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0006.patch b/meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0006.patch
new file mode 100644
index 0000000000..c7f19f45e7
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu/CVE-2024-3446-0006.patch
@@ -0,0 +1,43 @@
+From f4729ec39ad97a42ceaa7b5697f84f440ea6e5dc Mon Sep 17 00:00:00 2001
+From: Philippe Mathieu-Daudé <philmd@linaro.org>
+Date: Tue, 28 May 2024 09:22:58 +0000
+Subject: [PATCH] hw/virtio/virtio-crypto: Protect from DMA re-entrancy bugs
+
+Replace qemu_bh_new_guarded() by virtio_bh_new_guarded()
+so the bus and device use the same guard. Otherwise the
+DMA-reentrancy protection can be bypassed.
+
+Fixes: CVE-2024-3446
+Cc: qemu-stable@nongnu.org
+Suggested-by: Alexander Bulekov <alxndr@bu.edu>
+Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
+Acked-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
+Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
+Message-Id: <20240409105537.18308-5-philmd@linaro.org>
+
+CVE: CVE-2024-3446
+Upstream-Status: Backport [https://gitlab.com/qemu-project/qemu/-/commit/f4729ec39ad97a42ceaa7b5697f84f440ea6e5dc]
+
+Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
+---
+ hw/virtio/virtio-crypto.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c
+index cb3e6ed0e..930a8418f 100644
+--- a/hw/virtio/virtio-crypto.c
++++ b/hw/virtio/virtio-crypto.c
+@@ -822,8 +822,8 @@ static void virtio_crypto_device_realize(DeviceState *dev, Error **errp)
+ vcrypto->vqs[i].dataq =
+ virtio_add_queue(vdev, 1024, virtio_crypto_handle_dataq_bh);
+ vcrypto->vqs[i].dataq_bh =
+- qemu_bh_new_guarded(virtio_crypto_dataq_bh, &vcrypto->vqs[i],
+- &dev->mem_reentrancy_guard);
++ virtio_bh_new_guarded(dev, virtio_crypto_dataq_bh,
++ &vcrypto->vqs[i]);
+ vcrypto->vqs[i].vcrypto = vcrypto;
+ }
+
+--
+2.40.0
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 24/38] qemu: fix CVE-2024-3447
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (22 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 23/38] qemu: fix CVE-2024-3446 Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 25/38] diffoscope: fix CVE-2024-25711 Steve Sakoman
` (13 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Yogita Urade <yogita.urade@windriver.com>
A heap-based buffer overflow was found in the SDHCI device
emulation of QEMU. The bug is triggered when both
`s->data_count` and the size of `s->fifo_buffer` are set to
0x200, leading to an out-of-bound access. A malicious guest
could use this flaw to crash the QEMU process on the host,
resulting in a denial of service condition.
Reference:
https://nvd.nist.gov/vuln/detail/CVE-2024-3447
Upstream patch:
https://gitlab.com/qemu-project/qemu/-/commit/2429cb7a9f460b544f4b07bcf02dbdedfc4dcb39
Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
---
meta/recipes-devtools/qemu/qemu.inc | 1 +
.../qemu/qemu/CVE-2024-3447.patch | 137 ++++++++++++++++++
2 files changed, 138 insertions(+)
create mode 100644 meta/recipes-devtools/qemu/qemu/CVE-2024-3447.patch
diff --git a/meta/recipes-devtools/qemu/qemu.inc b/meta/recipes-devtools/qemu/qemu.inc
index 16eb30e572..bee30cd56f 100644
--- a/meta/recipes-devtools/qemu/qemu.inc
+++ b/meta/recipes-devtools/qemu/qemu.inc
@@ -127,6 +127,7 @@ SRC_URI = "https://download.qemu.org/${BPN}-${PV}.tar.xz \
file://CVE-2024-3446-0004.patch \
file://CVE-2024-3446-0005.patch \
file://CVE-2024-3446-0006.patch \
+ file://CVE-2024-3447.patch \
"
UPSTREAM_CHECK_REGEX = "qemu-(?P<pver>\d+(\.\d+)+)\.tar"
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2024-3447.patch b/meta/recipes-devtools/qemu/qemu/CVE-2024-3447.patch
new file mode 100644
index 0000000000..e403e3ec25
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu/CVE-2024-3447.patch
@@ -0,0 +1,137 @@
+From 2429cb7a9f460b544f4b07bcf02dbdedfc4dcb39 Mon Sep 17 00:00:00 2001
+From: Philippe Mathieu-Daudé <philmd@linaro.org>
+Date: Tue, 3 Dec 2024 08:19:23 +0000
+Subject: [PATCH] hw/sd/sdhci: Do not update TRNMOD when Command Inhibit (DAT)
+ is set Per "SD Host Controller Standard Specification Version 3.00":
+
+ * 2.2.5 Transfer Mode Register (Offset 00Ch)
+
+ Writes to this register shall be ignored when the Command
+ Inhibit (DAT) in the Present State register is 1.
+
+Do not update the TRNMOD register when Command Inhibit (DAT)
+bit is set to avoid the present-status register going out of
+sync, leading to malicious guest using DMA mode and overflowing
+the FIFO buffer:
+
+ $ cat << EOF | qemu-system-i386 \
+ -display none -nographic -nodefaults \
+ -machine accel=qtest -m 512M \
+ -device sdhci-pci,sd-spec-version=3 \
+ -device sd-card,drive=mydrive \
+ -drive if=none,index=0,file=null-co://,format=raw,id=mydrive \
+ -qtest stdio
+ outl 0xcf8 0x80001013
+ outl 0xcfc 0x91
+ outl 0xcf8 0x80001001
+ outl 0xcfc 0x06000000
+ write 0x9100002c 0x1 0x05
+ write 0x91000058 0x1 0x16
+ write 0x91000005 0x1 0x04
+ write 0x91000028 0x1 0x08
+ write 0x16 0x1 0x21
+ write 0x19 0x1 0x20
+ write 0x9100000c 0x1 0x01
+ write 0x9100000e 0x1 0x20
+ write 0x9100000f 0x1 0x00
+ write 0x9100000c 0x1 0x00
+ write 0x91000020 0x1 0x00
+ EOF
+
+Stack trace (part):
+=================================================================
+==89993==ERROR: AddressSanitizer: heap-buffer-overflow on address
+0x615000029900 at pc 0x55d5f885700d bp 0x7ffc1e1e9470 sp 0x7ffc1e1e9468
+WRITE of size 1 at 0x615000029900 thread T0
+ #0 0x55d5f885700c in sdhci_write_dataport hw/sd/sdhci.c:564:39
+ #1 0x55d5f8849150 in sdhci_write hw/sd/sdhci.c:1223:13
+ #2 0x55d5fa01db63 in memory_region_write_accessor system/memory.c:497:5
+ #3 0x55d5fa01d245 in access_with_adjusted_size system/memory.c:573:18
+ #4 0x55d5fa01b1a9 in memory_region_dispatch_write system/memory.c:1521:16
+ #5 0x55d5fa09f5c9 in flatview_write_continue system/physmem.c:2711:23
+ #6 0x55d5fa08f78b in flatview_write system/physmem.c:2753:12
+ #7 0x55d5fa08f258 in address_space_write system/physmem.c:2860:18
+ ...
+0x615000029900 is located 0 bytes to the right of 512-byte region
+[0x615000029700,0x615000029900) allocated by thread T0 here:
+ #0 0x55d5f7237b27 in __interceptor_calloc
+ #1 0x7f9e36dd4c50 in g_malloc0
+ #2 0x55d5f88672f7 in sdhci_pci_realize hw/sd/sdhci-pci.c:36:5
+ #3 0x55d5f844b582 in pci_qdev_realize hw/pci/pci.c:2092:9
+ #4 0x55d5fa2ee74b in device_set_realized hw/core/qdev.c:510:13
+ #5 0x55d5fa325bfb in property_set_bool qom/object.c:2358:5
+ #6 0x55d5fa31ea45 in object_property_set qom/object.c:1472:5
+ #7 0x55d5fa332509 in object_property_set_qobject om/qom-qobject.c:28:10
+ #8 0x55d5fa31f6ed in object_property_set_bool qom/object.c:1541:15
+ #9 0x55d5fa2e2948 in qdev_realize hw/core/qdev.c:292:12
+ #10 0x55d5f8eed3f1 in qdev_device_add_from_qdict system/qdev-monitor.c:719:10
+ #11 0x55d5f8eef7ff in qdev_device_add system/qdev-monitor.c:738:11
+ #12 0x55d5f8f211f0 in device_init_func system/vl.c:1200:11
+ #13 0x55d5fad0877d in qemu_opts_foreach util/qemu-option.c:1135:14
+ #14 0x55d5f8f0df9c in qemu_create_cli_devices system/vl.c:2638:5
+ #15 0x55d5f8f0db24 in qmp_x_exit_preconfig system/vl.c:2706:5
+ #16 0x55d5f8f14dc0 in qemu_init system/vl.c:3737:9
+ ...
+SUMMARY: AddressSanitizer: heap-buffer-overflow hw/sd/sdhci.c:564:39
+in sdhci_write_dataport
+
+Add assertions to ensure the fifo_buffer[] is not overflowed by
+malicious accesses to the Buffer Data Port register.
+
+Fixes: CVE-2024-3447
+Cc: qemu-stable@nongnu.org
+Fixes: d7dfca08 ("hw/sdhci: introduce standard SD host controller")
+Buglink: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=58813
+
+Reported-by: Alexander Bulekov <alxndr@bu.edu>
+Reported-by: Chuhong Yuan <hslester96@gmail.com>
+Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
+Message-Id: <CAFEAcA9iLiv1XGTGKeopgMa8Y9+8kvptvsb8z2OBeuy+5=NUfg@mail.gmail.com>
+Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
+Message-Id: <20240409145524.27913-1-philmd@linaro.org>
+(cherry picked from commit 9e4b27ca)
+Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
+
+CVE: CVE-2024-3447
+Upstream-Status: Backport [https://gitlab.com/qemu-project/qemu/-/commit/2429cb7a9f460b544f4b07bcf02dbdedfc4dcb39]
+
+Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
+---
+ hw/sd/sdhci.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
+index e0bbc9034..211daa4bb 100644
+--- a/hw/sd/sdhci.c
++++ b/hw/sd/sdhci.c
+@@ -471,6 +471,7 @@ static uint32_t sdhci_read_dataport(SDHCIState *s, unsigned size)
+ }
+
+ for (i = 0; i < size; i++) {
++ assert(s->data_count < s->buf_maxsz);
+ value |= s->fifo_buffer[s->data_count] << i * 8;
+ s->data_count++;
+ /* check if we've read all valid data (blksize bytes) from buffer */
+@@ -559,6 +560,7 @@ static void sdhci_write_dataport(SDHCIState *s, uint32_t value, unsigned size)
+ }
+
+ for (i = 0; i < size; i++) {
++ assert(s->data_count < s->buf_maxsz);
+ s->fifo_buffer[s->data_count] = value & 0xFF;
+ s->data_count++;
+ value >>= 8;
+@@ -1184,6 +1186,12 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
+ if (!(s->capareg & R_SDHC_CAPAB_SDMA_MASK)) {
+ value &= ~SDHC_TRNS_DMA;
+ }
++
++ /* TRNMOD writes are inhibited while Command Inhibit (DAT) is true */
++ if (s->prnsts & SDHC_DATA_INHIBIT) {
++ mask |= 0xffff;
++ }
++
+ MASKED_WRITE(s->trnmod, mask, value & SDHC_TRNMOD_MASK);
+ MASKED_WRITE(s->cmdreg, mask >> 16, value >> 16);
+
+--
+2.40.0
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 25/38] diffoscope: fix CVE-2024-25711
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (23 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 24/38] qemu: fix CVE-2024-3447 Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 26/38] do_package/sstate/sstatesig: Change timestamp clamping to hash output only Steve Sakoman
` (12 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Jiaying Song <jiaying.song.cn@windriver.com>
diffoscope before 256 allows directory traversal via an embedded
filename in a GPG file. Contents of any file, such as ../.ssh/id_rsa,
may be disclosed to an attacker. This occurs because the value of the
gpg --use-embedded-filenames option is trusted.
Reference:
https://nvd.nist.gov/vuln/detail/CVE-2024-25711
Upstream patches:
https://salsa.debian.org/reproducible-builds/diffoscope/-/commit/458f7f04bc053a0066aa7d2fd3251747d4899476
Signed-off-by: Jiaying Song <jiaying.song.cn@windriver.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
---
.../diffoscope/CVE-2024-25711.patch | 116 ++++++++++++++++++
.../diffoscope/diffoscope_208.bb | 1 +
2 files changed, 117 insertions(+)
create mode 100644 meta/recipes-support/diffoscope/diffoscope/CVE-2024-25711.patch
diff --git a/meta/recipes-support/diffoscope/diffoscope/CVE-2024-25711.patch b/meta/recipes-support/diffoscope/diffoscope/CVE-2024-25711.patch
new file mode 100644
index 0000000000..de1099c40b
--- /dev/null
+++ b/meta/recipes-support/diffoscope/diffoscope/CVE-2024-25711.patch
@@ -0,0 +1,116 @@
+From 1eda4012c5350efae02fcc058e0a36cc71ad62fd Mon Sep 17 00:00:00 2001
+From: Chris Lamb <lamby@debian.org>
+Date: Fri, 9 Feb 2024 10:43:18 -0800
+Subject: [PATCH] Use a determistic name instead of trusting gpg's
+ --use-embedded-filenames. (Closes: reproducible-builds/diffoscope#361)
+
+... but also expose the embedded name by attaching the ("unstable") output of
+--list-packets.
+
+Many thanks to Daniel Kahn Gillmor <dkg@debian.org> for reporting this issue
+and providing feedback.
+
+Upstream-Status: Backport
+[https://salsa.debian.org/reproducible-builds/diffoscope/-/commit/458f7f04bc053a0066aa7d2fd3251747d4899476]
+
+CVE: CVE-2024-25711
+
+Signed-off-by: Jiaying Song <jiaying.song.cn@windriver.com>
+---
+ diffoscope/comparators/pgp.py | 34 +++++++++++++++++++++++++++++-----
+ tests/comparators/test_pgp.py | 3 ++-
+ 2 files changed, 31 insertions(+), 6 deletions(-)
+
+diff --git a/diffoscope/comparators/pgp.py b/diffoscope/comparators/pgp.py
+index eea997b..9215664 100644
+--- a/diffoscope/comparators/pgp.py
++++ b/diffoscope/comparators/pgp.py
+@@ -32,6 +32,8 @@ from .utils.command import Command, our_check_output
+
+ logger = logging.getLogger(__name__)
+
++re_name = re.compile(r", created \d+, name=\"(?P<name>[^\"]+)\",")
++
+
+ class Pgpdump(Command):
+ @tool_required("pgpdump")
+@@ -46,21 +48,31 @@ class Pgpdump(Command):
+ )
+
+
++class GpgListPackets(Command):
++ @tool_required("gpg")
++ def cmdline(self):
++ return (
++ "gpg",
++ "--no-keyring",
++ "--list-packets",
++ self.path,
++ )
++
++
+ class PGPContainer(Archive):
+ @tool_required("gpg")
+ def open_archive(self):
+- # Extract to a fresh temporary directory so that we can use the
+- # embedded filename.
+-
++ # Extract to a fresh temporary directory.
+ self._temp_dir = get_temporary_directory(suffix="pgp")
+
+ try:
+ our_check_output(
+ (
+ "gpg",
+- "--use-embedded-filename",
+ "--decrypt",
+ "--no-keyring",
++ "--output",
++ os.path.join(self._temp_dir.name, "contents"),
+ os.path.abspath(self.source.path),
+ ),
+ cwd=self._temp_dir.name,
+@@ -75,7 +87,7 @@ class PGPContainer(Archive):
+ self._temp_dir.cleanup()
+
+ def get_member_names(self):
+- # Will only return one filename, taken from the signature file itself.
++ # Will only ever return one filename
+ return os.listdir(self._temp_dir.name)
+
+ def extract(self, member_name, dest_dir):
+@@ -136,4 +148,16 @@ class PgpSignature(TextFile):
+ ]
+ )
+
++ # ... as well as gpg --list-packets
++ difference.add_details(
++ [
++ Difference.from_operation(
++ GpgListPackets,
++ self.path,
++ other.path,
++ source="gpg --list-packets",
++ )
++ ]
++ )
++
+ return difference
+diff --git a/tests/comparators/test_pgp.py b/tests/comparators/test_pgp.py
+index 8652ea9..49b3fa0 100644
+--- a/tests/comparators/test_pgp.py
++++ b/tests/comparators/test_pgp.py
+@@ -80,8 +80,9 @@ def test_pgp_signature_identification(signature1, signature2):
+ def test_pgp_signature(signature1, signature2):
+ difference = signature1.compare(signature2)
+ assert_diff(difference, "pgp_signature_expected_diff")
++ assert len(difference.details) == 2
+ assert difference.details[0].source1 == "pgpdump"
+- assert len(difference.details) == 1
++ assert difference.details[1].source1 == "gpg --list-packets"
+
+
+ @skip_unless_tools_exist("pgpdump")
+--
+2.25.1
+
diff --git a/meta/recipes-support/diffoscope/diffoscope_208.bb b/meta/recipes-support/diffoscope/diffoscope_208.bb
index 3c3b007d60..e4fde88c95 100644
--- a/meta/recipes-support/diffoscope/diffoscope_208.bb
+++ b/meta/recipes-support/diffoscope/diffoscope_208.bb
@@ -12,6 +12,7 @@ PYPI_PACKAGE = "diffoscope"
inherit pypi setuptools3
+SRC_URI += " file://CVE-2024-25711.patch"
SRC_URI[sha256sum] = "2c5c0ac1159eefce158154849fe67f0f527dffc5295bfd3ca1aef14962ffcbcb"
RDEPENDS:${PN} += "binutils vim squashfs-tools python3-libarchive-c python3-magic python3-rpm"
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 26/38] do_package/sstate/sstatesig: Change timestamp clamping to hash output only
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (24 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 25/38] diffoscope: fix CVE-2024-25711 Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 27/38] rxvt-unicode.inc: disable the terminfo installation by setting TIC to : Steve Sakoman
` (11 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Richard Purdie <richard.purdie@linuxfoundation.org>
The code was changing the timestamps of the files in the do_package output,
particularly the files added for debug sources. This was to do two things:
a) make do_package sstate more reproducible
b) ensure better hash equivalence matching
Unfortuately the debug source files are hardlinks into the source tree for
efficiency so touching these, touches a lot of files in ${B} and ${S}. This
causes unpredictable effects if compile is run again for example, or could
cause compiling in the install task.
The hash equivalence matching is of key importance but we can mimic that
using clamping of the file timestamps in the depsig output used to generate
the hashes.
This patch drops the global timestamp clamping, instead allowing the files
to retain their creation timestamps into sstate. This makes do_package sstate
slightly less reproducibile. We could clamp the sstate timestamps but that
would lead to two different sets of timestamps depending on whether the
data came from sstate or not. I'd prefer to have consistent code behaviour,
rather than differing behavhour depending on whether data came from sstate
or not.
If we wanted to have reproducibiliy and fix the "corruption" of S/B and have
consistent codepaths, the only other option would be two copies of the
sources, which could end up huge and seems the least desireable option.
This patch therefore drops the timestamp clamping in the sstate files
and tweaks the depsig data generation to clamp the timestamps for do_package
instead since this seems the best compromise.
I validated that rpm/deb/ipk files still generate correctly as before.
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit 475759fdab7200488b2a568b2ba1aa31a456d113)
Signed-off-by: Steve Sakoman <steve@sakoman.com>
---
meta/classes/sstate.bbclass | 16 ----------------
meta/lib/oe/sstatesig.py | 7 ++++++-
2 files changed, 6 insertions(+), 17 deletions(-)
diff --git a/meta/classes/sstate.bbclass b/meta/classes/sstate.bbclass
index 91d42665c1..6bfccbb907 100644
--- a/meta/classes/sstate.bbclass
+++ b/meta/classes/sstate.bbclass
@@ -660,15 +660,6 @@ def sstate_package(ss, d):
tmpdir = d.getVar('TMPDIR')
- fixtime = False
- if ss['task'] == "package":
- fixtime = True
-
- def fixtimestamp(root, path):
- f = os.path.join(root, path)
- if os.lstat(f).st_mtime > sde:
- os.utime(f, (sde, sde), follow_symlinks=False)
-
sstatebuild = d.expand("${WORKDIR}/sstate-build-%s/" % ss['task'])
sde = int(d.getVar("SOURCE_DATE_EPOCH") or time.time())
d.setVar("SSTATE_CURRTASK", ss['task'])
@@ -683,8 +674,6 @@ def sstate_package(ss, d):
# to sstate tasks but there aren't many of these so better just avoid them entirely.
for walkroot, dirs, files in os.walk(state[1]):
for file in files + dirs:
- if fixtime:
- fixtimestamp(walkroot, file)
srcpath = os.path.join(walkroot, file)
if not os.path.islink(srcpath):
continue
@@ -706,11 +695,6 @@ def sstate_package(ss, d):
bb.utils.mkdirhier(plain)
bb.utils.mkdirhier(pdir)
bb.utils.rename(plain, pdir)
- if fixtime:
- fixtimestamp(pdir, "")
- for walkroot, dirs, files in os.walk(pdir):
- for file in files + dirs:
- fixtimestamp(walkroot, file)
d.setVar('SSTATE_BUILDDIR', sstatebuild)
d.setVar('SSTATE_INSTDIR', sstatebuild)
diff --git a/meta/lib/oe/sstatesig.py b/meta/lib/oe/sstatesig.py
index 30f27b0f4f..331b67c6e4 100644
--- a/meta/lib/oe/sstatesig.py
+++ b/meta/lib/oe/sstatesig.py
@@ -510,6 +510,7 @@ def OEOuthashBasic(path, sigfile, task, d):
if task == "package":
include_timestamps = True
include_root = False
+ source_date_epoch = float(d.getVar("SOURCE_DATE_EPOCH"))
hash_version = d.getVar('HASHEQUIV_HASH_VERSION')
extra_sigdata = d.getVar("HASHEQUIV_EXTRA_SIGDATA")
@@ -601,7 +602,11 @@ def OEOuthashBasic(path, sigfile, task, d):
raise Exception(msg).with_traceback(e.__traceback__)
if include_timestamps:
- update_hash(" %10d" % s.st_mtime)
+ # Need to clamp to SOURCE_DATE_EPOCH
+ if s.st_mtime > source_date_epoch:
+ update_hash(" %10d" % source_date_epoch)
+ else:
+ update_hash(" %10d" % s.st_mtime)
update_hash(" ")
if stat.S_ISBLK(s.st_mode) or stat.S_ISCHR(s.st_mode):
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 27/38] rxvt-unicode.inc: disable the terminfo installation by setting TIC to :
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (25 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 26/38] do_package/sstate/sstatesig: Change timestamp clamping to hash output only Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 28/38] selftest/reproducible: Drop rawlogs Steve Sakoman
` (10 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Changqing Li <changqing.li@windriver.com>
Without this change, TIC is the native tic in recipe-sysroot-native.
By default, native tic has set its default terminfo path to native path:
${datadir}/terminfo; $HOME/.terminfo
When sstate cache is used, the cached native tic's terminfo path could
be a path not exist on current host, then native tic will try to install
terminfo to HOME dir, cause host contamination.
Disable the terminfo installation by setting TIC to :
Signed-off-by: Changqing Li <changqing.li@windriver.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit fe35ead2c3135a18c346e7baa31d34b15c3e2d95)
Signed-off-by: Steve Sakoman <steve@sakoman.com>
---
meta/recipes-sato/rxvt-unicode/rxvt-unicode.inc | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/meta/recipes-sato/rxvt-unicode/rxvt-unicode.inc b/meta/recipes-sato/rxvt-unicode/rxvt-unicode.inc
index e7d520ebef..aa26cc41a8 100644
--- a/meta/recipes-sato/rxvt-unicode/rxvt-unicode.inc
+++ b/meta/recipes-sato/rxvt-unicode/rxvt-unicode.inc
@@ -28,7 +28,8 @@ EXTRA_OECONF = "--enable-xim \
--with-codesets=eu --enable-pointer-blank \
--enable-text-blink --enable-rxvt-scroll \
--enable-combining --disable-perl \
- --with-x=${STAGING_DIR_HOST}${prefix}"
+ --with-x=${STAGING_DIR_HOST}${prefix} \
+ ac_cv_path_TIC=:"
PACKAGECONFIG ??= ""
PACKAGECONFIG[startup] = "--enable-startup-notification,--disable-startup-notification,startup-notification,"
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 28/38] selftest/reproducible: Drop rawlogs
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (26 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 27/38] rxvt-unicode.inc: disable the terminfo installation by setting TIC to : Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 29/38] selftest/reproducible: Clean up pathnames Steve Sakoman
` (9 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Richard Purdie <richard.purdie@linuxfoundation.org>
The "rawlogs" data consists of a long string of results data which is
already in a structured data format. I can't see this is adding much
value in duplciating the data but it does create a huge string with a
lot of long problematic pathnames and inflates the results data size.
I suggest we drop this data as obsolete and not necessary.
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit 5b2c70fab2ffa409b861d83f048b65d458d03a90)
Signed-off-by: Steve Sakoman <steve@sakoman.com>
---
meta/lib/oeqa/selftest/cases/reproducible.py | 6 ------
1 file changed, 6 deletions(-)
diff --git a/meta/lib/oeqa/selftest/cases/reproducible.py b/meta/lib/oeqa/selftest/cases/reproducible.py
index 49318be43a..df7d9cc159 100644
--- a/meta/lib/oeqa/selftest/cases/reproducible.py
+++ b/meta/lib/oeqa/selftest/cases/reproducible.py
@@ -163,12 +163,8 @@ class ReproducibleTests(OESelftestTestCase):
setattr(self, v.lower(), bb_vars[v])
self.extraresults = {}
- self.extraresults.setdefault('reproducible.rawlogs', {})['log'] = ''
self.extraresults.setdefault('reproducible', {}).setdefault('files', {})
- def append_to_log(self, msg):
- self.extraresults['reproducible.rawlogs']['log'] += msg
-
def compare_packages(self, reference_dir, test_dir, diffutils_sysroot):
result = PackageCompareResults()
@@ -282,8 +278,6 @@ class ReproducibleTests(OESelftestTestCase):
self.logger.info('Reproducibility summary for %s: %s' % (c, result))
- self.append_to_log('\n'.join("%s: %s" % (r.status, r.test) for r in result.total))
-
self.write_package_list(package_class, 'missing', result.missing)
self.write_package_list(package_class, 'different', result.different)
self.write_package_list(package_class, 'different_excluded', result.different_excluded)
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 29/38] selftest/reproducible: Clean up pathnames
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (27 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 28/38] selftest/reproducible: Drop rawlogs Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 30/38] resulttool: Allow store to filter to specific revisions Steve Sakoman
` (8 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Richard Purdie <richard.purdie@linuxfoundation.org>
There are several problems with these paths. Firstly they contain full
system paths which depend upon where the test was run. These are pretty
pointless and just take up a lot of space making the results files large.
Secondly, they contain the same path twice. The reference and target path
will always be the same thing in two different locations.
Strip off the prefix and remove the duplication. This does change the output
data but that can't really be avoided. It does shrink the results data and makes
it more readable.
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit 81a44de36e864b08687451fd85aeba7c529fd7f7)
Signed-off-by: Steve Sakoman <steve@sakoman.com>
---
meta/lib/oeqa/selftest/cases/reproducible.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/meta/lib/oeqa/selftest/cases/reproducible.py b/meta/lib/oeqa/selftest/cases/reproducible.py
index df7d9cc159..08c23227d3 100644
--- a/meta/lib/oeqa/selftest/cases/reproducible.py
+++ b/meta/lib/oeqa/selftest/cases/reproducible.py
@@ -191,7 +191,7 @@ class ReproducibleTests(OESelftestTestCase):
def write_package_list(self, package_class, name, packages):
self.extraresults['reproducible']['files'].setdefault(package_class, {})[name] = [
- {'reference': p.reference, 'test': p.test} for p in packages]
+ p.reference.split("/./")[1] for p in packages]
def copy_file(self, source, dest):
bb.utils.mkdirhier(os.path.dirname(dest))
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 30/38] resulttool: Allow store to filter to specific revisions
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (28 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 29/38] selftest/reproducible: Clean up pathnames Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 31/38] resulttool: Use single space indentation in json output Steve Sakoman
` (7 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Richard Purdie <richard.purdie@linuxfoundation.org>
We have a challenge on the autobuilder where test results from both OE-Core
and poky are being mixed together during result storage which is confusing the
data. Add a way to filter to specific revisions as the least worst way to fix
the various issues this is causing.
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit 3f276a0dc65341668788853be2cf27ab6aa12b13)
Signed-off-by: Steve Sakoman <steve@sakoman.com>
---
scripts/lib/resulttool/store.py | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/scripts/lib/resulttool/store.py b/scripts/lib/resulttool/store.py
index e0951f0a8f..430213bbfe 100644
--- a/scripts/lib/resulttool/store.py
+++ b/scripts/lib/resulttool/store.py
@@ -65,6 +65,9 @@ def store(args, logger):
for r in revisions:
results = revisions[r]
+ if args.revision and r[0] != args.revision:
+ logger.info('skipping %s as non-matching' % r[0])
+ continue
keywords = {'commit': r[0], 'branch': r[1], "commit_count": r[2]}
subprocess.check_call(["find", tempdir, "!", "-path", "./.git/*", "-delete"])
resultutils.save_resultsdata(results, tempdir, ptestlogs=True)
@@ -102,3 +105,5 @@ def register_commands(subparsers):
help='add executed-by configuration to each result file')
parser_build.add_argument('-t', '--extra-test-env', default='',
help='add extra test environment data to each result file configuration')
+ parser_build.add_argument('-r', '--revision', default='',
+ help='only store data for the specified revision')
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 31/38] resulttool: Use single space indentation in json output
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (29 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 30/38] resulttool: Allow store to filter to specific revisions Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 32/38] oeqa/utils/gitarchive: Return tag name and improve exclude handling Steve Sakoman
` (6 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Richard Purdie <richard.purdie@linuxfoundation.org>
Using 4 space indentation in resulted in hundreds of megabytes of extra file size
in general use. Reduce this to make filesizes more managable and reduce the processing
cost. Some level of indentation and spacing does make the files more readable and allows
use of git diff so we need to retain some of it.
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit a274cdcaf852cca9497f0358f44dda99c06aacbe)
Signed-off-by: Steve Sakoman <steve@sakoman.com>
---
meta/lib/oeqa/core/runner.py | 2 +-
scripts/lib/resulttool/manualexecution.py | 2 +-
scripts/lib/resulttool/report.py | 2 +-
scripts/lib/resulttool/resultutils.py | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/meta/lib/oeqa/core/runner.py b/meta/lib/oeqa/core/runner.py
index d50690ab37..a246c7d26b 100644
--- a/meta/lib/oeqa/core/runner.py
+++ b/meta/lib/oeqa/core/runner.py
@@ -347,7 +347,7 @@ class OETestResultJSONHelper(object):
os.makedirs(write_dir, exist_ok=True)
test_results = self._get_existing_testresults_if_available(write_dir)
test_results[result_id] = {'configuration': configuration, 'result': test_result}
- json_testresults = json.dumps(test_results, sort_keys=True, indent=4)
+ json_testresults = json.dumps(test_results, sort_keys=True, indent=1)
self._write_file(write_dir, self.testresult_filename, json_testresults)
if has_bb:
bb.utils.unlockfile(lf)
diff --git a/scripts/lib/resulttool/manualexecution.py b/scripts/lib/resulttool/manualexecution.py
index ecb27c5933..ae0861ac6b 100755
--- a/scripts/lib/resulttool/manualexecution.py
+++ b/scripts/lib/resulttool/manualexecution.py
@@ -22,7 +22,7 @@ def load_json_file(f):
def write_json_file(f, json_data):
os.makedirs(os.path.dirname(f), exist_ok=True)
with open(f, 'w') as filedata:
- filedata.write(json.dumps(json_data, sort_keys=True, indent=4))
+ filedata.write(json.dumps(json_data, sort_keys=True, indent=1))
class ManualTestRunner(object):
diff --git a/scripts/lib/resulttool/report.py b/scripts/lib/resulttool/report.py
index a349510ab8..1c100b00ab 100644
--- a/scripts/lib/resulttool/report.py
+++ b/scripts/lib/resulttool/report.py
@@ -256,7 +256,7 @@ class ResultsTextReport(object):
if selected_test_case_only:
print_selected_testcase_result(raw_results, selected_test_case_only)
else:
- print(json.dumps(raw_results, sort_keys=True, indent=4))
+ print(json.dumps(raw_results, sort_keys=True, indent=1))
else:
print('Could not find raw test result for %s' % raw_test)
return 0
diff --git a/scripts/lib/resulttool/resultutils.py b/scripts/lib/resulttool/resultutils.py
index c5521d81bd..8fd4e0a9cf 100644
--- a/scripts/lib/resulttool/resultutils.py
+++ b/scripts/lib/resulttool/resultutils.py
@@ -169,7 +169,7 @@ def save_resultsdata(results, destdir, fn="testresults.json", ptestjson=False, p
if not ptestjson:
resultsout = strip_ptestresults(results[res])
with open(dst, 'w') as f:
- f.write(json.dumps(resultsout, sort_keys=True, indent=4))
+ f.write(json.dumps(resultsout, sort_keys=True, indent=1))
for res2 in results[res]:
if ptestlogs and 'result' in results[res][res2]:
seriesresults = results[res][res2]['result']
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 32/38] oeqa/utils/gitarchive: Return tag name and improve exclude handling
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (30 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 31/38] resulttool: Use single space indentation in json output Steve Sakoman
@ 2024-12-04 17:53 ` Steve Sakoman
2024-12-04 17:54 ` [OE-core][kirkstone 33/38] resulttool: Fix passthrough of --all files in store mode Steve Sakoman
` (5 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:53 UTC (permalink / raw)
To: openembedded-core
From: Richard Purdie <richard.purdie@linuxfoundation.org>
Tweak the gitarchive exclude handling not to error if excluded files
don't match.
Also return the tagname created so that other code can then use it.
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit 1adba3430faffdf6217b6a00533a3b48a9388abc)
Signed-off-by: Steve Sakoman <steve@sakoman.com>
---
meta/lib/oeqa/utils/gitarchive.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/meta/lib/oeqa/utils/gitarchive.py b/meta/lib/oeqa/utils/gitarchive.py
index 6e8040eb5c..6db8c99147 100644
--- a/meta/lib/oeqa/utils/gitarchive.py
+++ b/meta/lib/oeqa/utils/gitarchive.py
@@ -67,7 +67,7 @@ def git_commit_data(repo, data_dir, branch, message, exclude, notes, log):
# Remove files that are excluded
if exclude:
- repo.run_cmd(['rm', '--cached'] + [f for f in exclude], env_update)
+ repo.run_cmd(['rm', '--cached', '--ignore-unmatch'] + [f for f in exclude], env_update)
tree = repo.run_cmd('write-tree', env_update)
@@ -166,6 +166,8 @@ def gitarchive(data_dir, git_dir, no_create, bare, commit_msg_subject, commit_ms
log.info("Pushing data to remote")
data_repo.run_cmd(cmd)
+ return tag_name
+
# Container class for tester revisions
TestedRev = namedtuple('TestedRev', 'commit commit_number tags')
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 33/38] resulttool: Fix passthrough of --all files in store mode
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (31 preceding siblings ...)
2024-12-04 17:53 ` [OE-core][kirkstone 32/38] oeqa/utils/gitarchive: Return tag name and improve exclude handling Steve Sakoman
@ 2024-12-04 17:54 ` Steve Sakoman
2024-12-04 17:54 ` [OE-core][kirkstone 34/38] resulttool: Add --logfile-archive option to " Steve Sakoman
` (4 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:54 UTC (permalink / raw)
To: openembedded-core
From: Richard Purdie <richard.purdie@linuxfoundation.org>
When using store mode, --all was broken as not all files were being preserved.
Fix this by limiting the scope of the git rm command.
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit 9604561d2022b6c76b1cb4186d40800d1affdd2b)
Signed-off-by: Steve Sakoman <steve@sakoman.com>
---
scripts/lib/resulttool/store.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/lib/resulttool/store.py b/scripts/lib/resulttool/store.py
index 430213bbfe..903e29627a 100644
--- a/scripts/lib/resulttool/store.py
+++ b/scripts/lib/resulttool/store.py
@@ -69,7 +69,7 @@ def store(args, logger):
logger.info('skipping %s as non-matching' % r[0])
continue
keywords = {'commit': r[0], 'branch': r[1], "commit_count": r[2]}
- subprocess.check_call(["find", tempdir, "!", "-path", "./.git/*", "-delete"])
+ subprocess.check_call(["find", tempdir, "-name", "testresults.json", "!", "-path", "./.git/*", "-delete"])
resultutils.save_resultsdata(results, tempdir, ptestlogs=True)
logger.info('Storing test result into git repository %s' % args.git_dir)
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 34/38] resulttool: Add --logfile-archive option to store mode
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (32 preceding siblings ...)
2024-12-04 17:54 ` [OE-core][kirkstone 33/38] resulttool: Fix passthrough of --all files in store mode Steve Sakoman
@ 2024-12-04 17:54 ` Steve Sakoman
2024-12-04 17:54 ` [OE-core][kirkstone 35/38] resulttool: Handle ltp rawlogs as well as ptest Steve Sakoman
` (3 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:54 UTC (permalink / raw)
To: openembedded-core
From: Richard Purdie <richard.purdie@linuxfoundation.org>
Storing the log files inside the testresults git repo isn't scaling and isn't
really appropriate use of a git repository. Allow these to be optionally stored
in a separate filesystem location so the git repo can remain managable.
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit 1afc0f3d7e93fa8496be241e9622d3b9a6904bd5)
Signed-off-by: Steve Sakoman <steve@sakoman.com>
---
scripts/lib/resulttool/store.py | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/scripts/lib/resulttool/store.py b/scripts/lib/resulttool/store.py
index 903e29627a..578910d234 100644
--- a/scripts/lib/resulttool/store.py
+++ b/scripts/lib/resulttool/store.py
@@ -74,12 +74,25 @@ def store(args, logger):
logger.info('Storing test result into git repository %s' % args.git_dir)
- gitarchive.gitarchive(tempdir, args.git_dir, False, False,
+ excludes = []
+ if args.logfile_archive:
+ excludes = ['*.log', "*.log.zst"]
+
+ tagname = gitarchive.gitarchive(tempdir, args.git_dir, False, False,
"Results of {branch}:{commit}", "branch: {branch}\ncommit: {commit}", "{branch}",
False, "{branch}/{commit_count}-g{commit}/{tag_number}",
'Test run #{tag_number} of {branch}:{commit}', '',
- [], [], False, keywords, logger)
+ excludes, [], False, keywords, logger)
+ if args.logfile_archive:
+ logdir = args.logfile_archive + "/" + tagname
+ shutil.copytree(tempdir, logdir)
+ for root, dirs, files in os.walk(logdir):
+ for name in files:
+ if not name.endswith(".log"):
+ continue
+ f = os.path.join(root, name)
+ subprocess.run(["zstd", f, "--rm"], check=True, capture_output=True)
finally:
subprocess.check_call(["rm", "-rf", tempdir])
@@ -107,3 +120,5 @@ def register_commands(subparsers):
help='add extra test environment data to each result file configuration')
parser_build.add_argument('-r', '--revision', default='',
help='only store data for the specified revision')
+ parser_build.add_argument('-l', '--logfile-archive', default='',
+ help='directory to separately archive log files along with a copy of the results')
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 35/38] resulttool: Handle ltp rawlogs as well as ptest
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (33 preceding siblings ...)
2024-12-04 17:54 ` [OE-core][kirkstone 34/38] resulttool: Add --logfile-archive option to " Steve Sakoman
@ 2024-12-04 17:54 ` Steve Sakoman
2024-12-04 17:54 ` [OE-core][kirkstone 36/38] resulttool: Clean up repoducible build logs Steve Sakoman
` (2 subsequent siblings)
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:54 UTC (permalink / raw)
To: openembedded-core
From: Richard Purdie <richard.purdie@linuxfoundation.org>
Improve the rawlogs handling to include ltp logs as well as the ptest ones to
reduce the size of the results git repos.
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit a0a1954d559609c2c1ca16936d0d68eb3c4c6b45)
Signed-off-by: Steve Sakoman <steve@sakoman.com>
---
scripts/lib/resulttool/resultutils.py | 33 ++++++++++++++++-----------
1 file changed, 20 insertions(+), 13 deletions(-)
diff --git a/scripts/lib/resulttool/resultutils.py b/scripts/lib/resulttool/resultutils.py
index 8fd4e0a9cf..b9b93afaa6 100644
--- a/scripts/lib/resulttool/resultutils.py
+++ b/scripts/lib/resulttool/resultutils.py
@@ -14,8 +14,11 @@ import scriptpath
import copy
import urllib.request
import posixpath
+import logging
scriptpath.add_oe_lib_path()
+logger = logging.getLogger('resulttool')
+
flatten_map = {
"oeselftest": [],
"runtime": [],
@@ -38,6 +41,12 @@ store_map = {
"manual": ['TEST_TYPE', 'TEST_MODULE', 'MACHINE', 'IMAGE_BASENAME']
}
+rawlog_sections = {
+ "ptestresult.rawlogs": "ptest",
+ "ltpresult.rawlogs": "ltp",
+ "ltpposixresult.rawlogs": "ltpposix"
+}
+
def is_url(p):
"""
Helper for determining if the given path is a URL
@@ -108,15 +117,14 @@ def filter_resultsdata(results, resultid):
newresults[r][i] = results[r][i]
return newresults
-def strip_ptestresults(results):
+def strip_logs(results):
newresults = copy.deepcopy(results)
- #for a in newresults2:
- # newresults = newresults2[a]
for res in newresults:
if 'result' not in newresults[res]:
continue
- if 'ptestresult.rawlogs' in newresults[res]['result']:
- del newresults[res]['result']['ptestresult.rawlogs']
+ for logtype in rawlog_sections:
+ if logtype in newresults[res]['result']:
+ del newresults[res]['result'][logtype]
if 'ptestresult.sections' in newresults[res]['result']:
for i in newresults[res]['result']['ptestresult.sections']:
if 'log' in newresults[res]['result']['ptestresult.sections'][i]:
@@ -155,9 +163,6 @@ def generic_get_rawlogs(sectname, results):
return None
return decode_log(results[sectname]['log'])
-def ptestresult_get_rawlogs(results):
- return generic_get_rawlogs('ptestresult.rawlogs', results)
-
def save_resultsdata(results, destdir, fn="testresults.json", ptestjson=False, ptestlogs=False):
for res in results:
if res:
@@ -167,16 +172,18 @@ def save_resultsdata(results, destdir, fn="testresults.json", ptestjson=False, p
os.makedirs(os.path.dirname(dst), exist_ok=True)
resultsout = results[res]
if not ptestjson:
- resultsout = strip_ptestresults(results[res])
+ resultsout = strip_logs(results[res])
with open(dst, 'w') as f:
f.write(json.dumps(resultsout, sort_keys=True, indent=1))
for res2 in results[res]:
if ptestlogs and 'result' in results[res][res2]:
seriesresults = results[res][res2]['result']
- rawlogs = ptestresult_get_rawlogs(seriesresults)
- if rawlogs is not None:
- with open(dst.replace(fn, "ptest-raw.log"), "w+") as f:
- f.write(rawlogs)
+ for logtype in rawlog_sections:
+ logdata = generic_get_rawlogs(logtype, seriesresults)
+ if logdata is not None:
+ logger.info("Extracting " + rawlog_sections[logtype] + "-raw.log")
+ with open(dst.replace(fn, rawlog_sections[logtype] + "-raw.log"), "w+") as f:
+ f.write(logdata)
if 'ptestresult.sections' in seriesresults:
for i in seriesresults['ptestresult.sections']:
sectionlog = ptestresult_get_log(seriesresults, i)
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 36/38] resulttool: Clean up repoducible build logs
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (34 preceding siblings ...)
2024-12-04 17:54 ` [OE-core][kirkstone 35/38] resulttool: Handle ltp rawlogs as well as ptest Steve Sakoman
@ 2024-12-04 17:54 ` Steve Sakoman
2024-12-04 17:54 ` [OE-core][kirkstone 37/38] resulttool: Trim the precision of duration information Steve Sakoman
2024-12-04 17:54 ` [OE-core][kirkstone 38/38] resulttool: Improve repo layout for oeselftest results Steve Sakoman
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:54 UTC (permalink / raw)
To: openembedded-core
From: Richard Purdie <richard.purdie@linuxfoundation.org>
We've improved the data stored for reproduicible builds. Teach resulttool how
to apply those cleanups when reprocessing data so we can reduce results file
sizes and make the data easier to process.
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit b799c57ae6d61c1b1c7035c8a2c4ba6ee08d1a81)
Signed-off-by: Steve Sakoman <steve@sakoman.com>
---
scripts/lib/resulttool/resultutils.py | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/scripts/lib/resulttool/resultutils.py b/scripts/lib/resulttool/resultutils.py
index b9b93afaa6..9cba8639a3 100644
--- a/scripts/lib/resulttool/resultutils.py
+++ b/scripts/lib/resulttool/resultutils.py
@@ -131,6 +131,27 @@ def strip_logs(results):
del newresults[res]['result']['ptestresult.sections'][i]['log']
return newresults
+def handle_cleanups(results):
+ # Remove pointless path duplication from old format reproducibility results
+ for res2 in results:
+ try:
+ section = results[res2]['result']['reproducible']['files']
+ for pkgtype in section:
+ for filelist in section[pkgtype].copy():
+ if section[pkgtype][filelist] and type(section[pkgtype][filelist][0]) == dict:
+ newlist = []
+ for entry in section[pkgtype][filelist]:
+ newlist.append(entry["reference"].split("/./")[1])
+ section[pkgtype][filelist] = newlist
+
+ except KeyError:
+ pass
+ # Remove pointless duplicate rawlogs data
+ try:
+ del results[res2]['result']['reproducible.rawlogs']
+ except KeyError:
+ pass
+
def decode_log(logdata):
if isinstance(logdata, str):
return logdata
@@ -173,6 +194,7 @@ def save_resultsdata(results, destdir, fn="testresults.json", ptestjson=False, p
resultsout = results[res]
if not ptestjson:
resultsout = strip_logs(results[res])
+ handle_cleanups(resultsout)
with open(dst, 'w') as f:
f.write(json.dumps(resultsout, sort_keys=True, indent=1))
for res2 in results[res]:
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 37/38] resulttool: Trim the precision of duration information
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (35 preceding siblings ...)
2024-12-04 17:54 ` [OE-core][kirkstone 36/38] resulttool: Clean up repoducible build logs Steve Sakoman
@ 2024-12-04 17:54 ` Steve Sakoman
2024-12-04 17:54 ` [OE-core][kirkstone 38/38] resulttool: Improve repo layout for oeselftest results Steve Sakoman
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:54 UTC (permalink / raw)
To: openembedded-core
From: Richard Purdie <richard.purdie@linuxfoundation.org>
The duration values have pointless amounts of precision. Removing some of the
least significant digits reduces result size and makes the results easier to read.
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit a789a2e6d97bb8efd663226a17db8d1ca6c1e40f)
Signed-off-by: Steve Sakoman <steve@sakoman.com>
---
scripts/lib/resulttool/resultutils.py | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/scripts/lib/resulttool/resultutils.py b/scripts/lib/resulttool/resultutils.py
index 9cba8639a3..760e426de0 100644
--- a/scripts/lib/resulttool/resultutils.py
+++ b/scripts/lib/resulttool/resultutils.py
@@ -131,6 +131,22 @@ def strip_logs(results):
del newresults[res]['result']['ptestresult.sections'][i]['log']
return newresults
+# For timing numbers, crazy amounts of precision don't make sense and just confuse
+# the logs. For numbers over 1, trim to 3 decimal places, for numbers less than 1,
+# trim to 4 significant digits
+def trim_durations(results):
+ for res in results:
+ if 'result' not in results[res]:
+ continue
+ for entry in results[res]['result']:
+ if 'duration' in results[res]['result'][entry]:
+ duration = results[res]['result'][entry]['duration']
+ if duration > 1:
+ results[res]['result'][entry]['duration'] = float("%.3f" % duration)
+ elif duration < 1:
+ results[res]['result'][entry]['duration'] = float("%.4g" % duration)
+ return results
+
def handle_cleanups(results):
# Remove pointless path duplication from old format reproducibility results
for res2 in results:
@@ -194,6 +210,7 @@ def save_resultsdata(results, destdir, fn="testresults.json", ptestjson=False, p
resultsout = results[res]
if not ptestjson:
resultsout = strip_logs(results[res])
+ trim_durations(resultsout)
handle_cleanups(resultsout)
with open(dst, 'w') as f:
f.write(json.dumps(resultsout, sort_keys=True, indent=1))
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 38/38] resulttool: Improve repo layout for oeselftest results
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
` (36 preceding siblings ...)
2024-12-04 17:54 ` [OE-core][kirkstone 37/38] resulttool: Trim the precision of duration information Steve Sakoman
@ 2024-12-04 17:54 ` Steve Sakoman
37 siblings, 0 replies; 40+ messages in thread
From: Steve Sakoman @ 2024-12-04 17:54 UTC (permalink / raw)
To: openembedded-core
From: Richard Purdie <richard.purdie@linuxfoundation.org>
Having all oe-selftest results on top of each other results in a large 640MB
json file which is hard to use. Split the results out per machine and test type.
This also stops the toolchain raw logs from overwriting each other meaning more
than one MACHINE is preserved.
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit 4b890f04bc7d147b4a11b824a84f3d2abd75ac54)
Signed-off-by: Steve Sakoman <steve@sakoman.com>
---
scripts/lib/resulttool/resultutils.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/lib/resulttool/resultutils.py b/scripts/lib/resulttool/resultutils.py
index 760e426de0..b8fc79a6ac 100644
--- a/scripts/lib/resulttool/resultutils.py
+++ b/scripts/lib/resulttool/resultutils.py
@@ -34,7 +34,7 @@ regression_map = {
"manual": ['TEST_TYPE', 'TEST_MODULE', 'IMAGE_BASENAME', 'MACHINE']
}
store_map = {
- "oeselftest": ['TEST_TYPE'],
+ "oeselftest": ['TEST_TYPE', 'TESTSERIES', 'MACHINE'],
"runtime": ['TEST_TYPE', 'DISTRO', 'MACHINE', 'IMAGE_BASENAME'],
"sdk": ['TEST_TYPE', 'MACHINE', 'SDKMACHINE', 'IMAGE_BASENAME'],
"sdkext": ['TEST_TYPE', 'MACHINE', 'SDKMACHINE', 'IMAGE_BASENAME'],
--
2.34.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [OE-core][kirkstone 00/38] Patch review
@ 2026-02-24 14:23 Yoann Congal
0 siblings, 0 replies; 40+ messages in thread
From: Yoann Congal @ 2026-02-24 14:23 UTC (permalink / raw)
To: openembedded-core
Please review this set of changes for kirkstone and have comments back by
end of day Thursday, February 26.
Passed a-full on autobuilder:
https://autobuilder.yoctoproject.org/valkyrie/?#/builders/29/builds/3274
The following changes since commit e2994ca0076ec99038790e7a40936236a5078135:
build-appliance-image: Update to kirkstone head revision (2026-01-26 18:54:26 +0000)
are available in the Git repository at:
https://git.openembedded.org/openembedded-core-contrib stable/kirkstone-nut
https://git.openembedded.org/openembedded-core-contrib/log/?h=stable/kirkstone-nut
for you to fetch changes up to fd883ff6432946d23d923a9be1cd2cb1f001c732:
u-boot: move CVE patch out of u-boot-common.inc (2026-02-23 23:57:02 +0100)
----------------------------------------------------------------
Aleksandar Nikolic (1):
scripts/install-buildtools: Update to 4.0.32
Amaury Couderc (2):
avahi: patch CVE-2025-68468
avahi: patch CVE-2025-68471
Ankur Tyagi (2):
avahi: patch CVE-2025-68276
avahi: patch CVE-2026-24401
Bruce Ashfield (5):
linux-yocto/5.15: update to v5.15.195
linux-yocto/5.15: update to v5.15.196
linux-yocto/5.15: update to v5.15.197
linux-yocto/5.15: update to v5.15.198
linux-yocto/5.15: update to v5.15.199
Fabio Berton (1):
classes/buildhistory: Do not sign buildhistory commits
Hugo SIMELIERE (1):
libtasn1: Fix CVE-2025-13151
Peter Marko (20):
zlib: ignore CVE-2026-22184
python3: patch CVE-2025-13837
python3: patch CVE-2025-12084
libxml2: patch CVE-2026-0990
libxml2: patch CVE-2026-0992
libxml2: add follow-up patch for CVE-2026-0992
expat: patch CVE-2026-24515
expat: patch CVE-2026-25210
inetutils: patch CVE-2026-24061
libpng: patch CVE-2026-22695
libpng: patch CVE-2026-22801
libpng: patch CVE-2026-25646
glib-2.0: patch CVE-2026-0988
glib-2.0: patch CVE-2026-1484
glib-2.0: patch CVE-2026-1485
glib-2.0: patch CVE-2026-1489
ffmpeg: set status of CVE-2025-25468 and CVE-2025-25469
vim: ignore CVE-2025-66476
harfbuzz: ignore CVE-2026-22693
glibc: stable 2.35 branch updates
Richard Purdie (2):
pseudo: Update to 1.9.3 release
pseudo: Update to include an openat2 fix
Scott Murray (1):
u-boot: move CVE patch out of u-boot-common.inc
Vijay Anusuri (2):
openssl: upgrade 3.0.18 -> 3.0.19
bind: Upgrade 9.18.41 -> 9.18.44
Yoann Congal (1):
pseudo: Update to include a fix for systems with kernel <5.6
meta/classes/buildhistory.bbclass | 2 +-
meta/recipes-bsp/u-boot/u-boot-common.inc | 4 +-
meta/recipes-bsp/u-boot/u-boot_2022.01.bb | 1 +
meta/recipes-connectivity/avahi/avahi_0.8.bb | 4 +
.../avahi/files/CVE-2025-68276.patch | 65 ++++
.../avahi/files/CVE-2025-68468.patch | 32 ++
.../avahi/files/CVE-2025-68471.patch | 36 ++
.../avahi/files/CVE-2026-24401.patch | 74 ++++
.../bind/{bind_9.18.41.bb => bind_9.18.44.bb} | 2 +-
.../inetutils/CVE-2026-24061-01.patch | 38 ++
.../inetutils/CVE-2026-24061-02.patch | 82 +++++
.../inetutils/inetutils_2.2.bb | 2 +
.../openssl/openssl/CVE-2023-50781-1.patch | 46 ++-
.../openssl/openssl/CVE-2023-50781-2.patch | 112 +++---
.../openssl/openssl/CVE-2023-50781-3.patch | 16 +-
.../{openssl_3.0.18.bb => openssl_3.0.19.bb} | 2 +-
.../expat/expat/CVE-2026-24515.patch | 43 +++
.../expat/expat/CVE-2026-25210-01.patch | 27 ++
.../expat/expat/CVE-2026-25210-02.patch | 37 ++
.../expat/expat/CVE-2026-25210-03.patch | 28 ++
meta/recipes-core/expat/expat_2.5.0.bb | 4 +
.../glib-2.0/glib-2.0/CVE-2026-0988.patch | 58 ++++
.../glib-2.0/glib-2.0/CVE-2026-1484-01.patch | 48 +++
.../glib-2.0/glib-2.0/CVE-2026-1484-02.patch | 45 +++
.../glib-2.0/glib-2.0/CVE-2026-1485.patch | 44 +++
.../glib-2.0/glib-2.0/CVE-2026-1489-01.patch | 42 +++
.../glib-2.0/glib-2.0/CVE-2026-1489-02.patch | 30 ++
.../glib-2.0/glib-2.0/CVE-2026-1489-03.patch | 290 ++++++++++++++++
.../glib-2.0/glib-2.0/CVE-2026-1489-04.patch | 68 ++++
meta/recipes-core/glib-2.0/glib-2.0_2.72.3.bb | 8 +
meta/recipes-core/glibc/glibc-version.inc | 2 +-
meta/recipes-core/glibc/glibc_2.35.bb | 3 +-
.../libxml/libxml2/CVE-2026-0990.patch | 76 ++++
.../libxml/libxml2/CVE-2026-0992-01.patch | 49 +++
.../libxml/libxml2/CVE-2026-0992-02.patch | 325 ++++++++++++++++++
.../libxml/libxml2/CVE-2026-0992-03.patch | 33 ++
meta/recipes-core/libxml/libxml2_2.9.14.bb | 4 +
meta/recipes-core/zlib/zlib_1.2.11.bb | 2 +
meta/recipes-devtools/pseudo/pseudo_git.bb | 4 +-
.../python/python3/CVE-2025-12084.patch | 171 +++++++++
.../python/python3/CVE-2025-13837.patch | 162 +++++++++
.../python/python3_3.10.19.bb | 2 +
.../harfbuzz/harfbuzz_4.0.1.bb | 3 +
.../linux/linux-yocto-rt_5.15.bb | 6 +-
.../linux/linux-yocto-tiny_5.15.bb | 6 +-
meta/recipes-kernel/linux/linux-yocto_5.15.bb | 26 +-
.../recipes-multimedia/ffmpeg/ffmpeg_5.0.3.bb | 5 +
.../libpng/files/CVE-2026-22695.patch | 77 +++++
.../libpng/files/CVE-2026-22801.patch | 164 +++++++++
.../libpng/files/CVE-2026-25646.patch | 61 ++++
.../libpng/libpng_1.6.39.bb | 3 +
.../gnutls/libtasn1/CVE-2025-13151.patch | 30 ++
.../recipes-support/gnutls/libtasn1_4.20.0.bb | 1 +
meta/recipes-support/vim/vim_9.1.bb | 3 +
scripts/install-buildtools | 4 +-
55 files changed, 2391 insertions(+), 121 deletions(-)
create mode 100644 meta/recipes-connectivity/avahi/files/CVE-2025-68276.patch
create mode 100644 meta/recipes-connectivity/avahi/files/CVE-2025-68468.patch
create mode 100644 meta/recipes-connectivity/avahi/files/CVE-2025-68471.patch
create mode 100644 meta/recipes-connectivity/avahi/files/CVE-2026-24401.patch
rename meta/recipes-connectivity/bind/{bind_9.18.41.bb => bind_9.18.44.bb} (97%)
create mode 100644 meta/recipes-connectivity/inetutils/inetutils/CVE-2026-24061-01.patch
create mode 100644 meta/recipes-connectivity/inetutils/inetutils/CVE-2026-24061-02.patch
rename meta/recipes-connectivity/openssl/{openssl_3.0.18.bb => openssl_3.0.19.bb} (99%)
create mode 100644 meta/recipes-core/expat/expat/CVE-2026-24515.patch
create mode 100644 meta/recipes-core/expat/expat/CVE-2026-25210-01.patch
create mode 100644 meta/recipes-core/expat/expat/CVE-2026-25210-02.patch
create mode 100644 meta/recipes-core/expat/expat/CVE-2026-25210-03.patch
create mode 100644 meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-0988.patch
create mode 100644 meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-1484-01.patch
create mode 100644 meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-1484-02.patch
create mode 100644 meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-1485.patch
create mode 100644 meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-1489-01.patch
create mode 100644 meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-1489-02.patch
create mode 100644 meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-1489-03.patch
create mode 100644 meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-1489-04.patch
create mode 100644 meta/recipes-core/libxml/libxml2/CVE-2026-0990.patch
create mode 100644 meta/recipes-core/libxml/libxml2/CVE-2026-0992-01.patch
create mode 100644 meta/recipes-core/libxml/libxml2/CVE-2026-0992-02.patch
create mode 100644 meta/recipes-core/libxml/libxml2/CVE-2026-0992-03.patch
create mode 100644 meta/recipes-devtools/python/python3/CVE-2025-12084.patch
create mode 100644 meta/recipes-devtools/python/python3/CVE-2025-13837.patch
create mode 100644 meta/recipes-multimedia/libpng/files/CVE-2026-22695.patch
create mode 100644 meta/recipes-multimedia/libpng/files/CVE-2026-22801.patch
create mode 100644 meta/recipes-multimedia/libpng/files/CVE-2026-25646.patch
create mode 100644 meta/recipes-support/gnutls/libtasn1/CVE-2025-13151.patch
^ permalink raw reply [flat|nested] 40+ messages in thread
end of thread, other threads:[~2026-02-24 14:25 UTC | newest]
Thread overview: 40+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-04 17:53 [OE-core][kirkstone 00/38] Patch review Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 01/38] ovmf: Fix CVE-2022-36763 Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 02/38] ovmf: Fix CVE-2022-36764 Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 03/38] ovmf: Fix CVE-2023-45230 Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 04/38] ovmf: Fix CVE-2023-45231 Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 05/38] ovmf: Fix CVE-2023-45232, CVE-2023-45233 Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 06/38] ovmf: Fix CVE-2023-45234 Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 07/38] ovmf: Fix CVE-2023-45235 Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 08/38] ovmf: Fix CVE-2023-45229 Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 09/38] ovmf: Fix CVE-2023-45237 Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 10/38] ovmf: Fix CVE-2023-45236 Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 11/38] ovmf: Fix CVE-2022-36765 Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 12/38] ovmf: fix CVE-2024-38796 Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 13/38] ovmf: fix CVE-2024-1298 Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 14/38] libsoup: fix CVE-2024-52531 Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 15/38] python3-zipp: fix CVE-2024-5569 Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 16/38] libsoup-2.4: Backport fix for CVE-2024-52531 Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 17/38] cpio: ignore CVE-2023-7216 Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 18/38] gnupg: ignore CVE-2022-3515 Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 19/38] qemu: ignore CVE-2022-36648 Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 20/38] grub: ignore CVE-2024-1048 and CVE-2023-4001 Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 21/38] pixman: ignore CVE-2023-37769 Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 22/38] qemu: patch CVE-2024-6505 Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 23/38] qemu: fix CVE-2024-3446 Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 24/38] qemu: fix CVE-2024-3447 Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 25/38] diffoscope: fix CVE-2024-25711 Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 26/38] do_package/sstate/sstatesig: Change timestamp clamping to hash output only Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 27/38] rxvt-unicode.inc: disable the terminfo installation by setting TIC to : Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 28/38] selftest/reproducible: Drop rawlogs Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 29/38] selftest/reproducible: Clean up pathnames Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 30/38] resulttool: Allow store to filter to specific revisions Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 31/38] resulttool: Use single space indentation in json output Steve Sakoman
2024-12-04 17:53 ` [OE-core][kirkstone 32/38] oeqa/utils/gitarchive: Return tag name and improve exclude handling Steve Sakoman
2024-12-04 17:54 ` [OE-core][kirkstone 33/38] resulttool: Fix passthrough of --all files in store mode Steve Sakoman
2024-12-04 17:54 ` [OE-core][kirkstone 34/38] resulttool: Add --logfile-archive option to " Steve Sakoman
2024-12-04 17:54 ` [OE-core][kirkstone 35/38] resulttool: Handle ltp rawlogs as well as ptest Steve Sakoman
2024-12-04 17:54 ` [OE-core][kirkstone 36/38] resulttool: Clean up repoducible build logs Steve Sakoman
2024-12-04 17:54 ` [OE-core][kirkstone 37/38] resulttool: Trim the precision of duration information Steve Sakoman
2024-12-04 17:54 ` [OE-core][kirkstone 38/38] resulttool: Improve repo layout for oeselftest results Steve Sakoman
-- strict thread matches above, loose matches on Subject: below --
2026-02-24 14:23 [OE-core][kirkstone 00/38] Patch review Yoann Congal
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox