parent
c2949809b1
commit
da78271174
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,149 @@
|
||||
From 9ef10bbe9a03f22aa5c5ff659012794d37ef9839 Mon Sep 17 00:00:00 2001
|
||||
From: Ard Biesheuvel <ardb@kernel.org>
|
||||
Date: Mon, 24 Oct 2022 18:41:22 +0200
|
||||
Subject: [PATCH 17/18] ArmVirtPkg/ArmVirtQemu: migrate to OVMF's
|
||||
VirtNorFlashDxe
|
||||
|
||||
RH-Author: Gerd Hoffmann <None>
|
||||
RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport
|
||||
RH-Jira: RHEL-17587
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [19/20] 2160140b0ea566451ab723e941d2ab91e1ad874e
|
||||
|
||||
Switch to the virt specific NorFlashDxe driver implementation that was
|
||||
added recently.
|
||||
|
||||
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
|
||||
Reviewed-by: Sunil V L <sunilvl@ventanamicro.com>
|
||||
(cherry picked from commit b92298af8218dd074c231947bc95f2be94af663c)
|
||||
---
|
||||
ArmVirtPkg/ArmVirtQemu.dsc | 4 ++--
|
||||
ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc | 2 +-
|
||||
ArmVirtPkg/ArmVirtQemuKernel.dsc | 4 ++--
|
||||
ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c | 12 ++++++------
|
||||
.../Library/NorFlashQemuLib/NorFlashQemuLib.inf | 4 ++--
|
||||
5 files changed, 13 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/ArmVirtPkg/ArmVirtQemu.dsc b/ArmVirtPkg/ArmVirtQemu.dsc
|
||||
index e6fad9f066..2b23becf30 100644
|
||||
--- a/ArmVirtPkg/ArmVirtQemu.dsc
|
||||
+++ b/ArmVirtPkg/ArmVirtQemu.dsc
|
||||
@@ -67,7 +67,7 @@
|
||||
ArmPlatformLib|ArmPlatformPkg/Library/ArmPlatformLibNull/ArmPlatformLibNull.inf
|
||||
|
||||
TimerLib|ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.inf
|
||||
- NorFlashPlatformLib|ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf
|
||||
+ VirtNorFlashPlatformLib|ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf
|
||||
|
||||
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
|
||||
BootLogoLib|MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
|
||||
@@ -400,7 +400,7 @@
|
||||
<LibraryClasses>
|
||||
NULL|ArmVirtPkg/Library/ArmVirtTimerFdtClientLib/ArmVirtTimerFdtClientLib.inf
|
||||
}
|
||||
- ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
|
||||
+ OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf
|
||||
MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
|
||||
|
||||
#
|
||||
diff --git a/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc b/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc
|
||||
index f6a538df72..7c655d384d 100644
|
||||
--- a/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc
|
||||
+++ b/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc
|
||||
@@ -73,7 +73,7 @@ READ_LOCK_STATUS = TRUE
|
||||
|
||||
INF ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
|
||||
INF ArmPkg/Drivers/TimerDxe/TimerDxe.inf
|
||||
- INF ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
|
||||
+ INF OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf
|
||||
INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
|
||||
|
||||
#
|
||||
diff --git a/ArmVirtPkg/ArmVirtQemuKernel.dsc b/ArmVirtPkg/ArmVirtQemuKernel.dsc
|
||||
index 656c9d99a3..344e2c4ed9 100644
|
||||
--- a/ArmVirtPkg/ArmVirtQemuKernel.dsc
|
||||
+++ b/ArmVirtPkg/ArmVirtQemuKernel.dsc
|
||||
@@ -65,7 +65,7 @@
|
||||
ArmVirtMemInfoLib|ArmVirtPkg/Library/QemuVirtMemInfoLib/QemuVirtMemInfoLib.inf
|
||||
|
||||
TimerLib|ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.inf
|
||||
- NorFlashPlatformLib|ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf
|
||||
+ VirtNorFlashPlatformLib|ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf
|
||||
|
||||
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
|
||||
BootLogoLib|MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
|
||||
@@ -329,7 +329,7 @@
|
||||
<LibraryClasses>
|
||||
NULL|ArmVirtPkg/Library/ArmVirtTimerFdtClientLib/ArmVirtTimerFdtClientLib.inf
|
||||
}
|
||||
- ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
|
||||
+ OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf
|
||||
MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
|
||||
|
||||
#
|
||||
diff --git a/ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c b/ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c
|
||||
index 271d7f0efb..93a2fed40f 100644
|
||||
--- a/ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c
|
||||
+++ b/ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
-#include <Library/NorFlashPlatformLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
+#include <Library/VirtNorFlashPlatformLib.h>
|
||||
|
||||
#include <Protocol/FdtClient.h>
|
||||
|
||||
@@ -18,19 +18,19 @@
|
||||
#define MAX_FLASH_BANKS 4
|
||||
|
||||
EFI_STATUS
|
||||
-NorFlashPlatformInitialization (
|
||||
+VirtNorFlashPlatformInitialization (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
-NOR_FLASH_DESCRIPTION mNorFlashDevices[MAX_FLASH_BANKS];
|
||||
+STATIC VIRT_NOR_FLASH_DESCRIPTION mNorFlashDevices[MAX_FLASH_BANKS];
|
||||
|
||||
EFI_STATUS
|
||||
-NorFlashPlatformGetDevices (
|
||||
- OUT NOR_FLASH_DESCRIPTION **NorFlashDescriptions,
|
||||
- OUT UINT32 *Count
|
||||
+VirtNorFlashPlatformGetDevices (
|
||||
+ OUT VIRT_NOR_FLASH_DESCRIPTION **NorFlashDescriptions,
|
||||
+ OUT UINT32 *Count
|
||||
)
|
||||
{
|
||||
FDT_CLIENT_PROTOCOL *FdtClient;
|
||||
diff --git a/ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf b/ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf
|
||||
index 4c3683bf5d..a6b5865be9 100644
|
||||
--- a/ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf
|
||||
+++ b/ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf
|
||||
@@ -14,17 +14,17 @@
|
||||
FILE_GUID = 339B7829-4C5F-4EFC-B2DD-5050E530DECE
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
- LIBRARY_CLASS = NorFlashPlatformLib
|
||||
+ LIBRARY_CLASS = VirtNorFlashPlatformLib
|
||||
|
||||
[Sources.common]
|
||||
NorFlashQemuLib.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
- ArmPlatformPkg/ArmPlatformPkg.dec
|
||||
ArmPkg/ArmPkg.dec
|
||||
ArmVirtPkg/ArmVirtPkg.dec
|
||||
EmbeddedPkg/EmbeddedPkg.dec
|
||||
+ OvmfPkg/OvmfPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,174 @@
|
||||
From f8691984227809170b702f6fd087add1f95ee8fe Mon Sep 17 00:00:00 2001
|
||||
From: Jon Maloy <jmaloy@redhat.com>
|
||||
Date: Tue, 5 Mar 2024 16:38:49 -0500
|
||||
Subject: [PATCH 1/2] EmbeddedPkg/Hob: Integer Overflow in CreateHob()
|
||||
|
||||
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-MergeRequest: 66: EmbeddedPkg/Hob: Integer Overflow in CreateHob()
|
||||
RH-Jira: RHEL-21158
|
||||
RH-Acked-by: Oliver Steffen <osteffen@redhat.com>
|
||||
RH-Acked-by: Gerd Hoffmann <None>
|
||||
RH-Commit: [1/2] 301d3bfe82c39179fb85d510788831aa340212d9
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-21158
|
||||
CVE: CVE-2022-36765
|
||||
Upstream: Merged
|
||||
|
||||
commit aeaee8944f0eaacbf4cdf39279785b9ba4836bb6
|
||||
Author: Gua Guo <gua.guo@intel.com>
|
||||
Date: Thu Jan 11 13:07:50 2024 +0800
|
||||
|
||||
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>
|
||||
|
||||
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
|
||||
---
|
||||
EmbeddedPkg/Library/PrePiHobLib/Hob.c | 47 +++++++++++++++++++++++++--
|
||||
1 file changed, 45 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/EmbeddedPkg/Library/PrePiHobLib/Hob.c b/EmbeddedPkg/Library/PrePiHobLib/Hob.c
|
||||
index b5cc6c5d8f..f4c99369c6 100644
|
||||
--- a/EmbeddedPkg/Library/PrePiHobLib/Hob.c
|
||||
+++ b/EmbeddedPkg/Library/PrePiHobLib/Hob.c
|
||||
@@ -112,6 +112,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;
|
||||
@@ -161,7 +168,10 @@ BuildResourceDescriptorHob (
|
||||
EFI_HOB_RESOURCE_DESCRIPTOR *Hob;
|
||||
|
||||
Hob = CreateHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, sizeof (EFI_HOB_RESOURCE_DESCRIPTOR));
|
||||
- ASSERT(Hob != NULL);
|
||||
+ ASSERT (Hob != NULL);
|
||||
+ if (Hob == NULL) {
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
Hob->ResourceType = ResourceType;
|
||||
Hob->ResourceAttribute = ResourceAttribute;
|
||||
@@ -403,6 +413,10 @@ BuildModuleHob (
|
||||
((ModuleLength & (EFI_PAGE_SIZE - 1)) == 0));
|
||||
|
||||
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;
|
||||
@@ -450,7 +464,12 @@ BuildGuidHob (
|
||||
//
|
||||
ASSERT (DataLength <= (0xffff - sizeof (EFI_HOB_GUID_TYPE)));
|
||||
|
||||
- Hob = CreateHob (EFI_HOB_TYPE_GUID_EXTENSION, (UINT16) (sizeof (EFI_HOB_GUID_TYPE) + DataLength));
|
||||
+ 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;
|
||||
}
|
||||
@@ -516,6 +535,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;
|
||||
@@ -548,6 +571,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;
|
||||
@@ -589,6 +616,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;
|
||||
@@ -645,6 +676,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;
|
||||
@@ -681,6 +716,10 @@ BuildStackHob (
|
||||
((Length & (EFI_PAGE_SIZE - 1)) == 0));
|
||||
|
||||
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;
|
||||
@@ -761,6 +800,10 @@ BuildMemoryAllocationHob (
|
||||
((Length & (EFI_PAGE_SIZE - 1)) == 0));
|
||||
|
||||
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.39.3
|
||||
|
@ -0,0 +1,390 @@
|
||||
From b8261ac422ba284249cd4f341d78d058e79960f5 Mon Sep 17 00:00:00 2001
|
||||
From: Jon Maloy <jmaloy@redhat.com>
|
||||
Date: Wed, 7 Feb 2024 11:56:37 -0500
|
||||
Subject: [PATCH 03/17] MdePkg: Introduce CcMeasurementProtocol for CC Guest
|
||||
firmware
|
||||
|
||||
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-MergeRequest: 44: edk2: heap buffer overflow in Tcg2MeasureGptTable()
|
||||
RH-Jira: RHEL-21154 RHEL-21156
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [3/13] 6bf304f8e3bc875024c8fb0a4cd5d2c944f69480 (jmaloy/jons_fork)
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-21154
|
||||
CVE: CVE-2022-36763
|
||||
Upstream: Merged
|
||||
|
||||
commit e193584da60550008722498442c62ddb77bf27d5
|
||||
Author: Min Xu <min.m.xu@intel.com>
|
||||
Date: Sat Dec 11 21:08:40 2021 +0800
|
||||
|
||||
MdePkg: Introduce CcMeasurementProtocol for CC Guest firmware
|
||||
|
||||
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3625
|
||||
|
||||
CC guest is a Confidential Computing guest. If CC Guest firmware
|
||||
supports measurement and an event is created, CC Guest firmware
|
||||
is designed to report the event log with the same data structure
|
||||
in TCG-Platform-Firmware-Profile specification with
|
||||
EFI_TCG2_EVENT_LOG_FORMAT_TCG_2 format.
|
||||
|
||||
The CC Guest firmware supports measurement. It is designed to
|
||||
produce EFI_CC_MEASUREMENT_PROTOCOL with new GUID
|
||||
EFI_CC_MEASUREMENT_PROTOCOL_GUID to report event log and provides
|
||||
hash capability.
|
||||
|
||||
Cc: Michael D Kinney <michael.d.kinney@intel.com>
|
||||
Cc: Liming Gao <gaoliming@byosoft.com.cn>
|
||||
Cc: Zhiguang Liu <zhiguang.liu@intel.com>
|
||||
Cc: Jiewen Yao <jiewen.yao@intel.com>
|
||||
Cc: Jian J Wang <jian.j.wang@intel.com>
|
||||
Cc: Ken Lu <ken.lu@intel.com>
|
||||
Cc: Sami Mujawar <sami.mujawar@arm.com>
|
||||
Cc: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
|
||||
Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>
|
||||
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
|
||||
Signed-off-by: Min Xu <min.m.xu@intel.com>
|
||||
|
||||
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
|
||||
---
|
||||
MdePkg/Include/Protocol/CcMeasurement.h | 302 ++++++++++++++++++++++++
|
||||
MdePkg/MdePkg.dec | 6 +
|
||||
2 files changed, 308 insertions(+)
|
||||
create mode 100644 MdePkg/Include/Protocol/CcMeasurement.h
|
||||
|
||||
diff --git a/MdePkg/Include/Protocol/CcMeasurement.h b/MdePkg/Include/Protocol/CcMeasurement.h
|
||||
new file mode 100644
|
||||
index 0000000000..68029e977f
|
||||
--- /dev/null
|
||||
+++ b/MdePkg/Include/Protocol/CcMeasurement.h
|
||||
@@ -0,0 +1,302 @@
|
||||
+/** @file
|
||||
+ If CC Guest firmware supports measurement and an event is created,
|
||||
+ CC Guest firmware is designed to report the event log with the same
|
||||
+ data structure in TCG-Platform-Firmware-Profile specification with
|
||||
+ EFI_TCG2_EVENT_LOG_FORMAT_TCG_2 format.
|
||||
+
|
||||
+ The CC Guest firmware supports measurement, the CC Guest Firmware is
|
||||
+ designed to produce EFI_CC_MEASUREMENT_PROTOCOL with new GUID
|
||||
+ EFI_CC_MEASUREMENT_PROTOCOL_GUID to report event log and provides hash
|
||||
+ capability.
|
||||
+
|
||||
+Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
|
||||
+SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
+
|
||||
+**/
|
||||
+
|
||||
+#ifndef CC_MEASUREMENT_PROTOCOL_H_
|
||||
+#define CC_MEASUREMENT_PROTOCOL_H_
|
||||
+
|
||||
+#include <IndustryStandard/UefiTcgPlatform.h>
|
||||
+
|
||||
+#define EFI_CC_MEASUREMENT_PROTOCOL_GUID \
|
||||
+ { 0x96751a3d, 0x72f4, 0x41a6, { 0xa7, 0x94, 0xed, 0x5d, 0x0e, 0x67, 0xae, 0x6b }}
|
||||
+extern EFI_GUID gEfiCcMeasurementProtocolGuid;
|
||||
+
|
||||
+typedef struct _EFI_CC_MEASUREMENT_PROTOCOL EFI_CC_MEASUREMENT_PROTOCOL;
|
||||
+
|
||||
+typedef struct {
|
||||
+ UINT8 Major;
|
||||
+ UINT8 Minor;
|
||||
+} EFI_CC_VERSION;
|
||||
+
|
||||
+//
|
||||
+// EFI_CC Type/SubType definition
|
||||
+//
|
||||
+#define EFI_CC_TYPE_NONE 0
|
||||
+#define EFI_CC_TYPE_SEV 1
|
||||
+#define EFI_CC_TYPE_TDX 2
|
||||
+
|
||||
+typedef struct {
|
||||
+ UINT8 Type;
|
||||
+ UINT8 SubType;
|
||||
+} EFI_CC_TYPE;
|
||||
+
|
||||
+typedef UINT32 EFI_CC_EVENT_LOG_BITMAP;
|
||||
+typedef UINT32 EFI_CC_EVENT_LOG_FORMAT;
|
||||
+typedef UINT32 EFI_CC_EVENT_ALGORITHM_BITMAP;
|
||||
+typedef UINT32 EFI_CC_MR_INDEX;
|
||||
+
|
||||
+//
|
||||
+// Intel TDX measure register index
|
||||
+//
|
||||
+#define TDX_MR_INDEX_MRTD 0
|
||||
+#define TDX_MR_INDEX_RTMR0 1
|
||||
+#define TDX_MR_INDEX_RTMR1 2
|
||||
+#define TDX_MR_INDEX_RTMR2 3
|
||||
+#define TDX_MR_INDEX_RTMR3 4
|
||||
+
|
||||
+#define EFI_CC_EVENT_LOG_FORMAT_TCG_2 0x00000002
|
||||
+#define EFI_CC_BOOT_HASH_ALG_SHA384 0x00000004
|
||||
+
|
||||
+//
|
||||
+// This bit is shall be set when an event shall be extended but not logged.
|
||||
+//
|
||||
+#define EFI_CC_FLAG_EXTEND_ONLY 0x0000000000000001
|
||||
+//
|
||||
+// This bit shall be set when the intent is to measure a PE/COFF image.
|
||||
+//
|
||||
+#define EFI_CC_FLAG_PE_COFF_IMAGE 0x0000000000000010
|
||||
+
|
||||
+#pragma pack (1)
|
||||
+
|
||||
+#define EFI_CC_EVENT_HEADER_VERSION 1
|
||||
+
|
||||
+typedef struct {
|
||||
+ //
|
||||
+ // Size of the event header itself (sizeof(EFI_CC_EVENT_HEADER)).
|
||||
+ //
|
||||
+ UINT32 HeaderSize;
|
||||
+ //
|
||||
+ // Header version. For this version of this specification, the value shall be 1.
|
||||
+ //
|
||||
+ UINT16 HeaderVersion;
|
||||
+ //
|
||||
+ // Index of the MR (measurement register) that shall be extended.
|
||||
+ //
|
||||
+ EFI_CC_MR_INDEX MrIndex;
|
||||
+ //
|
||||
+ // Type of the event that shall be extended (and optionally logged).
|
||||
+ //
|
||||
+ UINT32 EventType;
|
||||
+} EFI_CC_EVENT_HEADER;
|
||||
+
|
||||
+typedef struct {
|
||||
+ //
|
||||
+ // Total size of the event including the Size component, the header and the Event data.
|
||||
+ //
|
||||
+ UINT32 Size;
|
||||
+ EFI_CC_EVENT_HEADER Header;
|
||||
+ UINT8 Event[1];
|
||||
+} EFI_CC_EVENT;
|
||||
+
|
||||
+#pragma pack()
|
||||
+
|
||||
+typedef struct {
|
||||
+ //
|
||||
+ // Allocated size of the structure
|
||||
+ //
|
||||
+ UINT8 Size;
|
||||
+ //
|
||||
+ // Version of the EFI_CC_BOOT_SERVICE_CAPABILITY structure itself.
|
||||
+ // For this version of the protocol, the Major version shall be set to 1
|
||||
+ // and the Minor version shall be set to 0.
|
||||
+ //
|
||||
+ EFI_CC_VERSION StructureVersion;
|
||||
+ //
|
||||
+ // Version of the EFI CC Measurement protocol.
|
||||
+ // For this version of the protocol, the Major version shall be set to 1
|
||||
+ // and the Minor version shall be set to 0.
|
||||
+ //
|
||||
+ EFI_CC_VERSION ProtocolVersion;
|
||||
+ //
|
||||
+ // Supported hash algorithms
|
||||
+ //
|
||||
+ EFI_CC_EVENT_ALGORITHM_BITMAP HashAlgorithmBitmap;
|
||||
+ //
|
||||
+ // Bitmap of supported event log formats
|
||||
+ //
|
||||
+ EFI_CC_EVENT_LOG_BITMAP SupportedEventLogs;
|
||||
+
|
||||
+ //
|
||||
+ // Indicates the CC type
|
||||
+ //
|
||||
+ EFI_CC_TYPE CcType;
|
||||
+} EFI_CC_BOOT_SERVICE_CAPABILITY;
|
||||
+
|
||||
+/**
|
||||
+ The EFI_CC_MEASUREMENT_PROTOCOL GetCapability function call provides protocol
|
||||
+ capability information and state information.
|
||||
+
|
||||
+ @param[in] This Indicates the calling context
|
||||
+ @param[in, out] ProtocolCapability The caller allocates memory for a EFI_CC_BOOT_SERVICE_CAPABILITY
|
||||
+ structure and sets the size field to the size of the structure allocated.
|
||||
+ The callee fills in the fields with the EFI CC BOOT Service capability
|
||||
+ information and the current CC information.
|
||||
+
|
||||
+ @retval EFI_SUCCESS Operation completed successfully.
|
||||
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
|
||||
+ The ProtocolCapability variable will not be populated.
|
||||
+ @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect.
|
||||
+ The ProtocolCapability variable will not be populated.
|
||||
+ @retval EFI_BUFFER_TOO_SMALL The ProtocolCapability variable is too small to hold the full response.
|
||||
+ It will be partially populated (required Size field will be set).
|
||||
+**/
|
||||
+typedef
|
||||
+EFI_STATUS
|
||||
+(EFIAPI *EFI_CC_GET_CAPABILITY)(
|
||||
+ IN EFI_CC_MEASUREMENT_PROTOCOL *This,
|
||||
+ IN OUT EFI_CC_BOOT_SERVICE_CAPABILITY *ProtocolCapability
|
||||
+ );
|
||||
+
|
||||
+/**
|
||||
+ The EFI_CC_MEASUREMENT_PROTOCOL Get Event Log function call allows a caller to
|
||||
+ retrieve the address of a given event log and its last entry.
|
||||
+
|
||||
+ @param[in] This Indicates the calling context
|
||||
+ @param[in] EventLogFormat The type of the event log for which the information is requested.
|
||||
+ @param[out] EventLogLocation A pointer to the memory address of the event log.
|
||||
+ @param[out] EventLogLastEntry If the Event Log contains more than one entry, this is a pointer to the
|
||||
+ address of the start of the last entry in the event log in memory.
|
||||
+ @param[out] EventLogTruncated If the Event Log is missing at least one entry because an event would
|
||||
+ have exceeded the area allocated for events, this value is set to TRUE.
|
||||
+ Otherwise, the value will be FALSE and the Event Log will be complete.
|
||||
+
|
||||
+ @retval EFI_SUCCESS Operation completed successfully.
|
||||
+ @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect
|
||||
+ (e.g. asking for an event log whose format is not supported).
|
||||
+**/
|
||||
+typedef
|
||||
+EFI_STATUS
|
||||
+(EFIAPI *EFI_CC_GET_EVENT_LOG)(
|
||||
+ IN EFI_CC_MEASUREMENT_PROTOCOL *This,
|
||||
+ IN EFI_CC_EVENT_LOG_FORMAT EventLogFormat,
|
||||
+ OUT EFI_PHYSICAL_ADDRESS *EventLogLocation,
|
||||
+ OUT EFI_PHYSICAL_ADDRESS *EventLogLastEntry,
|
||||
+ OUT BOOLEAN *EventLogTruncated
|
||||
+ );
|
||||
+
|
||||
+/**
|
||||
+ The EFI_CC_MEASUREMENT_PROTOCOL HashLogExtendEvent function call provides
|
||||
+ callers with an opportunity to extend and optionally log events without requiring
|
||||
+ knowledge of actual CC commands.
|
||||
+ The extend operation will occur even if this function cannot create an event
|
||||
+ log entry (e.g. due to the event log being full).
|
||||
+
|
||||
+ @param[in] This Indicates the calling context
|
||||
+ @param[in] Flags Bitmap providing additional information.
|
||||
+ @param[in] DataToHash Physical address of the start of the data buffer to be hashed.
|
||||
+ @param[in] DataToHashLen The length in bytes of the buffer referenced by DataToHash.
|
||||
+ @param[in] EfiCcEvent Pointer to data buffer containing information about the event.
|
||||
+
|
||||
+ @retval EFI_SUCCESS Operation completed successfully.
|
||||
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
|
||||
+ @retval EFI_VOLUME_FULL The extend operation occurred, but the event could not be written to one or more event logs.
|
||||
+ @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect.
|
||||
+ @retval EFI_UNSUPPORTED The PE/COFF image type is not supported.
|
||||
+**/
|
||||
+typedef
|
||||
+EFI_STATUS
|
||||
+(EFIAPI *EFI_CC_HASH_LOG_EXTEND_EVENT)(
|
||||
+ IN EFI_CC_MEASUREMENT_PROTOCOL *This,
|
||||
+ IN UINT64 Flags,
|
||||
+ IN EFI_PHYSICAL_ADDRESS DataToHash,
|
||||
+ IN UINT64 DataToHashLen,
|
||||
+ IN EFI_CC_EVENT *EfiCcEvent
|
||||
+ );
|
||||
+
|
||||
+/**
|
||||
+ The EFI_CC_MEASUREMENT_PROTOCOL MapPcrToMrIndex function call provides callers
|
||||
+ the info on TPM PCR <-> CC MR mapping information.
|
||||
+
|
||||
+ @param[in] This Indicates the calling context
|
||||
+ @param[in] PcrIndex TPM PCR index.
|
||||
+ @param[out] MrIndex CC MR index.
|
||||
+
|
||||
+ @retval EFI_SUCCESS The MrIndex is returned.
|
||||
+ @retval EFI_INVALID_PARAMETER The MrIndex is NULL.
|
||||
+ @retval EFI_UNSUPPORTED The PcrIndex is invalid.
|
||||
+**/
|
||||
+typedef
|
||||
+EFI_STATUS
|
||||
+(EFIAPI *EFI_CC_MAP_PCR_TO_MR_INDEX)(
|
||||
+ IN EFI_CC_MEASUREMENT_PROTOCOL *This,
|
||||
+ IN TCG_PCRINDEX PcrIndex,
|
||||
+ OUT EFI_CC_MR_INDEX *MrIndex
|
||||
+ );
|
||||
+
|
||||
+struct _EFI_CC_MEASUREMENT_PROTOCOL {
|
||||
+ EFI_CC_GET_CAPABILITY GetCapability;
|
||||
+ EFI_CC_GET_EVENT_LOG GetEventLog;
|
||||
+ EFI_CC_HASH_LOG_EXTEND_EVENT HashLogExtendEvent;
|
||||
+ EFI_CC_MAP_PCR_TO_MR_INDEX MapPcrToMrIndex;
|
||||
+};
|
||||
+
|
||||
+//
|
||||
+// CC event log
|
||||
+//
|
||||
+
|
||||
+#pragma pack(1)
|
||||
+
|
||||
+//
|
||||
+// Crypto Agile Log Entry Format.
|
||||
+// It is similar with TCG_PCR_EVENT2 except the field of MrIndex and PCRIndex.
|
||||
+//
|
||||
+typedef struct {
|
||||
+ EFI_CC_MR_INDEX MrIndex;
|
||||
+ UINT32 EventType;
|
||||
+ TPML_DIGEST_VALUES Digests;
|
||||
+ UINT32 EventSize;
|
||||
+ UINT8 Event[1];
|
||||
+} CC_EVENT;
|
||||
+
|
||||
+//
|
||||
+// EFI CC Event Header
|
||||
+// It is similar with TCG_PCR_EVENT2_HDR except the field of MrIndex and PCRIndex
|
||||
+//
|
||||
+typedef struct {
|
||||
+ EFI_CC_MR_INDEX MrIndex;
|
||||
+ UINT32 EventType;
|
||||
+ TPML_DIGEST_VALUES Digests;
|
||||
+ UINT32 EventSize;
|
||||
+} CC_EVENT_HDR;
|
||||
+
|
||||
+#pragma pack()
|
||||
+
|
||||
+//
|
||||
+// Log entries after Get Event Log service
|
||||
+//
|
||||
+
|
||||
+#define EFI_CC_FINAL_EVENTS_TABLE_VERSION 1
|
||||
+
|
||||
+typedef struct {
|
||||
+ //
|
||||
+ // The version of this structure. It shall be set to 1.
|
||||
+ //
|
||||
+ UINT64 Version;
|
||||
+ //
|
||||
+ // Number of events recorded after invocation of GetEventLog API
|
||||
+ //
|
||||
+ UINT64 NumberOfEvents;
|
||||
+ //
|
||||
+ // List of events of type CC_EVENT.
|
||||
+ //
|
||||
+ // CC_EVENT Event[1];
|
||||
+} EFI_CC_FINAL_EVENTS_TABLE;
|
||||
+
|
||||
+#define EFI_CC_FINAL_EVENTS_TABLE_GUID \
|
||||
+ {0xdd4a4648, 0x2de7, 0x4665, {0x96, 0x4d, 0x21, 0xd9, 0xef, 0x5f, 0xb4, 0x46}}
|
||||
+
|
||||
+extern EFI_GUID gEfiCcFinalEventsTableGuid;
|
||||
+
|
||||
+#endif
|
||||
diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec
|
||||
index 8b18415b10..6389a48338 100644
|
||||
--- a/MdePkg/MdePkg.dec
|
||||
+++ b/MdePkg/MdePkg.dec
|
||||
@@ -823,6 +823,9 @@
|
||||
#
|
||||
gLinuxEfiInitrdMediaGuid = {0x5568e427, 0x68fc, 0x4f3d, {0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68}}
|
||||
|
||||
+ ## Include/Protocol/CcMeasurement.h
|
||||
+ gEfiCcFinalEventsTableGuid = { 0xdd4a4648, 0x2de7, 0x4665, { 0x96, 0x4d, 0x21, 0xd9, 0xef, 0x5f, 0xb4, 0x46 }}
|
||||
+
|
||||
[Guids.IA32, Guids.X64]
|
||||
## Include/Guid/Cper.h
|
||||
gEfiIa32X64ErrorTypeCacheCheckGuid = { 0xA55701F5, 0xE3EF, 0x43de, { 0xAC, 0x72, 0x24, 0x9B, 0x57, 0x3F, 0xAD, 0x2C }}
|
||||
@@ -1011,6 +1014,9 @@
|
||||
## Include/Protocol/PcdInfo.h
|
||||
gGetPcdInfoProtocolGuid = { 0x5be40f57, 0xfa68, 0x4610, { 0xbb, 0xbf, 0xe9, 0xc5, 0xfc, 0xda, 0xd3, 0x65 } }
|
||||
|
||||
+ ## Include/Protocol/CcMeasurement.h
|
||||
+ gEfiCcMeasurementProtocolGuid = { 0x96751a3d, 0x72f4, 0x41a6, { 0xa7, 0x94, 0xed, 0x5d, 0x0e, 0x67, 0xae, 0x6b }}
|
||||
+
|
||||
#
|
||||
# Protocols defined in PI1.0.
|
||||
#
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,170 @@
|
||||
From ffa1202da2f55c1f540240e8267db9a7ec8d6a60 Mon Sep 17 00:00:00 2001
|
||||
From: Jon Maloy <jmaloy@redhat.com>
|
||||
Date: Fri, 16 Feb 2024 10:48:05 -0500
|
||||
Subject: [PATCH 11/15] NetworkPkg: : Adds a SecurityFix.yaml file
|
||||
|
||||
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-MergeRequest: 56: Pixiefail issues in NetworkPkg package
|
||||
RH-Jira: RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852
|
||||
RH-Acked-by: Gerd Hoffmann <None>
|
||||
RH-Acked-by: Oliver Steffen <osteffen@redhat.com>
|
||||
RH-Commit: [11/15] 8a46b763887843d00293997bdd7d50ea120104d9
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-21852
|
||||
CVE: CVE-2022-45235
|
||||
Upstream: Merged
|
||||
|
||||
commit 1d0b95f6457d225c5108302a9da74b4ed7aa5a38
|
||||
Author: Doug Flick via groups.io <dougflick=microsoft.com@groups.io>
|
||||
Date: Fri Jan 26 05:54:57 2024 +0800
|
||||
|
||||
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>
|
||||
|
||||
Signed-off-by: Jon Maloy <jmaloy@redhat.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.39.3
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,69 @@
|
||||
From 649fe647114ca5dee84b0c55106ee58a9703984f Mon Sep 17 00:00:00 2001
|
||||
From: Jon Maloy <jmaloy@redhat.com>
|
||||
Date: Fri, 16 Feb 2024 10:48:05 -0500
|
||||
Subject: [PATCH 15/15] NetworkPkg: Dhcp6Dxe: Packet-Length is not updated
|
||||
before appending
|
||||
|
||||
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-MergeRequest: 56: Pixiefail issues in NetworkPkg package
|
||||
RH-Jira: RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852
|
||||
RH-Acked-by: Gerd Hoffmann <None>
|
||||
RH-Acked-by: Oliver Steffen <osteffen@redhat.com>
|
||||
RH-Commit: [15/15] bc7ef287311bb3f757bc26f8921875566bcb5917
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-21840
|
||||
CVE: CVE-2023-45229
|
||||
Upstream: Merged
|
||||
|
||||
commit 75deaf5c3c0d164c61653258c331151241bb69d8
|
||||
Author: Doug Flick <dougflick@microsoft.com>
|
||||
Date: Tue Feb 13 10:46:02 2024 -0800
|
||||
|
||||
NetworkPkg: Dhcp6Dxe: Packet-Length is not updated before appending
|
||||
|
||||
In order for Dhcp6AppendIaAddrOption (..) to safely append the IA
|
||||
Address option, the Packet-Length field must be updated before appending
|
||||
the 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>
|
||||
|
||||
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
|
||||
---
|
||||
NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c | 10 +++++-----
|
||||
1 file changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c
|
||||
index e172ffc2a2..c23eff8766 100644
|
||||
--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c
|
||||
+++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c
|
||||
@@ -948,6 +948,11 @@ Dhcp6AppendIaOption (
|
||||
*PacketCursor += sizeof (T2);
|
||||
}
|
||||
|
||||
+ //
|
||||
+ // Update the packet length
|
||||
+ //
|
||||
+ Packet->Length += BytesNeeded;
|
||||
+
|
||||
//
|
||||
// Fill all the addresses belong to the Ia
|
||||
//
|
||||
@@ -959,11 +964,6 @@ Dhcp6AppendIaOption (
|
||||
}
|
||||
}
|
||||
|
||||
- //
|
||||
- // Update the packet length
|
||||
- //
|
||||
- Packet->Length += BytesNeeded;
|
||||
-
|
||||
//
|
||||
// Fill the value of Ia option length
|
||||
//
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,161 @@
|
||||
From 4bf844922a963cb20fb1e72ca11a65a673992ca2 Mon Sep 17 00:00:00 2001
|
||||
From: Jon Maloy <jmaloy@redhat.com>
|
||||
Date: Fri, 16 Feb 2024 10:48:05 -0500
|
||||
Subject: [PATCH 14/15] NetworkPkg: Dhcp6Dxe: Removes duplicate check and
|
||||
replaces with macro
|
||||
|
||||
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-MergeRequest: 56: Pixiefail issues in NetworkPkg package
|
||||
RH-Jira: RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852
|
||||
RH-Acked-by: Gerd Hoffmann <None>
|
||||
RH-Acked-by: Oliver Steffen <osteffen@redhat.com>
|
||||
RH-Commit: [14/15] a943400f9267b219bf1fd202534500f82a2a4c56
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-21840
|
||||
CVE: CVE-2023-45229
|
||||
Upstream: Merged
|
||||
|
||||
commit af3fad99d6088881562e50149f414f76a5be0140
|
||||
Author: Doug Flick <dougflick@microsoft.com>
|
||||
Date: Tue Feb 13 10:46:01 2024 -0800
|
||||
|
||||
NetworkPkg: Dhcp6Dxe: Removes duplicate check and replaces with macro
|
||||
|
||||
Removes duplicate check after merge
|
||||
|
||||
>
|
||||
> //
|
||||
> // 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;
|
||||
> }
|
||||
>
|
||||
|
||||
Converts the check to a macro and replaces all instances of the check
|
||||
with the macro
|
||||
|
||||
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>
|
||||
|
||||
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
|
||||
---
|
||||
NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c | 43 +++++++++++++-----------------
|
||||
1 file changed, 18 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c
|
||||
index 484c360a96..e172ffc2a2 100644
|
||||
--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c
|
||||
+++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c
|
||||
@@ -10,6 +10,15 @@
|
||||
|
||||
#include "Dhcp6Impl.h"
|
||||
|
||||
+//
|
||||
+// Verifies the packet cursor is within the packet
|
||||
+// otherwise it is invalid
|
||||
+//
|
||||
+#define IS_INVALID_PACKET_CURSOR(PacketCursor, Packet) \
|
||||
+ (((*PacketCursor) < (Packet)->Dhcp6.Option) || \
|
||||
+ ((*PacketCursor) >= (Packet)->Dhcp6.Option + ((Packet)->Size - sizeof(EFI_DHCP6_HEADER))) \
|
||||
+ ) \
|
||||
+
|
||||
|
||||
/**
|
||||
Generate client Duid in the format of Duid-llt.
|
||||
@@ -662,9 +671,7 @@ Dhcp6AppendOption (
|
||||
//
|
||||
// Verify the PacketCursor is within the packet
|
||||
//
|
||||
- if ( (*PacketCursor < Packet->Dhcp6.Option)
|
||||
- || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))
|
||||
- {
|
||||
+ if (IS_INVALID_PACKET_CURSOR (PacketCursor, Packet)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
@@ -681,15 +688,6 @@ Dhcp6AppendOption (
|
||||
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);
|
||||
@@ -768,9 +766,7 @@ Dhcp6AppendIaAddrOption (
|
||||
//
|
||||
// Verify the PacketCursor is within the packet
|
||||
//
|
||||
- if ( (*PacketCursor < Packet->Dhcp6.Option)
|
||||
- || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))
|
||||
- {
|
||||
+ if (IS_INVALID_PACKET_CURSOR (PacketCursor, Packet)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
@@ -902,9 +898,7 @@ Dhcp6AppendIaOption (
|
||||
//
|
||||
// Verify the PacketCursor is within the packet
|
||||
//
|
||||
- if ( (*PacketCursor < Packet->Dhcp6.Option)
|
||||
- || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))
|
||||
- {
|
||||
+ if (IS_INVALID_PACKET_CURSOR (PacketCursor, Packet)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
@@ -966,14 +960,14 @@ Dhcp6AppendIaOption (
|
||||
}
|
||||
|
||||
//
|
||||
- // Fill the value of Ia option length
|
||||
+ // Update the packet length
|
||||
//
|
||||
- *Len = HTONS ((UINT16)(*PacketCursor - (UINT8 *)Len - 2));
|
||||
+ Packet->Length += BytesNeeded;
|
||||
|
||||
//
|
||||
- // Update the packet length
|
||||
+ // Fill the value of Ia option length
|
||||
//
|
||||
- Packet->Length += BytesNeeded;
|
||||
+ *Len = HTONS ((UINT16)(*PacketCursor - (UINT8 *)Len - 2));
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
@@ -982,6 +976,7 @@ Dhcp6AppendIaOption (
|
||||
Append the appointed Elapsed time option to Buf, 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] Instance The pointer to the Dhcp6 instance.
|
||||
@@ -1037,9 +1032,7 @@ Dhcp6AppendETOption (
|
||||
//
|
||||
// Verify the PacketCursor is within the packet
|
||||
//
|
||||
- if ( (*PacketCursor < Packet->Dhcp6.Option)
|
||||
- || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))
|
||||
- {
|
||||
+ if (IS_INVALID_PACKET_CURSOR (PacketCursor, Packet)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,621 @@
|
||||
From a115d0a66c3e73c60b74ec6d09e3759da89e919b Mon Sep 17 00:00:00 2001
|
||||
From: Jon Maloy <jmaloy@redhat.com>
|
||||
Date: Fri, 9 Feb 2024 17:57:07 -0500
|
||||
Subject: [PATCH 17/17] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229
|
||||
Patch
|
||||
|
||||
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-MergeRequest: 50: CVE-2023-45230 and CVE-2023-45229
|
||||
RH-Jira: RHEL-21840 RHEL-21842
|
||||
RH-Acked-by: Oliver Steffen <osteffen@redhat.com>
|
||||
RH-Commit: [4/4] 3daf69000f78416ee1f1bad0b6ceb01ed28a84a5 (jmaloy/jons_fork)
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-21840
|
||||
CVE: CVE-2023-45229
|
||||
Upstream: Merged
|
||||
|
||||
commit 1dbb10cc52dc8ef49bb700daa1cefc76b26d52e0
|
||||
Author: Doug Flick via groups.io <dougflick=microsoft.com@groups.io>
|
||||
Date: Fri Jan 26 05:54:46 2024 +0800
|
||||
|
||||
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>
|
||||
|
||||
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
|
||||
---
|
||||
NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h | 138 ++++++++++++++++++---
|
||||
NetworkPkg/Dhcp6Dxe/Dhcp6Io.c | 205 +++++++++++++++++++++-----------
|
||||
2 files changed, 257 insertions(+), 86 deletions(-)
|
||||
|
||||
diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h
|
||||
index ec0ed5d8f5..e759ab9a62 100644
|
||||
--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h
|
||||
+++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h
|
||||
@@ -47,6 +47,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
|
||||
//
|
||||
@@ -61,12 +75,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)
|
||||
|
||||
@@ -75,34 +87,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 2976684aba..d680febbf1 100644
|
||||
--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
|
||||
+++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
|
||||
@@ -611,8 +611,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
|
||||
@@ -621,13 +621,14 @@ Dhcp6UpdateIaInfo (
|
||||
if (T1 > T2 && T2 > 0) {
|
||||
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);
|
||||
+
|
||||
+ IaInnerOpt = DHCP6_OFFSET_OF_IA_TA_INNER_OPT (Option);
|
||||
+ IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN (Option)))) - DHCP6_SIZE_OF_IAID);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -653,7 +654,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;
|
||||
}
|
||||
@@ -675,6 +676,87 @@ Dhcp6UpdateIaInfo (
|
||||
|
||||
|
||||
|
||||
+/**
|
||||
+ 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.
|
||||
@@ -695,9 +777,15 @@ Dhcp6SeekStsOption (
|
||||
OUT UINT8 **Option
|
||||
)
|
||||
{
|
||||
- UINT8 *IaInnerOpt;
|
||||
- UINT16 IaInnerLen;
|
||||
- UINT16 StsCode;
|
||||
+ 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
|
||||
@@ -705,12 +793,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;
|
||||
}
|
||||
@@ -721,7 +809,7 @@ Dhcp6SeekStsOption (
|
||||
//
|
||||
*Option = Dhcp6SeekIaOption (
|
||||
Packet->Dhcp6.Option,
|
||||
- Packet->Length - sizeof (EFI_DHCP6_HEADER),
|
||||
+ OptionLen,
|
||||
&Instance->Config->IaDescriptor
|
||||
);
|
||||
if (*Option == NULL) {
|
||||
@@ -729,52 +817,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
|
||||
+ // Seek the inner option
|
||||
//
|
||||
- // The inner options still start with 2 bytes option-code and 2 bytes option-len.
|
||||
- //
|
||||
- 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;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -798,7 +869,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;
|
||||
}
|
||||
@@ -1123,7 +1194,7 @@ Dhcp6SendRequestMsg (
|
||||
//
|
||||
Option = Dhcp6SeekOption (
|
||||
Instance->AdSelect->Dhcp6.Option,
|
||||
- Instance->AdSelect->Length - 4,
|
||||
+ Instance->AdSelect->Length - sizeof (EFI_DHCP6_HEADER),
|
||||
Dhcp6OptServerId
|
||||
);
|
||||
if (Option == NULL) {
|
||||
@@ -1309,7 +1380,7 @@ Dhcp6SendDeclineMsg (
|
||||
//
|
||||
Option = Dhcp6SeekOption (
|
||||
LastReply->Dhcp6.Option,
|
||||
- LastReply->Length - 4,
|
||||
+ LastReply->Length - sizeof (EFI_DHCP6_HEADER),
|
||||
Dhcp6OptServerId
|
||||
);
|
||||
if (Option == NULL) {
|
||||
@@ -1469,7 +1540,7 @@ Dhcp6SendReleaseMsg (
|
||||
//
|
||||
Option = Dhcp6SeekOption (
|
||||
LastReply->Dhcp6.Option,
|
||||
- LastReply->Length - 4,
|
||||
+ LastReply->Length - sizeof (EFI_DHCP6_HEADER),
|
||||
Dhcp6OptServerId
|
||||
);
|
||||
if (Option == NULL) {
|
||||
@@ -1695,7 +1766,7 @@ Dhcp6SendRenewRebindMsg (
|
||||
|
||||
Option = Dhcp6SeekOption (
|
||||
LastReply->Dhcp6.Option,
|
||||
- LastReply->Length - 4,
|
||||
+ LastReply->Length - sizeof (EFI_DHCP6_HEADER),
|
||||
Dhcp6OptServerId
|
||||
);
|
||||
if (Option == NULL) {
|
||||
@@ -2235,7 +2306,7 @@ Dhcp6HandleReplyMsg (
|
||||
//
|
||||
Option = Dhcp6SeekOption (
|
||||
Packet->Dhcp6.Option,
|
||||
- Packet->Length - 4,
|
||||
+ Packet->Length - sizeof (EFI_DHCP6_HEADER),
|
||||
Dhcp6OptRapidCommit
|
||||
);
|
||||
|
||||
@@ -2383,7 +2454,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:
|
||||
//
|
||||
@@ -2514,7 +2585,7 @@ Dhcp6SelectAdvertiseMsg (
|
||||
//
|
||||
Option = Dhcp6SeekOption(
|
||||
AdSelect->Dhcp6.Option,
|
||||
- AdSelect->Length - 4,
|
||||
+ AdSelect->Length - sizeof (EFI_DHCP6_HEADER),
|
||||
Dhcp6OptServerUnicast
|
||||
);
|
||||
|
||||
@@ -2526,7 +2597,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));
|
||||
}
|
||||
|
||||
//
|
||||
@@ -2580,7 +2651,7 @@ Dhcp6HandleAdvertiseMsg (
|
||||
//
|
||||
Option = Dhcp6SeekOption(
|
||||
Packet->Dhcp6.Option,
|
||||
- Packet->Length - 4,
|
||||
+ Packet->Length - sizeof (EFI_DHCP6_HEADER),
|
||||
Dhcp6OptRapidCommit
|
||||
);
|
||||
|
||||
@@ -2676,7 +2747,7 @@ Dhcp6HandleAdvertiseMsg (
|
||||
CopyMem (Instance->AdSelect, Packet, Packet->Size);
|
||||
|
||||
if (Option != NULL) {
|
||||
- Instance->AdPref = *(Option + 4);
|
||||
+ Instance->AdPref = *(DHCP6_OFFSET_OF_OPT_DATA (Option));
|
||||
}
|
||||
} else {
|
||||
//
|
||||
@@ -2747,11 +2818,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;
|
||||
}
|
||||
|
||||
@@ -2760,7 +2831,7 @@ Dhcp6HandleStateful (
|
||||
//
|
||||
Option = Dhcp6SeekOption(
|
||||
Packet->Dhcp6.Option,
|
||||
- Packet->Length - 4,
|
||||
+ Packet->Length - DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN,
|
||||
Dhcp6OptServerId
|
||||
);
|
||||
|
||||
@@ -2865,7 +2936,7 @@ Dhcp6HandleStateless (
|
||||
//
|
||||
Option = Dhcp6SeekOption (
|
||||
Packet->Dhcp6.Option,
|
||||
- Packet->Length - 4,
|
||||
+ Packet->Length - sizeof (EFI_DHCP6_HEADER),
|
||||
Dhcp6OptServerId
|
||||
);
|
||||
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,257 @@
|
||||
From 1b58858f28a364a8f8fa897a78db7ced068719dd Mon Sep 17 00:00:00 2001
|
||||
From: Jon Maloy <jmaloy@redhat.com>
|
||||
Date: Fri, 16 Feb 2024 10:48:05 -0500
|
||||
Subject: [PATCH 13/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229
|
||||
Related Patch
|
||||
|
||||
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-MergeRequest: 56: Pixiefail issues in NetworkPkg package
|
||||
RH-Jira: RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852
|
||||
RH-Acked-by: Gerd Hoffmann <None>
|
||||
RH-Acked-by: Oliver Steffen <osteffen@redhat.com>
|
||||
RH-Commit: [13/15] 904fd82592208d0ca42bbb64f437691a5bdfd0b6
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-21840
|
||||
CVE: CVE-2023-45229
|
||||
Upstream: Merged
|
||||
|
||||
commit 1c440a5eceedc64e892877eeac0f1a4938f5abbb
|
||||
Author: Doug Flick <dougflick@microsoft.com>
|
||||
Date: Tue Feb 13 10:46:00 2024 -0800
|
||||
|
||||
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>
|
||||
|
||||
Signed-off-by: Jon Maloy <jmaloy@redhat.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 554f0f5e5d..8c0d282bca 100644
|
||||
--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.h
|
||||
+++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.h
|
||||
@@ -218,4 +218,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.39.3
|
||||
|
@ -0,0 +1,78 @@
|
||||
From e3f153773bd2ca13ee4869187f1711840fc8afc9 Mon Sep 17 00:00:00 2001
|
||||
From: Jon Maloy <jmaloy@redhat.com>
|
||||
Date: Thu, 15 Feb 2024 11:51:09 -0500
|
||||
Subject: [PATCH 02/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 Patch
|
||||
|
||||
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-MergeRequest: 56: Pixiefail issues in NetworkPkg package
|
||||
RH-Jira: RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852
|
||||
RH-Acked-by: Gerd Hoffmann <None>
|
||||
RH-Acked-by: Oliver Steffen <osteffen@redhat.com>
|
||||
RH-Commit: [2/15] 61eaf6aac61b774c3a8ace54af8abd607651d2db
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-21844
|
||||
CVE: CVE-2022-45231
|
||||
Upstream: Merged
|
||||
|
||||
commit bbfee34f4188ac00371abe1389ae9c9fb989a0cd
|
||||
Author: Doug Flick <dougflick@microsoft.com>
|
||||
Date: Fri Jan 26 05:54:48 2024 +0800
|
||||
|
||||
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>
|
||||
|
||||
Signed-off-by: Jon Maloy <jmaloy@redhat.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.39.3
|
||||
|
@ -0,0 +1,277 @@
|
||||
From e8200dda7752d21794b2268efe9e957958ffef29 Mon Sep 17 00:00:00 2001
|
||||
From: Jon Maloy <jmaloy@redhat.com>
|
||||
Date: Wed, 14 Feb 2024 12:24:44 -0500
|
||||
Subject: [PATCH 03/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 Unit
|
||||
Tests
|
||||
|
||||
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-MergeRequest: 56: Pixiefail issues in NetworkPkg package
|
||||
RH-Jira: RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852
|
||||
RH-Acked-by: Gerd Hoffmann <None>
|
||||
RH-Acked-by: Oliver Steffen <osteffen@redhat.com>
|
||||
RH-Commit: [3/15] ca554677a3397423073d3bb4774f856b2329ae9c
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-21844
|
||||
CVE: CVE-2022-45231
|
||||
Upstream: Merged
|
||||
|
||||
commit 6f77463d72807ec7f4ed6518c3dac29a1040df9f
|
||||
Author: Doug Flick <dougflick@microsoft.com>
|
||||
Date: Fri Jan 26 05:54:49 2024 +0800
|
||||
|
||||
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>
|
||||
|
||||
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
|
||||
---
|
||||
.../Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp | 20 +++
|
||||
.../Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf | 42 ++++++
|
||||
.../Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp | 129 ++++++++++++++++++
|
||||
NetworkPkg/Test/NetworkPkgHostTest.dsc | 1 +
|
||||
4 files changed, 192 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));
|
||||
+}
|
||||
diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc
|
||||
index 20bc90b172..ab7c2857b6 100644
|
||||
--- a/NetworkPkg/Test/NetworkPkgHostTest.dsc
|
||||
+++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc
|
||||
@@ -25,6 +25,7 @@
|
||||
# Build HOST_APPLICATION that tests NetworkPkg
|
||||
#
|
||||
NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
|
||||
+ NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
|
||||
|
||||
# Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests.
|
||||
[LibraryClasses]
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,377 @@
|
||||
From 23b31a16bbb789f4c251b1d2f23334210a9fb545 Mon Sep 17 00:00:00 2001
|
||||
From: Jon Maloy <jmaloy@redhat.com>
|
||||
Date: Thu, 15 Feb 2024 11:51:09 -0500
|
||||
Subject: [PATCH 04/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Patch
|
||||
|
||||
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-MergeRequest: 56: Pixiefail issues in NetworkPkg package
|
||||
RH-Jira: RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852
|
||||
RH-Acked-by: Gerd Hoffmann <None>
|
||||
RH-Acked-by: Oliver Steffen <osteffen@redhat.com>
|
||||
RH-Commit: [4/15] 48c273e43a6275c7eae3223c4ffa433f4d6531a4
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-21846
|
||||
CVE: CVE-2022-45232
|
||||
Upstream: Merged
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-21848
|
||||
CVE: CVE-2022-45233
|
||||
Upstream: Merged
|
||||
|
||||
commit 4df0229ef992d4f2721a8508787ebf9dc81fbd6e
|
||||
Author: Doug Flick <dougflick@microsoft.com>
|
||||
Date: Fri Jan 26 05:54:50 2024 +0800
|
||||
|
||||
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>
|
||||
|
||||
Signed-off-by: Jon Maloy <jmaloy@redhat.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.39.3
|
||||
|
@ -0,0 +1,430 @@
|
||||
From 2bd8bc051f6394f2ab3c22649c54ecbed5d636cd Mon Sep 17 00:00:00 2001
|
||||
From: Jon Maloy <jmaloy@redhat.com>
|
||||
Date: Wed, 14 Feb 2024 20:25:29 -0500
|
||||
Subject: [PATCH 05/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Unit
|
||||
Tests
|
||||
|
||||
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-MergeRequest: 56: Pixiefail issues in NetworkPkg package
|
||||
RH-Jira: RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852
|
||||
RH-Acked-by: Gerd Hoffmann <None>
|
||||
RH-Acked-by: Oliver Steffen <osteffen@redhat.com>
|
||||
RH-Commit: [5/15] 624365d403df25927ab0514b0e25faea7376def8
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-21846
|
||||
CVE: CVE-2022-45232
|
||||
Upstream: Merged
|
||||
|
||||
commit c9c87f08dd6ace36fa843424522c3558a8374cac
|
||||
Author: Doug Flick <dougflick@microsoft.com>
|
||||
Date: Fri Jan 26 05:54:51 2024 +0800
|
||||
|
||||
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>
|
||||
|
||||
Signed-off-by: Jon Maloy <jmaloy@redhat.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.39.3
|
||||
|
@ -0,0 +1,257 @@
|
||||
From 0016db53099ba979617f376fe1104fefada4fa29 Mon Sep 17 00:00:00 2001
|
||||
From: Jon Maloy <jmaloy@redhat.com>
|
||||
Date: Fri, 16 Feb 2024 10:48:05 -0500
|
||||
Subject: [PATCH 09/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235
|
||||
Patch
|
||||
|
||||
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-MergeRequest: 56: Pixiefail issues in NetworkPkg package
|
||||
RH-Jira: RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852
|
||||
RH-Acked-by: Gerd Hoffmann <None>
|
||||
RH-Acked-by: Oliver Steffen <osteffen@redhat.com>
|
||||
RH-Commit: [9/15] c48c060b87761537ee526e1f8a9e5993eb1a0381
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-21852
|
||||
CVE: CVE-2022-45235
|
||||
Upstream: Merged
|
||||
|
||||
commit fac297724e6cc343430cd0104e55cd7a96d1151e
|
||||
Author: Doug Flick <dougflick@microsoft.com>
|
||||
Date: Fri Jan 26 05:54:55 2024 +0800
|
||||
|
||||
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>
|
||||
|
||||
Signed-off-by: Jon Maloy <jmaloy@redhat.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 ae4be775e8..47eb8cc0c0 100644
|
||||
--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h
|
||||
+++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h
|
||||
@@ -35,6 +35,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.39.3
|
||||
|
@ -0,0 +1,409 @@
|
||||
From 80b34c0f56228353c174f9ff739d0755c62d76cf Mon Sep 17 00:00:00 2001
|
||||
From: Jon Maloy <jmaloy@redhat.com>
|
||||
Date: Fri, 16 Feb 2024 10:48:05 -0500
|
||||
Subject: [PATCH 10/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235
|
||||
Unit Tests
|
||||
|
||||
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-MergeRequest: 56: Pixiefail issues in NetworkPkg package
|
||||
RH-Jira: RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852
|
||||
RH-Acked-by: Gerd Hoffmann <None>
|
||||
RH-Acked-by: Oliver Steffen <osteffen@redhat.com>
|
||||
RH-Commit: [10/15] 5dbf3f771506ff9a0c28827c568d04e825572658
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-21852
|
||||
CVE: CVE-2022-45235
|
||||
Upstream: Merged
|
||||
|
||||
commit ff2986358f75d8f58ef08a66fe673539c9c48f41
|
||||
Author: Doug Flick <dougflick@microsoft.com>
|
||||
Date: Fri Jan 26 05:54:56 2024 +0800
|
||||
|
||||
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>
|
||||
|
||||
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
|
||||
---
|
||||
NetworkPkg/Test/NetworkPkgHostTest.dsc | 5 +-
|
||||
.../GoogleTest/PxeBcDhcp6GoogleTest.cpp | 278 +++++++++++++++++-
|
||||
.../GoogleTest/PxeBcDhcp6GoogleTest.h | 18 ++
|
||||
3 files changed, 298 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc
|
||||
index c8a991e5c1..1010a80a15 100644
|
||||
--- a/NetworkPkg/Test/NetworkPkgHostTest.dsc
|
||||
+++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc
|
||||
@@ -26,7 +26,10 @@
|
||||
#
|
||||
NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
|
||||
NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
|
||||
- NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
|
||||
+ NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf {
|
||||
+ <LibraryClasses>
|
||||
+ UefiRuntimeServicesTableLib|MdePkg/Test/Mock/Library/GoogleTest/MockUefiRuntimeServicesTableLib/MockUefiRuntimeServicesTableLib.inf
|
||||
+ }
|
||||
|
||||
# Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests.
|
||||
[LibraryClasses]
|
||||
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.39.3
|
||||
|
@ -0,0 +1,47 @@
|
||||
From f2aeff31924f6d070d7f8b87550dc6d9820531ad Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Tue, 16 Jan 2024 18:11:04 +0100
|
||||
Subject: [PATCH 15/18] OvmfPkg/VirtNorFlashDxe: ValidateFvHeader: unwritten
|
||||
state is EOL too
|
||||
|
||||
RH-Author: Gerd Hoffmann <None>
|
||||
RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport
|
||||
RH-Jira: RHEL-17587
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [17/20] 37220c700ea816c815e0612031e10b7d466b71a2
|
||||
|
||||
It is possible to find variable entries with State being 0xff, i.e. not
|
||||
updated since flash block erase. This indicates the variable driver
|
||||
could not complete the header write while appending a new entry, and
|
||||
therefore State was not set to VAR_HEADER_VALID_ONLY.
|
||||
|
||||
This can only happen at the end of the variable list, so treat this as
|
||||
additional "end of variable list" condition.
|
||||
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
|
||||
Message-Id: <20240116171105.37831-6-kraxel@redhat.com>
|
||||
(cherry picked from commit 735d0a5e2e25c1577bf9bea7826da937ca38169d)
|
||||
---
|
||||
OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c
|
||||
index acc4a413ee..f8e71f88c1 100644
|
||||
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c
|
||||
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c
|
||||
@@ -302,6 +302,11 @@ ValidateFvHeader (
|
||||
break;
|
||||
}
|
||||
|
||||
+ if (VarHeader->State == 0xff) {
|
||||
+ DEBUG ((DEBUG_INFO, "%a: end of var list (unwritten state)\n", __func__));
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
VarName = NULL;
|
||||
switch (VarHeader->State) {
|
||||
// usage: State = VAR_HEADER_VALID_ONLY
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,73 @@
|
||||
From 00d9e2d6cb03afeef5a1110d6f1fae1389a06f7a Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Tue, 16 Jan 2024 18:11:02 +0100
|
||||
Subject: [PATCH 13/18] OvmfPkg/VirtNorFlashDxe: add a loop for
|
||||
NorFlashWriteBuffer calls.
|
||||
|
||||
RH-Author: Gerd Hoffmann <None>
|
||||
RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport
|
||||
RH-Jira: RHEL-17587
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [15/20] 72004a196ea61d627ab528573db657dd7db16de2
|
||||
|
||||
Replace the two NorFlashWriteBuffer() calls with a loop containing a
|
||||
single NorFlashWriteBuffer() call.
|
||||
|
||||
With the changes in place the code is able to handle updates larger
|
||||
than two P30_MAX_BUFFER_SIZE_IN_BYTES blocks, even though the patch
|
||||
does not actually change the size limit.
|
||||
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
|
||||
Message-Id: <20240116171105.37831-4-kraxel@redhat.com>
|
||||
(cherry picked from commit 28ffd726894f11a587a6ac7f71a4c4af341e24d2)
|
||||
---
|
||||
OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 21 ++++++++-------------
|
||||
1 file changed, 8 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
index 88a4d2c23f..3d1343b381 100644
|
||||
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
@@ -521,6 +521,7 @@ NorFlashWriteSingleBlock (
|
||||
UINTN BlockAddress;
|
||||
UINT8 *OrigData;
|
||||
UINTN Start, End;
|
||||
+ UINT32 Index, Count;
|
||||
|
||||
DEBUG ((DEBUG_BLKIO, "NorFlashWriteSingleBlock(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumBytes, Buffer));
|
||||
|
||||
@@ -621,23 +622,17 @@ NorFlashWriteSingleBlock (
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
- Status = NorFlashWriteBuffer (
|
||||
- Instance,
|
||||
- BlockAddress + Start,
|
||||
- P30_MAX_BUFFER_SIZE_IN_BYTES,
|
||||
- Instance->ShadowBuffer
|
||||
- );
|
||||
- if (EFI_ERROR (Status)) {
|
||||
- goto Exit;
|
||||
- }
|
||||
-
|
||||
- if ((End - Start) > P30_MAX_BUFFER_SIZE_IN_BYTES) {
|
||||
+ Count = (End - Start) / P30_MAX_BUFFER_SIZE_IN_BYTES;
|
||||
+ for (Index = 0; Index < Count; Index++) {
|
||||
Status = NorFlashWriteBuffer (
|
||||
Instance,
|
||||
- BlockAddress + Start + P30_MAX_BUFFER_SIZE_IN_BYTES,
|
||||
+ BlockAddress + Start + Index * P30_MAX_BUFFER_SIZE_IN_BYTES,
|
||||
P30_MAX_BUFFER_SIZE_IN_BYTES,
|
||||
- Instance->ShadowBuffer + P30_MAX_BUFFER_SIZE_IN_BYTES
|
||||
+ Instance->ShadowBuffer + Index * P30_MAX_BUFFER_SIZE_IN_BYTES
|
||||
);
|
||||
+ if (EFI_ERROR (Status)) {
|
||||
+ goto Exit;
|
||||
+ }
|
||||
}
|
||||
|
||||
Exit:
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,55 @@
|
||||
From e8150ee7fdf1421d2e2801c901e0196496ef599e Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Tue, 16 Jan 2024 18:11:00 +0100
|
||||
Subject: [PATCH 11/18] OvmfPkg/VirtNorFlashDxe: add casts to UINTN and UINT32
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
RH-Author: Gerd Hoffmann <None>
|
||||
RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport
|
||||
RH-Jira: RHEL-17587
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [13/20] fa695acadb9d693242b5221d2bc1958b929718e7
|
||||
|
||||
This is needed to avoid bit operations being applied to signed integers.
|
||||
|
||||
Suggested-by: László Érsek <lersek@redhat.com>
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
|
||||
Message-Id: <20240116171105.37831-2-kraxel@redhat.com>
|
||||
(cherry picked from commit 0395045ae307c43a41f72ca9a8bf4eb8f16b2fe0)
|
||||
---
|
||||
OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 2 +-
|
||||
OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
index 1afd60ce66..7f4743b003 100644
|
||||
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
@@ -581,7 +581,7 @@ NorFlashWriteSingleBlock (
|
||||
// contents, while checking whether the old version had any bits cleared
|
||||
// that we want to set. In that case, we will need to erase the block first.
|
||||
for (CurOffset = 0; CurOffset < *NumBytes; CurOffset++) {
|
||||
- if (~OrigData[CurOffset] & Buffer[CurOffset]) {
|
||||
+ if (~(UINT32)OrigData[CurOffset] & (UINT32)Buffer[CurOffset]) {
|
||||
goto DoErase;
|
||||
}
|
||||
|
||||
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h
|
||||
index b7f5d208b2..455eafacc2 100644
|
||||
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h
|
||||
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h
|
||||
@@ -61,7 +61,7 @@
|
||||
#define P30_MAX_BUFFER_SIZE_IN_BYTES ((UINTN)128)
|
||||
#define P30_MAX_BUFFER_SIZE_IN_WORDS (P30_MAX_BUFFER_SIZE_IN_BYTES/((UINTN)4))
|
||||
#define MAX_BUFFERED_PROG_ITERATIONS 10000000
|
||||
-#define BOUNDARY_OF_32_WORDS 0x7F
|
||||
+#define BOUNDARY_OF_32_WORDS ((UINTN)0x7F)
|
||||
|
||||
// CFI Addresses
|
||||
#define P30_CFI_ADDR_QUERY_UNIQUE_QRY 0x10
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,65 @@
|
||||
From 0193a89b0db837da31301bc1edb8382927842978 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Tue, 16 Jan 2024 18:11:03 +0100
|
||||
Subject: [PATCH 14/18] OvmfPkg/VirtNorFlashDxe: allow larger writes without
|
||||
block erase
|
||||
|
||||
RH-Author: Gerd Hoffmann <None>
|
||||
RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport
|
||||
RH-Jira: RHEL-17587
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [16/20] 27ac63b90eb5e6fdc00cbc5a9105c3178ee559cd
|
||||
|
||||
Raise the limit for writes without block erase from two to four
|
||||
P30_MAX_BUFFER_SIZE_IN_BYTES blocks. With this in place almost all efi
|
||||
variable updates are handled without block erase. With the old limit
|
||||
some variable updates (with device paths) took the block erase code
|
||||
path.
|
||||
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
|
||||
Message-Id: <20240116171105.37831-5-kraxel@redhat.com>
|
||||
(cherry picked from commit b25733c97442513890ae6bb8e10fd340f13844a7)
|
||||
---
|
||||
OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 18 ++++++++++--------
|
||||
1 file changed, 10 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
index 3d1343b381..3d1d20daa1 100644
|
||||
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
@@ -550,13 +550,15 @@ NorFlashWriteSingleBlock (
|
||||
return EFI_BAD_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
- // Pick P30_MAX_BUFFER_SIZE_IN_BYTES (== 128 bytes) as a good start for word
|
||||
- // operations as opposed to erasing the block and writing the data regardless
|
||||
- // if an erase is really needed. It looks like most individual NV variable
|
||||
- // writes are smaller than 128 bytes.
|
||||
- // To avoid pathological cases were a 2 byte write is disregarded because it
|
||||
- // occurs right at a 128 byte buffered write alignment boundary, permit up to
|
||||
- // twice the max buffer size, and perform two writes if needed.
|
||||
+ // Pick 4 * P30_MAX_BUFFER_SIZE_IN_BYTES (== 512 bytes) as a good
|
||||
+ // start for word operations as opposed to erasing the block and
|
||||
+ // writing the data regardless if an erase is really needed.
|
||||
+ //
|
||||
+ // Many NV variable updates are small enough for a a single
|
||||
+ // P30_MAX_BUFFER_SIZE_IN_BYTES block write. In case the update is
|
||||
+ // larger than a single block, or the update crosses a
|
||||
+ // P30_MAX_BUFFER_SIZE_IN_BYTES boundary (as shown in the diagram
|
||||
+ // below), or both, we might have to write two or more blocks.
|
||||
//
|
||||
// 0 128 256
|
||||
// [----------------|----------------]
|
||||
@@ -578,7 +580,7 @@ NorFlashWriteSingleBlock (
|
||||
Start = Offset & ~BOUNDARY_OF_32_WORDS;
|
||||
End = ALIGN_VALUE (Offset + *NumBytes, P30_MAX_BUFFER_SIZE_IN_BYTES);
|
||||
|
||||
- if ((End - Start) <= (2 * P30_MAX_BUFFER_SIZE_IN_BYTES)) {
|
||||
+ if ((End - Start) <= (4 * P30_MAX_BUFFER_SIZE_IN_BYTES)) {
|
||||
// Check to see if we need to erase before programming the data into NOR.
|
||||
// If the destination bits are only changing from 1s to 0s we can just write.
|
||||
// After a block is erased all bits in the block is set to 1.
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,89 @@
|
||||
From 20ba071dabad6b0f5663083a017799b7a6e684c5 Mon Sep 17 00:00:00 2001
|
||||
From: Ard Biesheuvel <ardb@kernel.org>
|
||||
Date: Mon, 24 Oct 2022 17:34:09 +0200
|
||||
Subject: [PATCH 05/18] OvmfPkg/VirtNorFlashDxe: avoid array mode switch after
|
||||
each word write
|
||||
|
||||
RH-Author: Gerd Hoffmann <None>
|
||||
RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport
|
||||
RH-Jira: RHEL-17587
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [7/20] 274f2ed71a6d5d3f6497129ee3c62f494cc2f067
|
||||
|
||||
NorFlashWriteSingleWord() switches into programming mode and back into
|
||||
array mode for every single word that it writes. Under KVM, this
|
||||
involves tearing down the read-only memslot, and setting it up again,
|
||||
which is costly and unnecessary.
|
||||
|
||||
Instead, move the array mode switch into the callers, and only make the
|
||||
switch when the writing is done.
|
||||
|
||||
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
|
||||
Reviewed-by: Sunil V L <sunilvl@ventanamicro.com>
|
||||
(cherry picked from commit ca01e6216a8d1a26c69018e216d1dc3f88a819a4)
|
||||
---
|
||||
OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 12 +++---------
|
||||
OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c | 3 +++
|
||||
2 files changed, 6 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
index f41d9d372f..0a5c5d48c7 100644
|
||||
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
@@ -205,9 +205,6 @@ NorFlashWriteSingleWord (
|
||||
SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER);
|
||||
}
|
||||
|
||||
- // Put device back into Read Array mode
|
||||
- SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
|
||||
-
|
||||
return Status;
|
||||
}
|
||||
|
||||
@@ -286,8 +283,7 @@ NorFlashWriteBuffer (
|
||||
|
||||
// The buffer was not available for writing
|
||||
if (WaitForBuffer == 0) {
|
||||
- Status = EFI_DEVICE_ERROR;
|
||||
- goto EXIT;
|
||||
+ return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
// From now on we work in 32-bit words
|
||||
@@ -337,10 +333,6 @@ NorFlashWriteBuffer (
|
||||
SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER);
|
||||
}
|
||||
|
||||
-EXIT:
|
||||
- // Put device back into Read Array mode
|
||||
- SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
|
||||
-
|
||||
return Status;
|
||||
}
|
||||
|
||||
@@ -739,6 +731,8 @@ NorFlashWriteSingleBlock (
|
||||
}
|
||||
|
||||
TempStatus = NorFlashWriteSingleWord (Instance, WordAddr, WordToWrite);
|
||||
+ // Put device back into Read Array mode
|
||||
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
|
||||
if (EFI_ERROR (TempStatus)) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c
|
||||
index 2ceda22635..f9a41f6aab 100644
|
||||
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c
|
||||
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c
|
||||
@@ -280,6 +280,9 @@ NorFlashWriteFullBlock (
|
||||
}
|
||||
|
||||
EXIT:
|
||||
+ // Put device back into Read Array mode
|
||||
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
|
||||
+
|
||||
if (!EfiAtRuntime ()) {
|
||||
// Interruptions can resume.
|
||||
gBS->RestoreTPL (OriginalTPL);
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,303 @@
|
||||
From 67e26db39c0ec90c164634251da761f649546529 Mon Sep 17 00:00:00 2001
|
||||
From: Ard Biesheuvel <ardb@kernel.org>
|
||||
Date: Mon, 24 Oct 2022 17:58:07 +0200
|
||||
Subject: [PATCH 06/18] OvmfPkg/VirtNorFlashDxe: avoid switching between modes
|
||||
in a tight loop
|
||||
|
||||
RH-Author: Gerd Hoffmann <None>
|
||||
RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport
|
||||
RH-Jira: RHEL-17587
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [8/20] 4923b0fb1586d7955be466b90dce5f790da704ff
|
||||
|
||||
Currently, when dealing with small updates that can be written out
|
||||
directly (i.e., if they only involve clearing bits and not setting bits,
|
||||
as the latter requires a block level erase), we iterate over the data
|
||||
one word at a time, read the old value, compare it, write the new value,
|
||||
and repeat, unless we encountered a value that we cannot write (0->1
|
||||
transition), in which case we fall back to a block level operation.
|
||||
|
||||
This is inefficient for two reasons:
|
||||
- reading and writing a word at a time involves switching between array
|
||||
and programming mode for every word of data, which is
|
||||
disproportionately costly when running under KVM;
|
||||
- we end up writing some data twice, as we may not notice that a block
|
||||
erase is needed until after some data has been written to flash.
|
||||
|
||||
So replace this sequence with a single read of up to twice the buffered
|
||||
write maximum size, followed by one or two buffered writes if the data
|
||||
can be written directly. Otherwise, fall back to the existing block
|
||||
level sequence, but without writing out part of the data twice.
|
||||
|
||||
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
|
||||
Reviewed-by: Sunil V L <sunilvl@ventanamicro.com>
|
||||
(cherry picked from commit 25589c4a76e7e3668fd6f794dd1827e958b6719c)
|
||||
---
|
||||
OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 214 +++++++++----------------
|
||||
1 file changed, 76 insertions(+), 138 deletions(-)
|
||||
|
||||
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
index 0a5c5d48c7..0343131a54 100644
|
||||
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
@@ -576,23 +576,20 @@ NorFlashWriteSingleBlock (
|
||||
IN UINT8 *Buffer
|
||||
)
|
||||
{
|
||||
- EFI_STATUS TempStatus;
|
||||
- UINT32 Tmp;
|
||||
- UINT32 TmpBuf;
|
||||
- UINT32 WordToWrite;
|
||||
- UINT32 Mask;
|
||||
- BOOLEAN DoErase;
|
||||
- UINTN BytesToWrite;
|
||||
+ EFI_STATUS Status;
|
||||
UINTN CurOffset;
|
||||
- UINTN WordAddr;
|
||||
UINTN BlockSize;
|
||||
UINTN BlockAddress;
|
||||
- UINTN PrevBlockAddress;
|
||||
-
|
||||
- PrevBlockAddress = 0;
|
||||
+ UINT8 *OrigData;
|
||||
|
||||
DEBUG ((DEBUG_BLKIO, "NorFlashWriteSingleBlock(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumBytes, Buffer));
|
||||
|
||||
+ // Check we did get some memory. Buffer is BlockSize.
|
||||
+ if (Instance->ShadowBuffer == NULL) {
|
||||
+ DEBUG ((DEBUG_ERROR, "FvbWrite: ERROR - Buffer not ready\n"));
|
||||
+ return EFI_DEVICE_ERROR;
|
||||
+ }
|
||||
+
|
||||
// Cache the block size to avoid de-referencing pointers all the time
|
||||
BlockSize = Instance->BlockSize;
|
||||
|
||||
@@ -612,148 +609,89 @@ NorFlashWriteSingleBlock (
|
||||
return EFI_BAD_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
- // Pick 128bytes as a good start for word operations as opposed to erasing the
|
||||
- // block and writing the data regardless if an erase is really needed.
|
||||
- // It looks like most individual NV variable writes are smaller than 128bytes.
|
||||
- if (*NumBytes <= 128) {
|
||||
+ // Pick P30_MAX_BUFFER_SIZE_IN_BYTES (== 128 bytes) as a good start for word
|
||||
+ // operations as opposed to erasing the block and writing the data regardless
|
||||
+ // if an erase is really needed. It looks like most individual NV variable
|
||||
+ // writes are smaller than 128 bytes.
|
||||
+ // To avoid pathological cases were a 2 byte write is disregarded because it
|
||||
+ // occurs right at a 128 byte buffered write alignment boundary, permit up to
|
||||
+ // twice the max buffer size, and perform two writes if needed.
|
||||
+ if ((*NumBytes + (Offset & BOUNDARY_OF_32_WORDS)) <= (2 * P30_MAX_BUFFER_SIZE_IN_BYTES)) {
|
||||
// Check to see if we need to erase before programming the data into NOR.
|
||||
// If the destination bits are only changing from 1s to 0s we can just write.
|
||||
// After a block is erased all bits in the block is set to 1.
|
||||
// If any byte requires us to erase we just give up and rewrite all of it.
|
||||
- DoErase = FALSE;
|
||||
- BytesToWrite = *NumBytes;
|
||||
- CurOffset = Offset;
|
||||
-
|
||||
- while (BytesToWrite > 0) {
|
||||
- // Read full word from NOR, splice as required. A word is the smallest
|
||||
- // unit we can write.
|
||||
- TempStatus = NorFlashRead (Instance, Lba, CurOffset & ~(0x3), sizeof (Tmp), &Tmp);
|
||||
- if (EFI_ERROR (TempStatus)) {
|
||||
- return EFI_DEVICE_ERROR;
|
||||
- }
|
||||
|
||||
- // Physical address of word in NOR to write.
|
||||
- WordAddr = (CurOffset & ~(0x3)) + GET_NOR_BLOCK_ADDRESS (
|
||||
- Instance->RegionBaseAddress,
|
||||
- Lba,
|
||||
- BlockSize
|
||||
- );
|
||||
- // The word of data that is to be written.
|
||||
- TmpBuf = *((UINT32 *)(Buffer + (*NumBytes - BytesToWrite)));
|
||||
-
|
||||
- // First do word aligned chunks.
|
||||
- if ((CurOffset & 0x3) == 0) {
|
||||
- if (BytesToWrite >= 4) {
|
||||
- // Is the destination still in 'erased' state?
|
||||
- if (~Tmp != 0) {
|
||||
- // Check to see if we are only changing bits to zero.
|
||||
- if ((Tmp ^ TmpBuf) & TmpBuf) {
|
||||
- DoErase = TRUE;
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- // Write this word to NOR
|
||||
- WordToWrite = TmpBuf;
|
||||
- CurOffset += sizeof (TmpBuf);
|
||||
- BytesToWrite -= sizeof (TmpBuf);
|
||||
- } else {
|
||||
- // BytesToWrite < 4. Do small writes and left-overs
|
||||
- Mask = ~((~0) << (BytesToWrite * 8));
|
||||
- // Mask out the bytes we want.
|
||||
- TmpBuf &= Mask;
|
||||
- // Is the destination still in 'erased' state?
|
||||
- if ((Tmp & Mask) != Mask) {
|
||||
- // Check to see if we are only changing bits to zero.
|
||||
- if ((Tmp ^ TmpBuf) & TmpBuf) {
|
||||
- DoErase = TRUE;
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- // Merge old and new data. Write merged word to NOR
|
||||
- WordToWrite = (Tmp & ~Mask) | TmpBuf;
|
||||
- CurOffset += BytesToWrite;
|
||||
- BytesToWrite = 0;
|
||||
- }
|
||||
- } else {
|
||||
- // Do multiple words, but starting unaligned.
|
||||
- if (BytesToWrite > (4 - (CurOffset & 0x3))) {
|
||||
- Mask = ((~0) << ((CurOffset & 0x3) * 8));
|
||||
- // Mask out the bytes we want.
|
||||
- TmpBuf &= Mask;
|
||||
- // Is the destination still in 'erased' state?
|
||||
- if ((Tmp & Mask) != Mask) {
|
||||
- // Check to see if we are only changing bits to zero.
|
||||
- if ((Tmp ^ TmpBuf) & TmpBuf) {
|
||||
- DoErase = TRUE;
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- // Merge old and new data. Write merged word to NOR
|
||||
- WordToWrite = (Tmp & ~Mask) | TmpBuf;
|
||||
- BytesToWrite -= (4 - (CurOffset & 0x3));
|
||||
- CurOffset += (4 - (CurOffset & 0x3));
|
||||
- } else {
|
||||
- // Unaligned and fits in one word.
|
||||
- Mask = (~((~0) << (BytesToWrite * 8))) << ((CurOffset & 0x3) * 8);
|
||||
- // Mask out the bytes we want.
|
||||
- TmpBuf = (TmpBuf << ((CurOffset & 0x3) * 8)) & Mask;
|
||||
- // Is the destination still in 'erased' state?
|
||||
- if ((Tmp & Mask) != Mask) {
|
||||
- // Check to see if we are only changing bits to zero.
|
||||
- if ((Tmp ^ TmpBuf) & TmpBuf) {
|
||||
- DoErase = TRUE;
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- // Merge old and new data. Write merged word to NOR
|
||||
- WordToWrite = (Tmp & ~Mask) | TmpBuf;
|
||||
- CurOffset += BytesToWrite;
|
||||
- BytesToWrite = 0;
|
||||
- }
|
||||
+ // Read the old version of the data into the shadow buffer
|
||||
+ Status = NorFlashRead (
|
||||
+ Instance,
|
||||
+ Lba,
|
||||
+ Offset & ~BOUNDARY_OF_32_WORDS,
|
||||
+ (*NumBytes | BOUNDARY_OF_32_WORDS) + 1,
|
||||
+ Instance->ShadowBuffer
|
||||
+ );
|
||||
+ if (EFI_ERROR (Status)) {
|
||||
+ return EFI_DEVICE_ERROR;
|
||||
+ }
|
||||
+
|
||||
+ // Make OrigData point to the start of the old version of the data inside
|
||||
+ // the word aligned buffer
|
||||
+ OrigData = Instance->ShadowBuffer + (Offset & BOUNDARY_OF_32_WORDS);
|
||||
+
|
||||
+ // Update the buffer containing the old version of the data with the new
|
||||
+ // contents, while checking whether the old version had any bits cleared
|
||||
+ // that we want to set. In that case, we will need to erase the block first.
|
||||
+ for (CurOffset = 0; CurOffset < *NumBytes; CurOffset++) {
|
||||
+ if (~OrigData[CurOffset] & Buffer[CurOffset]) {
|
||||
+ goto DoErase;
|
||||
}
|
||||
|
||||
- //
|
||||
- // Write the word to NOR.
|
||||
- //
|
||||
+ OrigData[CurOffset] = Buffer[CurOffset];
|
||||
+ }
|
||||
|
||||
- BlockAddress = GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba, BlockSize);
|
||||
- if (BlockAddress != PrevBlockAddress) {
|
||||
- TempStatus = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress);
|
||||
- if (EFI_ERROR (TempStatus)) {
|
||||
- return EFI_DEVICE_ERROR;
|
||||
- }
|
||||
+ //
|
||||
+ // Write the updated buffer to NOR.
|
||||
+ //
|
||||
+ BlockAddress = GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba, BlockSize);
|
||||
|
||||
- PrevBlockAddress = BlockAddress;
|
||||
- }
|
||||
+ // Unlock the block if we have to
|
||||
+ Status = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress);
|
||||
+ if (EFI_ERROR (Status)) {
|
||||
+ goto Exit;
|
||||
+ }
|
||||
|
||||
- TempStatus = NorFlashWriteSingleWord (Instance, WordAddr, WordToWrite);
|
||||
- // Put device back into Read Array mode
|
||||
- SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
|
||||
- if (EFI_ERROR (TempStatus)) {
|
||||
- return EFI_DEVICE_ERROR;
|
||||
- }
|
||||
+ Status = NorFlashWriteBuffer (
|
||||
+ Instance,
|
||||
+ BlockAddress + (Offset & ~BOUNDARY_OF_32_WORDS),
|
||||
+ P30_MAX_BUFFER_SIZE_IN_BYTES,
|
||||
+ Instance->ShadowBuffer
|
||||
+ );
|
||||
+ if (EFI_ERROR (Status)) {
|
||||
+ goto Exit;
|
||||
}
|
||||
|
||||
- // Exit if we got here and could write all the data. Otherwise do the
|
||||
- // Erase-Write cycle.
|
||||
- if (!DoErase) {
|
||||
- return EFI_SUCCESS;
|
||||
+ if ((*NumBytes + (Offset & BOUNDARY_OF_32_WORDS)) > P30_MAX_BUFFER_SIZE_IN_BYTES) {
|
||||
+ BlockAddress += P30_MAX_BUFFER_SIZE_IN_BYTES;
|
||||
+
|
||||
+ Status = NorFlashWriteBuffer (
|
||||
+ Instance,
|
||||
+ BlockAddress + (Offset & ~BOUNDARY_OF_32_WORDS),
|
||||
+ P30_MAX_BUFFER_SIZE_IN_BYTES,
|
||||
+ Instance->ShadowBuffer + P30_MAX_BUFFER_SIZE_IN_BYTES
|
||||
+ );
|
||||
}
|
||||
- }
|
||||
|
||||
- // Check we did get some memory. Buffer is BlockSize.
|
||||
- if (Instance->ShadowBuffer == NULL) {
|
||||
- DEBUG ((DEBUG_ERROR, "FvbWrite: ERROR - Buffer not ready\n"));
|
||||
- return EFI_DEVICE_ERROR;
|
||||
+Exit:
|
||||
+ // Put device back into Read Array mode
|
||||
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
|
||||
+
|
||||
+ return Status;
|
||||
}
|
||||
|
||||
+DoErase:
|
||||
// Read NOR Flash data into shadow buffer
|
||||
- TempStatus = NorFlashReadBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer);
|
||||
- if (EFI_ERROR (TempStatus)) {
|
||||
+ Status = NorFlashReadBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer);
|
||||
+ if (EFI_ERROR (Status)) {
|
||||
// Return one of the pre-approved error statuses
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
@@ -762,8 +700,8 @@ NorFlashWriteSingleBlock (
|
||||
CopyMem ((VOID *)((UINTN)Instance->ShadowBuffer + Offset), Buffer, *NumBytes);
|
||||
|
||||
// Write the modified buffer back to the NorFlash
|
||||
- TempStatus = NorFlashWriteBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer);
|
||||
- if (EFI_ERROR (TempStatus)) {
|
||||
+ Status = NorFlashWriteBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer);
|
||||
+ if (EFI_ERROR (Status)) {
|
||||
// Return one of the pre-approved error statuses
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,110 @@
|
||||
From f136d4895b1477a56b916a76448ba76e67b08163 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Tue, 16 Jan 2024 18:11:01 +0100
|
||||
Subject: [PATCH 12/18] OvmfPkg/VirtNorFlashDxe: clarify block write logic &
|
||||
fix shadowbuffer reads
|
||||
|
||||
RH-Author: Gerd Hoffmann <None>
|
||||
RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport
|
||||
RH-Jira: RHEL-17587
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [14/20] 38009625e5f189166f7a93e236576140a7ccb393
|
||||
|
||||
Introduce 'Start' and 'End' variables to make it easier to follow the
|
||||
logic and code flow. Also add a ascii art diagram (based on a
|
||||
suggestion by Laszlo).
|
||||
|
||||
This also fixes the 'Size' calculation for the NorFlashRead() call.
|
||||
Without this patch the code will read only one instead of two
|
||||
P30_MAX_BUFFER_SIZE_IN_BYTES blocks in case '*NumBytes' is smaller than
|
||||
P30_MAX_BUFFER_SIZE_IN_BYTES but 'Offset + *NumBytes' is not, i.e. the
|
||||
update range crosses a P30_MAX_BUFFER_SIZE_IN_BYTES boundary.
|
||||
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
|
||||
Message-Id: <20240116171105.37831-3-kraxel@redhat.com>
|
||||
(cherry picked from commit 35d8ea8097794b522149688b5cfaf8364bc44d54)
|
||||
---
|
||||
OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 36 ++++++++++++++++++++------
|
||||
1 file changed, 28 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
index 7f4743b003..88a4d2c23f 100644
|
||||
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
@@ -520,6 +520,7 @@ NorFlashWriteSingleBlock (
|
||||
UINTN BlockSize;
|
||||
UINTN BlockAddress;
|
||||
UINT8 *OrigData;
|
||||
+ UINTN Start, End;
|
||||
|
||||
DEBUG ((DEBUG_BLKIO, "NorFlashWriteSingleBlock(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumBytes, Buffer));
|
||||
|
||||
@@ -555,7 +556,28 @@ NorFlashWriteSingleBlock (
|
||||
// To avoid pathological cases were a 2 byte write is disregarded because it
|
||||
// occurs right at a 128 byte buffered write alignment boundary, permit up to
|
||||
// twice the max buffer size, and perform two writes if needed.
|
||||
- if ((*NumBytes + (Offset & BOUNDARY_OF_32_WORDS)) <= (2 * P30_MAX_BUFFER_SIZE_IN_BYTES)) {
|
||||
+ //
|
||||
+ // 0 128 256
|
||||
+ // [----------------|----------------]
|
||||
+ // ^ ^ ^ ^
|
||||
+ // | | | |
|
||||
+ // | | | End, the next "word" boundary beyond
|
||||
+ // | | | the (logical) update
|
||||
+ // | | |
|
||||
+ // | | (Offset & BOUNDARY_OF_32_WORDS) + NumBytes;
|
||||
+ // | | i.e., the relative offset inside (or just past)
|
||||
+ // | | the *double-word* such that it is the
|
||||
+ // | | *exclusive* end of the (logical) update.
|
||||
+ // | |
|
||||
+ // | Offset & BOUNDARY_OF_32_WORDS; i.e., Offset within the "word";
|
||||
+ // | this is where the (logical) update is supposed to start
|
||||
+ // |
|
||||
+ // Start = Offset & ~BOUNDARY_OF_32_WORDS; i.e., Offset truncated to "word" boundary
|
||||
+
|
||||
+ Start = Offset & ~BOUNDARY_OF_32_WORDS;
|
||||
+ End = ALIGN_VALUE (Offset + *NumBytes, P30_MAX_BUFFER_SIZE_IN_BYTES);
|
||||
+
|
||||
+ if ((End - Start) <= (2 * P30_MAX_BUFFER_SIZE_IN_BYTES)) {
|
||||
// Check to see if we need to erase before programming the data into NOR.
|
||||
// If the destination bits are only changing from 1s to 0s we can just write.
|
||||
// After a block is erased all bits in the block is set to 1.
|
||||
@@ -565,8 +587,8 @@ NorFlashWriteSingleBlock (
|
||||
Status = NorFlashRead (
|
||||
Instance,
|
||||
Lba,
|
||||
- Offset & ~BOUNDARY_OF_32_WORDS,
|
||||
- (*NumBytes | BOUNDARY_OF_32_WORDS) + 1,
|
||||
+ Start,
|
||||
+ End - Start,
|
||||
Instance->ShadowBuffer
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
@@ -601,7 +623,7 @@ NorFlashWriteSingleBlock (
|
||||
|
||||
Status = NorFlashWriteBuffer (
|
||||
Instance,
|
||||
- BlockAddress + (Offset & ~BOUNDARY_OF_32_WORDS),
|
||||
+ BlockAddress + Start,
|
||||
P30_MAX_BUFFER_SIZE_IN_BYTES,
|
||||
Instance->ShadowBuffer
|
||||
);
|
||||
@@ -609,12 +631,10 @@ NorFlashWriteSingleBlock (
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
- if ((*NumBytes + (Offset & BOUNDARY_OF_32_WORDS)) > P30_MAX_BUFFER_SIZE_IN_BYTES) {
|
||||
- BlockAddress += P30_MAX_BUFFER_SIZE_IN_BYTES;
|
||||
-
|
||||
+ if ((End - Start) > P30_MAX_BUFFER_SIZE_IN_BYTES) {
|
||||
Status = NorFlashWriteBuffer (
|
||||
Instance,
|
||||
- BlockAddress + (Offset & ~BOUNDARY_OF_32_WORDS),
|
||||
+ BlockAddress + Start + P30_MAX_BUFFER_SIZE_IN_BYTES,
|
||||
P30_MAX_BUFFER_SIZE_IN_BYTES,
|
||||
Instance->ShadowBuffer + P30_MAX_BUFFER_SIZE_IN_BYTES
|
||||
);
|
||||
--
|
||||
2.41.0
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,504 @@
|
||||
From 8cf16599ade30de07c9b51f90d2208046f74fee6 Mon Sep 17 00:00:00 2001
|
||||
From: Ard Biesheuvel <ardb@kernel.org>
|
||||
Date: Mon, 24 Oct 2022 17:12:08 +0200
|
||||
Subject: [PATCH 04/18] OvmfPkg/VirtNorFlashDxe: drop block I/O protocol
|
||||
implementation
|
||||
|
||||
RH-Author: Gerd Hoffmann <None>
|
||||
RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport
|
||||
RH-Jira: RHEL-17587
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [6/20] 6843078997a30c2818e0d53a90fb7f6accb89aaf
|
||||
|
||||
We never boot from NOR flash, and generally rely on the firmware volume
|
||||
PI protocols to expose the contents. So drop the block I/O protocol
|
||||
implementation from VirtNorFlashDxe.
|
||||
|
||||
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
|
||||
Reviewed-by: Sunil V L <sunilvl@ventanamicro.com>
|
||||
(cherry picked from commit 83f11f957240ead9b135a778316330762b0a3acb)
|
||||
---
|
||||
OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 49 ++++++------------
|
||||
OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h | 54 ++------------------
|
||||
OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c | 40 +++------------
|
||||
OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf | 1 -
|
||||
OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c | 55 ++++++++-------------
|
||||
5 files changed, 45 insertions(+), 154 deletions(-)
|
||||
|
||||
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
index 1094d48f7d..f41d9d372f 100644
|
||||
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
@@ -366,10 +366,6 @@ NorFlashWriteBlocks (
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
- if (Instance->Media.ReadOnly == TRUE) {
|
||||
- return EFI_WRITE_PROTECTED;
|
||||
- }
|
||||
-
|
||||
// We must have some bytes to read
|
||||
DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: BufferSizeInBytes=0x%x\n", BufferSizeInBytes));
|
||||
if (BufferSizeInBytes == 0) {
|
||||
@@ -377,22 +373,22 @@ NorFlashWriteBlocks (
|
||||
}
|
||||
|
||||
// The size of the buffer must be a multiple of the block size
|
||||
- DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: BlockSize in bytes =0x%x\n", Instance->Media.BlockSize));
|
||||
- if ((BufferSizeInBytes % Instance->Media.BlockSize) != 0) {
|
||||
+ DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: BlockSize in bytes =0x%x\n", Instance->BlockSize));
|
||||
+ if ((BufferSizeInBytes % Instance->BlockSize) != 0) {
|
||||
return EFI_BAD_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
// All blocks must be within the device
|
||||
- NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize;
|
||||
+ NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->BlockSize;
|
||||
|
||||
- DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: NumBlocks=%d, LastBlock=%ld, Lba=%ld.\n", NumBlocks, Instance->Media.LastBlock, Lba));
|
||||
+ DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: NumBlocks=%d, LastBlock=%ld, Lba=%ld.\n", NumBlocks, Instance->LastBlock, Lba));
|
||||
|
||||
- if ((Lba + NumBlocks) > (Instance->Media.LastBlock + 1)) {
|
||||
+ if ((Lba + NumBlocks) > (Instance->LastBlock + 1)) {
|
||||
DEBUG ((DEBUG_ERROR, "NorFlashWriteBlocks: ERROR - Write will exceed last block.\n"));
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
- BlockSizeInWords = Instance->Media.BlockSize / 4;
|
||||
+ BlockSizeInWords = Instance->BlockSize / 4;
|
||||
|
||||
// Because the target *Buffer is a pointer to VOID, we must put all the data into a pointer
|
||||
// to a proper data type, so use *ReadBuffer
|
||||
@@ -489,8 +485,8 @@ NorFlashReadBlocks (
|
||||
DEBUG_BLKIO,
|
||||
"NorFlashReadBlocks: BufferSize=0x%xB BlockSize=0x%xB LastBlock=%ld, Lba=%ld.\n",
|
||||
BufferSizeInBytes,
|
||||
- Instance->Media.BlockSize,
|
||||
- Instance->Media.LastBlock,
|
||||
+ Instance->BlockSize,
|
||||
+ Instance->LastBlock,
|
||||
Lba
|
||||
));
|
||||
|
||||
@@ -505,14 +501,14 @@ NorFlashReadBlocks (
|
||||
}
|
||||
|
||||
// The size of the buffer must be a multiple of the block size
|
||||
- if ((BufferSizeInBytes % Instance->Media.BlockSize) != 0) {
|
||||
+ if ((BufferSizeInBytes % Instance->BlockSize) != 0) {
|
||||
return EFI_BAD_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
// All blocks must be within the device
|
||||
- NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize;
|
||||
+ NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->BlockSize;
|
||||
|
||||
- if ((Lba + NumBlocks) > (Instance->Media.LastBlock + 1)) {
|
||||
+ if ((Lba + NumBlocks) > (Instance->LastBlock + 1)) {
|
||||
DEBUG ((DEBUG_ERROR, "NorFlashReadBlocks: ERROR - Read will exceed last block\n"));
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
@@ -521,7 +517,7 @@ NorFlashReadBlocks (
|
||||
StartAddress = GET_NOR_BLOCK_ADDRESS (
|
||||
Instance->RegionBaseAddress,
|
||||
Lba,
|
||||
- Instance->Media.BlockSize
|
||||
+ Instance->BlockSize
|
||||
);
|
||||
|
||||
// Put the device into Read Array mode
|
||||
@@ -554,7 +550,7 @@ NorFlashRead (
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
- if (((Lba * Instance->Media.BlockSize) + Offset + BufferSizeInBytes) > Instance->Size) {
|
||||
+ if (((Lba * Instance->BlockSize) + Offset + BufferSizeInBytes) > Instance->Size) {
|
||||
DEBUG ((DEBUG_ERROR, "NorFlashRead: ERROR - Read will exceed device size.\n"));
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
@@ -563,7 +559,7 @@ NorFlashRead (
|
||||
StartAddress = GET_NOR_BLOCK_ADDRESS (
|
||||
Instance->RegionBaseAddress,
|
||||
Lba,
|
||||
- Instance->Media.BlockSize
|
||||
+ Instance->BlockSize
|
||||
);
|
||||
|
||||
// Put the device into Read Array mode
|
||||
@@ -577,7 +573,7 @@ NorFlashRead (
|
||||
|
||||
/*
|
||||
Write a full or portion of a block. It must not span block boundaries; that is,
|
||||
- Offset + *NumBytes <= Instance->Media.BlockSize.
|
||||
+ Offset + *NumBytes <= Instance->BlockSize.
|
||||
*/
|
||||
EFI_STATUS
|
||||
NorFlashWriteSingleBlock (
|
||||
@@ -605,15 +601,8 @@ NorFlashWriteSingleBlock (
|
||||
|
||||
DEBUG ((DEBUG_BLKIO, "NorFlashWriteSingleBlock(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumBytes, Buffer));
|
||||
|
||||
- // Detect WriteDisabled state
|
||||
- if (Instance->Media.ReadOnly == TRUE) {
|
||||
- DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleBlock: ERROR - Can not write: Device is in WriteDisabled state.\n"));
|
||||
- // It is in WriteDisabled state, return an error right away
|
||||
- return EFI_ACCESS_DENIED;
|
||||
- }
|
||||
-
|
||||
// Cache the block size to avoid de-referencing pointers all the time
|
||||
- BlockSize = Instance->Media.BlockSize;
|
||||
+ BlockSize = Instance->BlockSize;
|
||||
|
||||
// The write must not span block boundaries.
|
||||
// We need to check each variable individually because adding two large values together overflows.
|
||||
@@ -819,12 +808,6 @@ NorFlashVirtualNotifyEvent (
|
||||
EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->DeviceBaseAddress);
|
||||
EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->RegionBaseAddress);
|
||||
|
||||
- // Convert BlockIo protocol
|
||||
- EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->BlockIoProtocol.FlushBlocks);
|
||||
- EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->BlockIoProtocol.ReadBlocks);
|
||||
- EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->BlockIoProtocol.Reset);
|
||||
- EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->BlockIoProtocol.WriteBlocks);
|
||||
-
|
||||
// Convert Fvb
|
||||
EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.EraseBlocks);
|
||||
EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.GetAttributes);
|
||||
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h
|
||||
index 7733ee02ee..b7f5d208b2 100644
|
||||
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h
|
||||
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include <Guid/EventGroup.h>
|
||||
|
||||
-#include <Protocol/BlockIo.h>
|
||||
#include <Protocol/FirmwareVolumeBlock.h>
|
||||
|
||||
#include <Library/DebugLib.h>
|
||||
@@ -108,8 +107,7 @@
|
||||
#define P30_CMD_READ_CONFIGURATION_REGISTER 0x0003
|
||||
|
||||
#define NOR_FLASH_SIGNATURE SIGNATURE_32('n', 'o', 'r', '0')
|
||||
-#define INSTANCE_FROM_FVB_THIS(a) CR(a, NOR_FLASH_INSTANCE, FvbProtocol, NOR_FLASH_SIGNATURE)
|
||||
-#define INSTANCE_FROM_BLKIO_THIS(a) CR(a, NOR_FLASH_INSTANCE, BlockIoProtocol, NOR_FLASH_SIGNATURE)
|
||||
+#define INSTANCE_FROM_FVB_THIS(a) CR(a, NOR_FLASH_INSTANCE, FvbProtocol, NOR_FLASH_SIGNATURE)
|
||||
|
||||
typedef struct _NOR_FLASH_INSTANCE NOR_FLASH_INSTANCE;
|
||||
|
||||
@@ -129,9 +127,8 @@ struct _NOR_FLASH_INSTANCE {
|
||||
UINTN RegionBaseAddress;
|
||||
UINTN Size;
|
||||
EFI_LBA StartLba;
|
||||
-
|
||||
- EFI_BLOCK_IO_PROTOCOL BlockIoProtocol;
|
||||
- EFI_BLOCK_IO_MEDIA Media;
|
||||
+ EFI_LBA LastBlock;
|
||||
+ UINT32 BlockSize;
|
||||
|
||||
EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol;
|
||||
VOID *ShadowBuffer;
|
||||
@@ -155,51 +152,6 @@ NorFlashWriteBuffer (
|
||||
IN UINT32 *Buffer
|
||||
);
|
||||
|
||||
-//
|
||||
-// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.Reset
|
||||
-//
|
||||
-EFI_STATUS
|
||||
-EFIAPI
|
||||
-NorFlashBlockIoReset (
|
||||
- IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
- IN BOOLEAN ExtendedVerification
|
||||
- );
|
||||
-
|
||||
-//
|
||||
-// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.ReadBlocks
|
||||
-//
|
||||
-EFI_STATUS
|
||||
-EFIAPI
|
||||
-NorFlashBlockIoReadBlocks (
|
||||
- IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
- IN UINT32 MediaId,
|
||||
- IN EFI_LBA Lba,
|
||||
- IN UINTN BufferSizeInBytes,
|
||||
- OUT VOID *Buffer
|
||||
- );
|
||||
-
|
||||
-//
|
||||
-// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.WriteBlocks
|
||||
-//
|
||||
-EFI_STATUS
|
||||
-EFIAPI
|
||||
-NorFlashBlockIoWriteBlocks (
|
||||
- IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
- IN UINT32 MediaId,
|
||||
- IN EFI_LBA Lba,
|
||||
- IN UINTN BufferSizeInBytes,
|
||||
- IN VOID *Buffer
|
||||
- );
|
||||
-
|
||||
-//
|
||||
-// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks
|
||||
-//
|
||||
-EFI_STATUS
|
||||
-EFIAPI
|
||||
-NorFlashBlockIoFlushBlocks (
|
||||
- IN EFI_BLOCK_IO_PROTOCOL *This
|
||||
- );
|
||||
-
|
||||
//
|
||||
// NorFlashFvbDxe.c
|
||||
//
|
||||
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c
|
||||
index 4875b057d5..2ceda22635 100644
|
||||
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c
|
||||
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c
|
||||
@@ -34,29 +34,8 @@ NOR_FLASH_INSTANCE mNorFlashInstanceTemplate = {
|
||||
0, // RegionBaseAddress ... NEED TO BE FILLED
|
||||
0, // Size ... NEED TO BE FILLED
|
||||
0, // StartLba
|
||||
-
|
||||
- {
|
||||
- EFI_BLOCK_IO_PROTOCOL_REVISION2, // Revision
|
||||
- NULL, // Media ... NEED TO BE FILLED
|
||||
- NorFlashBlockIoReset, // Reset;
|
||||
- NorFlashBlockIoReadBlocks, // ReadBlocks
|
||||
- NorFlashBlockIoWriteBlocks, // WriteBlocks
|
||||
- NorFlashBlockIoFlushBlocks // FlushBlocks
|
||||
- }, // BlockIoProtocol
|
||||
-
|
||||
- {
|
||||
- 0, // MediaId ... NEED TO BE FILLED
|
||||
- FALSE, // RemovableMedia
|
||||
- TRUE, // MediaPresent
|
||||
- FALSE, // LogicalPartition
|
||||
- FALSE, // ReadOnly
|
||||
- FALSE, // WriteCaching;
|
||||
- 0, // BlockSize ... NEED TO BE FILLED
|
||||
- 4, // IoAlign
|
||||
- 0, // LastBlock ... NEED TO BE FILLED
|
||||
- 0, // LowestAlignedLba
|
||||
- 1, // LogicalBlocksPerPhysicalBlock
|
||||
- }, // Media;
|
||||
+ 0, // LastBlock
|
||||
+ 0, // BlockSize
|
||||
|
||||
{
|
||||
FvbGetAttributes, // GetAttributes
|
||||
@@ -115,11 +94,8 @@ NorFlashCreateInstance (
|
||||
Instance->DeviceBaseAddress = NorFlashDeviceBase;
|
||||
Instance->RegionBaseAddress = NorFlashRegionBase;
|
||||
Instance->Size = NorFlashSize;
|
||||
-
|
||||
- Instance->BlockIoProtocol.Media = &Instance->Media;
|
||||
- Instance->Media.MediaId = Index;
|
||||
- Instance->Media.BlockSize = BlockSize;
|
||||
- Instance->Media.LastBlock = (NorFlashSize / BlockSize)-1;
|
||||
+ Instance->BlockSize = BlockSize;
|
||||
+ Instance->LastBlock = (NorFlashSize / BlockSize) - 1;
|
||||
|
||||
CopyGuid (&Instance->DevicePath.Vendor.Guid, &gEfiCallerIdGuid);
|
||||
Instance->DevicePath.Index = (UINT8)Index;
|
||||
@@ -136,8 +112,6 @@ NorFlashCreateInstance (
|
||||
&Instance->Handle,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
&Instance->DevicePath,
|
||||
- &gEfiBlockIoProtocolGuid,
|
||||
- &Instance->BlockIoProtocol,
|
||||
&gEfiFirmwareVolumeBlockProtocolGuid,
|
||||
&Instance->FvbProtocol,
|
||||
NULL
|
||||
@@ -151,8 +125,6 @@ NorFlashCreateInstance (
|
||||
&Instance->Handle,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
&Instance->DevicePath,
|
||||
- &gEfiBlockIoProtocolGuid,
|
||||
- &Instance->BlockIoProtocol,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
@@ -434,7 +406,7 @@ NorFlashFvbInitialize (
|
||||
PcdGet64 (PcdFlashNvStorageVariableBase64) : PcdGet32 (PcdFlashNvStorageVariableBase);
|
||||
|
||||
// Set the index of the first LBA for the FVB
|
||||
- Instance->StartLba = (mFlashNvStorageVariableBase - Instance->RegionBaseAddress) / Instance->Media.BlockSize;
|
||||
+ Instance->StartLba = (mFlashNvStorageVariableBase - Instance->RegionBaseAddress) / Instance->BlockSize;
|
||||
|
||||
BootMode = GetBootModeHob ();
|
||||
if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) {
|
||||
@@ -455,7 +427,7 @@ NorFlashFvbInitialize (
|
||||
));
|
||||
|
||||
// Erase all the NorFlash that is reserved for variable storage
|
||||
- FvbNumLba = (PcdGet32 (PcdFlashNvStorageVariableSize) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) + PcdGet32 (PcdFlashNvStorageFtwSpareSize)) / Instance->Media.BlockSize;
|
||||
+ FvbNumLba = (PcdGet32 (PcdFlashNvStorageVariableSize) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) + PcdGet32 (PcdFlashNvStorageFtwSpareSize)) / Instance->BlockSize;
|
||||
|
||||
Status = FvbEraseBlocks (&Instance->FvbProtocol, (EFI_LBA)0, FvbNumLba, EFI_LBA_LIST_TERMINATOR);
|
||||
if (EFI_ERROR (Status)) {
|
||||
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf
|
||||
index 53e9d58204..2a3d4a218e 100644
|
||||
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf
|
||||
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf
|
||||
@@ -19,7 +19,6 @@
|
||||
[Sources.common]
|
||||
VirtNorFlash.c
|
||||
VirtNorFlash.h
|
||||
- VirtNorFlashBlockIoDxe.c
|
||||
VirtNorFlashDxe.c
|
||||
VirtNorFlashFvb.c
|
||||
|
||||
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c
|
||||
index c824e0a0fb..cc5eefaaf3 100644
|
||||
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c
|
||||
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c
|
||||
@@ -89,7 +89,7 @@ InitializeFvAndVariableStoreHeaders (
|
||||
}
|
||||
|
||||
// Check if the size of the area is at least one block size
|
||||
- if ((NvStorageVariableSize <= 0) || (NvStorageVariableSize / Instance->Media.BlockSize <= 0)) {
|
||||
+ if ((NvStorageVariableSize <= 0) || (NvStorageVariableSize / Instance->BlockSize <= 0)) {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"%a: NvStorageVariableSize is 0x%x, should be atleast one block size\n",
|
||||
@@ -99,7 +99,7 @@ InitializeFvAndVariableStoreHeaders (
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
- if ((NvStorageFtwWorkingSize <= 0) || (NvStorageFtwWorkingSize / Instance->Media.BlockSize <= 0)) {
|
||||
+ if ((NvStorageFtwWorkingSize <= 0) || (NvStorageFtwWorkingSize / Instance->BlockSize <= 0)) {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"%a: NvStorageFtwWorkingSize is 0x%x, should be atleast one block size\n",
|
||||
@@ -109,7 +109,7 @@ InitializeFvAndVariableStoreHeaders (
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
- if ((NvStorageFtwSpareSize <= 0) || (NvStorageFtwSpareSize / Instance->Media.BlockSize <= 0)) {
|
||||
+ if ((NvStorageFtwSpareSize <= 0) || (NvStorageFtwSpareSize / Instance->BlockSize <= 0)) {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"%a: NvStorageFtwSpareSize is 0x%x, should be atleast one block size\n",
|
||||
@@ -120,9 +120,9 @@ InitializeFvAndVariableStoreHeaders (
|
||||
}
|
||||
|
||||
// Ensure the Variable area Base Addresses are aligned on a block size boundaries
|
||||
- if ((NvStorageVariableBase % Instance->Media.BlockSize != 0) ||
|
||||
- (NvStorageFtwWorkingBase % Instance->Media.BlockSize != 0) ||
|
||||
- (NvStorageFtwSpareBase % Instance->Media.BlockSize != 0))
|
||||
+ if ((NvStorageVariableBase % Instance->BlockSize != 0) ||
|
||||
+ (NvStorageFtwWorkingBase % Instance->BlockSize != 0) ||
|
||||
+ (NvStorageFtwSpareBase % Instance->BlockSize != 0))
|
||||
{
|
||||
DEBUG ((DEBUG_ERROR, "%a: NvStorage Base addresses must be aligned to block size boundaries", __FUNCTION__));
|
||||
return EFI_INVALID_PARAMETER;
|
||||
@@ -149,8 +149,8 @@ InitializeFvAndVariableStoreHeaders (
|
||||
);
|
||||
FirmwareVolumeHeader->HeaderLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY);
|
||||
FirmwareVolumeHeader->Revision = EFI_FVH_REVISION;
|
||||
- FirmwareVolumeHeader->BlockMap[0].NumBlocks = Instance->Media.LastBlock + 1;
|
||||
- FirmwareVolumeHeader->BlockMap[0].Length = Instance->Media.BlockSize;
|
||||
+ FirmwareVolumeHeader->BlockMap[0].NumBlocks = Instance->LastBlock + 1;
|
||||
+ FirmwareVolumeHeader->BlockMap[0].Length = Instance->BlockSize;
|
||||
FirmwareVolumeHeader->BlockMap[1].NumBlocks = 0;
|
||||
FirmwareVolumeHeader->BlockMap[1].Length = 0;
|
||||
FirmwareVolumeHeader->Checksum = CalculateCheckSum16 ((UINT16 *)FirmwareVolumeHeader, FirmwareVolumeHeader->HeaderLength);
|
||||
@@ -284,9 +284,6 @@ FvbGetAttributes (
|
||||
)
|
||||
{
|
||||
EFI_FVB_ATTRIBUTES_2 FlashFvbAttributes;
|
||||
- NOR_FLASH_INSTANCE *Instance;
|
||||
-
|
||||
- Instance = INSTANCE_FROM_FVB_THIS (This);
|
||||
|
||||
FlashFvbAttributes = (EFI_FVB_ATTRIBUTES_2)(
|
||||
|
||||
@@ -294,17 +291,12 @@ FvbGetAttributes (
|
||||
EFI_FVB2_READ_STATUS | // Reads are currently enabled
|
||||
EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY
|
||||
EFI_FVB2_MEMORY_MAPPED | // It is memory mapped
|
||||
- EFI_FVB2_ERASE_POLARITY // After erasure all bits take this value (i.e. '1')
|
||||
+ EFI_FVB2_ERASE_POLARITY | // After erasure all bits take this value (i.e. '1')
|
||||
+ EFI_FVB2_WRITE_STATUS | // Writes are currently enabled
|
||||
+ EFI_FVB2_WRITE_ENABLED_CAP // Writes may be enabled
|
||||
|
||||
);
|
||||
|
||||
- // Check if it is write protected
|
||||
- if (Instance->Media.ReadOnly != TRUE) {
|
||||
- FlashFvbAttributes = FlashFvbAttributes |
|
||||
- EFI_FVB2_WRITE_STATUS | // Writes are currently enabled
|
||||
- EFI_FVB2_WRITE_ENABLED_CAP; // Writes may be enabled
|
||||
- }
|
||||
-
|
||||
*Attributes = FlashFvbAttributes;
|
||||
|
||||
DEBUG ((DEBUG_BLKIO, "FvbGetAttributes(0x%X)\n", *Attributes));
|
||||
@@ -418,15 +410,15 @@ FvbGetBlockSize (
|
||||
|
||||
Instance = INSTANCE_FROM_FVB_THIS (This);
|
||||
|
||||
- DEBUG ((DEBUG_BLKIO, "FvbGetBlockSize(Lba=%ld, BlockSize=0x%x, LastBlock=%ld)\n", Lba, Instance->Media.BlockSize, Instance->Media.LastBlock));
|
||||
+ DEBUG ((DEBUG_BLKIO, "FvbGetBlockSize(Lba=%ld, BlockSize=0x%x, LastBlock=%ld)\n", Lba, Instance->BlockSize, Instance->LastBlock));
|
||||
|
||||
- if (Lba > Instance->Media.LastBlock) {
|
||||
- DEBUG ((DEBUG_ERROR, "FvbGetBlockSize: ERROR - Parameter LBA %ld is beyond the last Lba (%ld).\n", Lba, Instance->Media.LastBlock));
|
||||
+ if (Lba > Instance->LastBlock) {
|
||||
+ DEBUG ((DEBUG_ERROR, "FvbGetBlockSize: ERROR - Parameter LBA %ld is beyond the last Lba (%ld).\n", Lba, Instance->LastBlock));
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
} else {
|
||||
// This is easy because in this platform each NorFlash device has equal sized blocks.
|
||||
- *BlockSize = (UINTN)Instance->Media.BlockSize;
|
||||
- *NumberOfBlocks = (UINTN)(Instance->Media.LastBlock - Lba + 1);
|
||||
+ *BlockSize = (UINTN)Instance->BlockSize;
|
||||
+ *NumberOfBlocks = (UINTN)(Instance->LastBlock - Lba + 1);
|
||||
|
||||
DEBUG ((DEBUG_BLKIO, "FvbGetBlockSize: *BlockSize=0x%x, *NumberOfBlocks=0x%x.\n", *BlockSize, *NumberOfBlocks));
|
||||
|
||||
@@ -498,7 +490,7 @@ FvbRead (
|
||||
TempStatus = EFI_SUCCESS;
|
||||
|
||||
// Cache the block size to avoid de-referencing pointers all the time
|
||||
- BlockSize = Instance->Media.BlockSize;
|
||||
+ BlockSize = Instance->BlockSize;
|
||||
|
||||
DEBUG ((DEBUG_BLKIO, "FvbRead: Check if (Offset=0x%x + NumBytes=0x%x) <= BlockSize=0x%x\n", Offset, *NumBytes, BlockSize));
|
||||
|
||||
@@ -669,13 +661,6 @@ FvbEraseBlocks (
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
- // Detect WriteDisabled state
|
||||
- if (Instance->Media.ReadOnly == TRUE) {
|
||||
- // Firmware volume is in WriteDisabled state
|
||||
- DEBUG ((DEBUG_ERROR, "FvbEraseBlocks: ERROR - Device is in WriteDisabled state.\n"));
|
||||
- return EFI_ACCESS_DENIED;
|
||||
- }
|
||||
-
|
||||
// Before erasing, check the entire list of parameters to ensure all specified blocks are valid
|
||||
|
||||
VA_START (Args, This);
|
||||
@@ -698,9 +683,9 @@ FvbEraseBlocks (
|
||||
"FvbEraseBlocks: Check if: ( StartingLba=%ld + NumOfLba=%Lu - 1 ) > LastBlock=%ld.\n",
|
||||
Instance->StartLba + StartingLba,
|
||||
(UINT64)NumOfLba,
|
||||
- Instance->Media.LastBlock
|
||||
+ Instance->LastBlock
|
||||
));
|
||||
- if ((NumOfLba == 0) || ((Instance->StartLba + StartingLba + NumOfLba - 1) > Instance->Media.LastBlock)) {
|
||||
+ if ((NumOfLba == 0) || ((Instance->StartLba + StartingLba + NumOfLba - 1) > Instance->LastBlock)) {
|
||||
VA_END (Args);
|
||||
DEBUG ((DEBUG_ERROR, "FvbEraseBlocks: ERROR - Lba range goes past the last Lba.\n"));
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
@@ -733,7 +718,7 @@ FvbEraseBlocks (
|
||||
BlockAddress = GET_NOR_BLOCK_ADDRESS (
|
||||
Instance->RegionBaseAddress,
|
||||
Instance->StartLba + StartingLba,
|
||||
- Instance->Media.BlockSize
|
||||
+ Instance->BlockSize
|
||||
);
|
||||
|
||||
// Erase it
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,67 @@
|
||||
From 15415de9a228e74ff1847777a29f1531754b03b0 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Wed, 11 Jan 2023 19:00:23 +0100
|
||||
Subject: [PATCH 08/18] OvmfPkg/VirtNorFlashDxe: map flash memory as
|
||||
uncacheable
|
||||
|
||||
RH-Author: Gerd Hoffmann <None>
|
||||
RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport
|
||||
RH-Jira: RHEL-17587
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [10/20] 40ca967bead9ec5c98c528bfe0757f75f3d3352f
|
||||
|
||||
Switching from the ArmPlatformPkg/NorFlashDxe driver to the
|
||||
OvmfPkg/VirtNorFlashDxe driver had the side effect that flash address
|
||||
space got registered as EFI_MEMORY_WC instead of EFI_MEMORY_UC.
|
||||
|
||||
That confuses the linux kernel's numa code, seems this makes kernel
|
||||
consider the flash being node memory. "lsmem" changes from ...
|
||||
|
||||
RANGE SIZE STATE REMOVABLE BLOCK
|
||||
0x0000000040000000-0x000000013fffffff 4G online yes 8-39
|
||||
|
||||
... to ...
|
||||
|
||||
RANGE SIZE STATE REMOVABLE BLOCK
|
||||
0x0000000000000000-0x0000000007ffffff 128M online yes 0
|
||||
0x0000000040000000-0x000000013fffffff 4G online yes 8-39
|
||||
|
||||
... and in the kernel log got new error lines:
|
||||
|
||||
NUMA: Warning: invalid memblk node 512 [mem 0x0000000004000000-0x0000000007ffffff]
|
||||
NUMA: Faking a node at [mem 0x0000000004000000-0x000000013fffffff]
|
||||
|
||||
Changing the attributes back to EFI_MEMORY_UC fixes this.
|
||||
|
||||
Fixes: b92298af8218 ("ArmVirtPkg/ArmVirtQemu: migrate to OVMF's VirtNorFlashDxe")
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
|
||||
(cherry picked from commit e5ec3ba409b5baa9cf429cc25fdf3c8d1b8dcef0)
|
||||
---
|
||||
OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c
|
||||
index ff3121af2a..f9a41f6aab 100644
|
||||
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c
|
||||
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c
|
||||
@@ -394,14 +394,14 @@ NorFlashFvbInitialize (
|
||||
EfiGcdMemoryTypeMemoryMappedIo,
|
||||
Instance->DeviceBaseAddress,
|
||||
RuntimeMmioRegionSize,
|
||||
- EFI_MEMORY_WC | EFI_MEMORY_RUNTIME
|
||||
+ EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
Status = gDS->SetMemorySpaceAttributes (
|
||||
Instance->DeviceBaseAddress,
|
||||
RuntimeMmioRegionSize,
|
||||
- EFI_MEMORY_WC | EFI_MEMORY_RUNTIME
|
||||
+ EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,131 @@
|
||||
From 791c26a4a172b4a609a708db8018411ab653de4a Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Tue, 16 Jan 2024 18:11:05 +0100
|
||||
Subject: [PATCH 16/18] OvmfPkg/VirtNorFlashDxe: move DoErase code block into
|
||||
new function
|
||||
|
||||
RH-Author: Gerd Hoffmann <None>
|
||||
RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport
|
||||
RH-Jira: RHEL-17587
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [18/20] 10f4685bfcb0c5423e392b4cf0e8633cd25b46b4
|
||||
|
||||
Move the DoErase code block into a separate function, call the function
|
||||
instead of jumping around with goto.
|
||||
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Message-Id: <20240116171105.37831-7-kraxel@redhat.com>
|
||||
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
|
||||
(cherry picked from commit b481b00f593ef37695ee14271453320ed02a1256)
|
||||
---
|
||||
OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 76 ++++++++++++++++++--------
|
||||
1 file changed, 52 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
index 3d1d20daa1..e6aaed27ce 100644
|
||||
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
@@ -502,6 +502,38 @@ NorFlashRead (
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
+STATIC
|
||||
+EFI_STATUS
|
||||
+NorFlashWriteSingleBlockWithErase (
|
||||
+ IN NOR_FLASH_INSTANCE *Instance,
|
||||
+ IN EFI_LBA Lba,
|
||||
+ IN UINTN Offset,
|
||||
+ IN OUT UINTN *NumBytes,
|
||||
+ IN UINT8 *Buffer
|
||||
+ )
|
||||
+{
|
||||
+ EFI_STATUS Status;
|
||||
+
|
||||
+ // Read NOR Flash data into shadow buffer
|
||||
+ Status = NorFlashReadBlocks (Instance, Lba, Instance->BlockSize, Instance->ShadowBuffer);
|
||||
+ if (EFI_ERROR (Status)) {
|
||||
+ // Return one of the pre-approved error statuses
|
||||
+ return EFI_DEVICE_ERROR;
|
||||
+ }
|
||||
+
|
||||
+ // Put the data at the appropriate location inside the buffer area
|
||||
+ CopyMem ((VOID *)((UINTN)Instance->ShadowBuffer + Offset), Buffer, *NumBytes);
|
||||
+
|
||||
+ // Write the modified buffer back to the NorFlash
|
||||
+ Status = NorFlashWriteBlocks (Instance, Lba, Instance->BlockSize, Instance->ShadowBuffer);
|
||||
+ if (EFI_ERROR (Status)) {
|
||||
+ // Return one of the pre-approved error statuses
|
||||
+ return EFI_DEVICE_ERROR;
|
||||
+ }
|
||||
+
|
||||
+ return EFI_SUCCESS;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
Write a full or portion of a block. It must not span block boundaries; that is,
|
||||
Offset + *NumBytes <= Instance->BlockSize.
|
||||
@@ -607,7 +639,14 @@ NorFlashWriteSingleBlock (
|
||||
// that we want to set. In that case, we will need to erase the block first.
|
||||
for (CurOffset = 0; CurOffset < *NumBytes; CurOffset++) {
|
||||
if (~(UINT32)OrigData[CurOffset] & (UINT32)Buffer[CurOffset]) {
|
||||
- goto DoErase;
|
||||
+ Status = NorFlashWriteSingleBlockWithErase (
|
||||
+ Instance,
|
||||
+ Lba,
|
||||
+ Offset,
|
||||
+ NumBytes,
|
||||
+ Buffer
|
||||
+ );
|
||||
+ return Status;
|
||||
}
|
||||
|
||||
OrigData[CurOffset] = Buffer[CurOffset];
|
||||
@@ -636,33 +675,22 @@ NorFlashWriteSingleBlock (
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
-
|
||||
-Exit:
|
||||
- // Put device back into Read Array mode
|
||||
- SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
|
||||
-
|
||||
+ } else {
|
||||
+ Status = NorFlashWriteSingleBlockWithErase (
|
||||
+ Instance,
|
||||
+ Lba,
|
||||
+ Offset,
|
||||
+ NumBytes,
|
||||
+ Buffer
|
||||
+ );
|
||||
return Status;
|
||||
}
|
||||
|
||||
-DoErase:
|
||||
- // Read NOR Flash data into shadow buffer
|
||||
- Status = NorFlashReadBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer);
|
||||
- if (EFI_ERROR (Status)) {
|
||||
- // Return one of the pre-approved error statuses
|
||||
- return EFI_DEVICE_ERROR;
|
||||
- }
|
||||
-
|
||||
- // Put the data at the appropriate location inside the buffer area
|
||||
- CopyMem ((VOID *)((UINTN)Instance->ShadowBuffer + Offset), Buffer, *NumBytes);
|
||||
-
|
||||
- // Write the modified buffer back to the NorFlash
|
||||
- Status = NorFlashWriteBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer);
|
||||
- if (EFI_ERROR (Status)) {
|
||||
- // Return one of the pre-approved error statuses
|
||||
- return EFI_DEVICE_ERROR;
|
||||
- }
|
||||
+Exit:
|
||||
+ // Put device back into Read Array mode
|
||||
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
|
||||
|
||||
- return EFI_SUCCESS;
|
||||
+ return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,94 @@
|
||||
From 03e0a729a5c3ebcab8806d136cd8908627bd91c9 Mon Sep 17 00:00:00 2001
|
||||
From: Ard Biesheuvel <ardb@kernel.org>
|
||||
Date: Mon, 24 Oct 2022 16:45:02 +0200
|
||||
Subject: [PATCH 02/18] OvmfPkg/VirtNorFlashDxe: remove CheckBlockLocked
|
||||
feature
|
||||
|
||||
RH-Author: Gerd Hoffmann <None>
|
||||
RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport
|
||||
RH-Jira: RHEL-17587
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [4/20] 990bdf373801df8107d8a6ec4db3fb93e5a6ad68
|
||||
|
||||
We inherited a feature from the ArmPlatformPkg version of this driver
|
||||
that never gets enabled. Let's remove it.
|
||||
|
||||
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
|
||||
Reviewed-by: Sunil V L <sunilvl@ventanamicro.com>
|
||||
(cherry picked from commit 0a64106c566273ff8ef951d56ddfa972fe65bd6c)
|
||||
---
|
||||
OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 35 +++++----------------
|
||||
OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf | 3 --
|
||||
2 files changed, 8 insertions(+), 30 deletions(-)
|
||||
|
||||
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
index 12fa720dad..59a562efdf 100644
|
||||
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
@@ -65,35 +65,16 @@ NorFlashUnlockSingleBlock (
|
||||
// Raise the Task Priority Level to TPL_NOTIFY to serialise all its operations
|
||||
// and to protect shared data structures.
|
||||
|
||||
- if (FeaturePcdGet (PcdNorFlashCheckBlockLocked) == TRUE) {
|
||||
- do {
|
||||
- // Request a lock setup
|
||||
- SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_LOCK_BLOCK_SETUP);
|
||||
+ // Request a lock setup
|
||||
+ SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_LOCK_BLOCK_SETUP);
|
||||
|
||||
- // Request an unlock
|
||||
- SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_UNLOCK_BLOCK);
|
||||
+ // Request an unlock
|
||||
+ SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_UNLOCK_BLOCK);
|
||||
|
||||
- // Send command for reading device id
|
||||
- SEND_NOR_COMMAND (BlockAddress, 2, P30_CMD_READ_DEVICE_ID);
|
||||
-
|
||||
- // Read block lock status
|
||||
- LockStatus = MmioRead32 (CREATE_NOR_ADDRESS (BlockAddress, 2));
|
||||
-
|
||||
- // Decode block lock status
|
||||
- LockStatus = FOLD_32BIT_INTO_16BIT (LockStatus);
|
||||
- } while ((LockStatus & 0x1) == 1);
|
||||
- } else {
|
||||
- // Request a lock setup
|
||||
- SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_LOCK_BLOCK_SETUP);
|
||||
-
|
||||
- // Request an unlock
|
||||
- SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_UNLOCK_BLOCK);
|
||||
-
|
||||
- // Wait until the status register gives us the all clear
|
||||
- do {
|
||||
- LockStatus = NorFlashReadStatusRegister (Instance, BlockAddress);
|
||||
- } while ((LockStatus & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
|
||||
- }
|
||||
+ // Wait until the status register gives us the all clear
|
||||
+ do {
|
||||
+ LockStatus = NorFlashReadStatusRegister (Instance, BlockAddress);
|
||||
+ } while ((LockStatus & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
|
||||
|
||||
// Put device back into Read Array mode
|
||||
SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_READ_ARRAY);
|
||||
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf
|
||||
index 1bf50e4823..53e9d58204 100644
|
||||
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf
|
||||
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf
|
||||
@@ -24,7 +24,6 @@
|
||||
VirtNorFlashFvb.c
|
||||
|
||||
[Packages]
|
||||
- ArmPlatformPkg/ArmPlatformPkg.dec
|
||||
EmbeddedPkg/EmbeddedPkg.dec
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
@@ -66,7 +65,5 @@
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
|
||||
|
||||
- gArmPlatformTokenSpaceGuid.PcdNorFlashCheckBlockLocked
|
||||
-
|
||||
[Depex]
|
||||
gEfiCpuArchProtocolGuid
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,386 @@
|
||||
From 56041232238e4e4d3c8d703b27f51b0bc70fd5c8 Mon Sep 17 00:00:00 2001
|
||||
From: Ard Biesheuvel <ardb@kernel.org>
|
||||
Date: Mon, 24 Oct 2022 16:50:05 +0200
|
||||
Subject: [PATCH 03/18] OvmfPkg/VirtNorFlashDxe: remove disk I/O protocol
|
||||
implementation
|
||||
|
||||
RH-Author: Gerd Hoffmann <None>
|
||||
RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport
|
||||
RH-Jira: RHEL-17587
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [5/20] 0551c3f56f43396cfdc380127565e89d69eb29a3
|
||||
|
||||
We only use NOR flash for firmware volumes, either for executable images
|
||||
or for the variable store. So we have no need for exposing disk I/O on
|
||||
top of the NOR flash partitions so let's remove it.
|
||||
|
||||
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
|
||||
Reviewed-by: Sunil V L <sunilvl@ventanamicro.com>
|
||||
(cherry picked from commit 68d234989b2d6bd8f255577e08bf8be0b1d197bb)
|
||||
---
|
||||
OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 129 ------------------
|
||||
OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h | 29 ----
|
||||
.../VirtNorFlashDxe/VirtNorFlashBlockIoDxe.c | 123 -----------------
|
||||
OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c | 8 --
|
||||
4 files changed, 289 deletions(-)
|
||||
delete mode 100644 OvmfPkg/VirtNorFlashDxe/VirtNorFlashBlockIoDxe.c
|
||||
|
||||
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
index 59a562efdf..1094d48f7d 100644
|
||||
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
@@ -788,135 +788,6 @@ NorFlashWriteSingleBlock (
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
-/*
|
||||
- Although DiskIoDxe will automatically install the DiskIO protocol whenever
|
||||
- we install the BlockIO protocol, its implementation is sub-optimal as it reads
|
||||
- and writes entire blocks using the BlockIO protocol. In fact we can access
|
||||
- NOR flash with a finer granularity than that, so we can improve performance
|
||||
- by directly producing the DiskIO protocol.
|
||||
-*/
|
||||
-
|
||||
-/**
|
||||
- Read BufferSize bytes from Offset into Buffer.
|
||||
-
|
||||
- @param This Protocol instance pointer.
|
||||
- @param MediaId Id of the media, changes every time the media is replaced.
|
||||
- @param Offset The starting byte offset to read from
|
||||
- @param BufferSize Size of Buffer
|
||||
- @param Buffer Buffer containing read data
|
||||
-
|
||||
- @retval EFI_SUCCESS The data was read correctly from the device.
|
||||
- @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
|
||||
- @retval EFI_NO_MEDIA There is no media in the device.
|
||||
- @retval EFI_MEDIA_CHANGED The MediaId does not match the current device.
|
||||
- @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not
|
||||
- valid for the device.
|
||||
-
|
||||
-**/
|
||||
-EFI_STATUS
|
||||
-EFIAPI
|
||||
-NorFlashDiskIoReadDisk (
|
||||
- IN EFI_DISK_IO_PROTOCOL *This,
|
||||
- IN UINT32 MediaId,
|
||||
- IN UINT64 DiskOffset,
|
||||
- IN UINTN BufferSize,
|
||||
- OUT VOID *Buffer
|
||||
- )
|
||||
-{
|
||||
- NOR_FLASH_INSTANCE *Instance;
|
||||
- UINT32 BlockSize;
|
||||
- UINT32 BlockOffset;
|
||||
- EFI_LBA Lba;
|
||||
-
|
||||
- Instance = INSTANCE_FROM_DISKIO_THIS (This);
|
||||
-
|
||||
- if (MediaId != Instance->Media.MediaId) {
|
||||
- return EFI_MEDIA_CHANGED;
|
||||
- }
|
||||
-
|
||||
- BlockSize = Instance->Media.BlockSize;
|
||||
- Lba = (EFI_LBA)DivU64x32Remainder (DiskOffset, BlockSize, &BlockOffset);
|
||||
-
|
||||
- return NorFlashRead (Instance, Lba, BlockOffset, BufferSize, Buffer);
|
||||
-}
|
||||
-
|
||||
-/**
|
||||
- Writes a specified number of bytes to a device.
|
||||
-
|
||||
- @param This Indicates a pointer to the calling context.
|
||||
- @param MediaId ID of the medium to be written.
|
||||
- @param Offset The starting byte offset on the logical block I/O device to write.
|
||||
- @param BufferSize The size in bytes of Buffer. The number of bytes to write to the device.
|
||||
- @param Buffer A pointer to the buffer containing the data to be written.
|
||||
-
|
||||
- @retval EFI_SUCCESS The data was written correctly to the device.
|
||||
- @retval EFI_WRITE_PROTECTED The device can not be written to.
|
||||
- @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
|
||||
- @retval EFI_NO_MEDIA There is no media in the device.
|
||||
- @retval EFI_MEDIA_CHANGED The MediaId does not match the current device.
|
||||
- @retval EFI_INVALID_PARAMETER The write request contains device addresses that are not
|
||||
- valid for the device.
|
||||
-
|
||||
-**/
|
||||
-EFI_STATUS
|
||||
-EFIAPI
|
||||
-NorFlashDiskIoWriteDisk (
|
||||
- IN EFI_DISK_IO_PROTOCOL *This,
|
||||
- IN UINT32 MediaId,
|
||||
- IN UINT64 DiskOffset,
|
||||
- IN UINTN BufferSize,
|
||||
- IN VOID *Buffer
|
||||
- )
|
||||
-{
|
||||
- NOR_FLASH_INSTANCE *Instance;
|
||||
- UINT32 BlockSize;
|
||||
- UINT32 BlockOffset;
|
||||
- EFI_LBA Lba;
|
||||
- UINTN RemainingBytes;
|
||||
- UINTN WriteSize;
|
||||
- EFI_STATUS Status;
|
||||
-
|
||||
- Instance = INSTANCE_FROM_DISKIO_THIS (This);
|
||||
-
|
||||
- if (MediaId != Instance->Media.MediaId) {
|
||||
- return EFI_MEDIA_CHANGED;
|
||||
- }
|
||||
-
|
||||
- BlockSize = Instance->Media.BlockSize;
|
||||
- Lba = (EFI_LBA)DivU64x32Remainder (DiskOffset, BlockSize, &BlockOffset);
|
||||
-
|
||||
- RemainingBytes = BufferSize;
|
||||
-
|
||||
- // Write either all the remaining bytes, or the number of bytes that bring
|
||||
- // us up to a block boundary, whichever is less.
|
||||
- // (DiskOffset | (BlockSize - 1)) + 1) rounds DiskOffset up to the next
|
||||
- // block boundary (even if it is already on one).
|
||||
- WriteSize = MIN (RemainingBytes, ((DiskOffset | (BlockSize - 1)) + 1) - DiskOffset);
|
||||
-
|
||||
- do {
|
||||
- if (WriteSize == BlockSize) {
|
||||
- // Write a full block
|
||||
- Status = NorFlashWriteFullBlock (Instance, Lba, Buffer, BlockSize / sizeof (UINT32));
|
||||
- } else {
|
||||
- // Write a partial block
|
||||
- Status = NorFlashWriteSingleBlock (Instance, Lba, BlockOffset, &WriteSize, Buffer);
|
||||
- }
|
||||
-
|
||||
- if (EFI_ERROR (Status)) {
|
||||
- return Status;
|
||||
- }
|
||||
-
|
||||
- // Now continue writing either all the remaining bytes or single blocks.
|
||||
- RemainingBytes -= WriteSize;
|
||||
- Buffer = (UINT8 *)Buffer + WriteSize;
|
||||
- Lba++;
|
||||
- BlockOffset = 0;
|
||||
- WriteSize = MIN (RemainingBytes, BlockSize);
|
||||
- } while (RemainingBytes);
|
||||
-
|
||||
- return Status;
|
||||
-}
|
||||
-
|
||||
EFI_STATUS
|
||||
NorFlashReset (
|
||||
IN NOR_FLASH_INSTANCE *Instance
|
||||
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h
|
||||
index e46522a198..7733ee02ee 100644
|
||||
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h
|
||||
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h
|
||||
@@ -15,7 +15,6 @@
|
||||
#include <Guid/EventGroup.h>
|
||||
|
||||
#include <Protocol/BlockIo.h>
|
||||
-#include <Protocol/DiskIo.h>
|
||||
#include <Protocol/FirmwareVolumeBlock.h>
|
||||
|
||||
#include <Library/DebugLib.h>
|
||||
@@ -111,7 +110,6 @@
|
||||
#define NOR_FLASH_SIGNATURE SIGNATURE_32('n', 'o', 'r', '0')
|
||||
#define INSTANCE_FROM_FVB_THIS(a) CR(a, NOR_FLASH_INSTANCE, FvbProtocol, NOR_FLASH_SIGNATURE)
|
||||
#define INSTANCE_FROM_BLKIO_THIS(a) CR(a, NOR_FLASH_INSTANCE, BlockIoProtocol, NOR_FLASH_SIGNATURE)
|
||||
-#define INSTANCE_FROM_DISKIO_THIS(a) CR(a, NOR_FLASH_INSTANCE, DiskIoProtocol, NOR_FLASH_SIGNATURE)
|
||||
|
||||
typedef struct _NOR_FLASH_INSTANCE NOR_FLASH_INSTANCE;
|
||||
|
||||
@@ -134,7 +132,6 @@ struct _NOR_FLASH_INSTANCE {
|
||||
|
||||
EFI_BLOCK_IO_PROTOCOL BlockIoProtocol;
|
||||
EFI_BLOCK_IO_MEDIA Media;
|
||||
- EFI_DISK_IO_PROTOCOL DiskIoProtocol;
|
||||
|
||||
EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol;
|
||||
VOID *ShadowBuffer;
|
||||
@@ -203,32 +200,6 @@ NorFlashBlockIoFlushBlocks (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This
|
||||
);
|
||||
|
||||
-//
|
||||
-// DiskIO Protocol function EFI_DISK_IO_PROTOCOL.ReadDisk
|
||||
-//
|
||||
-EFI_STATUS
|
||||
-EFIAPI
|
||||
-NorFlashDiskIoReadDisk (
|
||||
- IN EFI_DISK_IO_PROTOCOL *This,
|
||||
- IN UINT32 MediaId,
|
||||
- IN UINT64 Offset,
|
||||
- IN UINTN BufferSize,
|
||||
- OUT VOID *Buffer
|
||||
- );
|
||||
-
|
||||
-//
|
||||
-// DiskIO Protocol function EFI_DISK_IO_PROTOCOL.WriteDisk
|
||||
-//
|
||||
-EFI_STATUS
|
||||
-EFIAPI
|
||||
-NorFlashDiskIoWriteDisk (
|
||||
- IN EFI_DISK_IO_PROTOCOL *This,
|
||||
- IN UINT32 MediaId,
|
||||
- IN UINT64 Offset,
|
||||
- IN UINTN BufferSize,
|
||||
- IN VOID *Buffer
|
||||
- );
|
||||
-
|
||||
//
|
||||
// NorFlashFvbDxe.c
|
||||
//
|
||||
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashBlockIoDxe.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashBlockIoDxe.c
|
||||
deleted file mode 100644
|
||||
index ecf152e355..0000000000
|
||||
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashBlockIoDxe.c
|
||||
+++ /dev/null
|
||||
@@ -1,123 +0,0 @@
|
||||
-/** @file NorFlashBlockIoDxe.c
|
||||
-
|
||||
- Copyright (c) 2011-2013, ARM Ltd. All rights reserved.<BR>
|
||||
-
|
||||
- SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
-
|
||||
-**/
|
||||
-
|
||||
-#include <Library/BaseMemoryLib.h>
|
||||
-#include <Library/UefiBootServicesTableLib.h>
|
||||
-
|
||||
-#include "VirtNorFlash.h"
|
||||
-
|
||||
-//
|
||||
-// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.Reset
|
||||
-//
|
||||
-EFI_STATUS
|
||||
-EFIAPI
|
||||
-NorFlashBlockIoReset (
|
||||
- IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
- IN BOOLEAN ExtendedVerification
|
||||
- )
|
||||
-{
|
||||
- NOR_FLASH_INSTANCE *Instance;
|
||||
-
|
||||
- Instance = INSTANCE_FROM_BLKIO_THIS (This);
|
||||
-
|
||||
- DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoReset(MediaId=0x%x)\n", This->Media->MediaId));
|
||||
-
|
||||
- return NorFlashReset (Instance);
|
||||
-}
|
||||
-
|
||||
-//
|
||||
-// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.ReadBlocks
|
||||
-//
|
||||
-EFI_STATUS
|
||||
-EFIAPI
|
||||
-NorFlashBlockIoReadBlocks (
|
||||
- IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
- IN UINT32 MediaId,
|
||||
- IN EFI_LBA Lba,
|
||||
- IN UINTN BufferSizeInBytes,
|
||||
- OUT VOID *Buffer
|
||||
- )
|
||||
-{
|
||||
- NOR_FLASH_INSTANCE *Instance;
|
||||
- EFI_STATUS Status;
|
||||
- EFI_BLOCK_IO_MEDIA *Media;
|
||||
-
|
||||
- if (This == NULL) {
|
||||
- return EFI_INVALID_PARAMETER;
|
||||
- }
|
||||
-
|
||||
- Instance = INSTANCE_FROM_BLKIO_THIS (This);
|
||||
- Media = This->Media;
|
||||
-
|
||||
- DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoReadBlocks(MediaId=0x%x, Lba=%ld, BufferSize=0x%x bytes (%d kB), BufferPtr @ 0x%08x)\n", MediaId, Lba, BufferSizeInBytes, BufferSizeInBytes, Buffer));
|
||||
-
|
||||
- if (!Media) {
|
||||
- Status = EFI_INVALID_PARAMETER;
|
||||
- } else if (!Media->MediaPresent) {
|
||||
- Status = EFI_NO_MEDIA;
|
||||
- } else if (Media->MediaId != MediaId) {
|
||||
- Status = EFI_MEDIA_CHANGED;
|
||||
- } else if ((Media->IoAlign > 2) && (((UINTN)Buffer & (Media->IoAlign - 1)) != 0)) {
|
||||
- Status = EFI_INVALID_PARAMETER;
|
||||
- } else {
|
||||
- Status = NorFlashReadBlocks (Instance, Lba, BufferSizeInBytes, Buffer);
|
||||
- }
|
||||
-
|
||||
- return Status;
|
||||
-}
|
||||
-
|
||||
-//
|
||||
-// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.WriteBlocks
|
||||
-//
|
||||
-EFI_STATUS
|
||||
-EFIAPI
|
||||
-NorFlashBlockIoWriteBlocks (
|
||||
- IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
- IN UINT32 MediaId,
|
||||
- IN EFI_LBA Lba,
|
||||
- IN UINTN BufferSizeInBytes,
|
||||
- IN VOID *Buffer
|
||||
- )
|
||||
-{
|
||||
- NOR_FLASH_INSTANCE *Instance;
|
||||
- EFI_STATUS Status;
|
||||
-
|
||||
- Instance = INSTANCE_FROM_BLKIO_THIS (This);
|
||||
-
|
||||
- DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoWriteBlocks(MediaId=0x%x, Lba=%ld, BufferSize=0x%x bytes, BufferPtr @ 0x%08x)\n", MediaId, Lba, BufferSizeInBytes, Buffer));
|
||||
-
|
||||
- if ( !This->Media->MediaPresent ) {
|
||||
- Status = EFI_NO_MEDIA;
|
||||
- } else if ( This->Media->MediaId != MediaId ) {
|
||||
- Status = EFI_MEDIA_CHANGED;
|
||||
- } else if ( This->Media->ReadOnly ) {
|
||||
- Status = EFI_WRITE_PROTECTED;
|
||||
- } else {
|
||||
- Status = NorFlashWriteBlocks (Instance, Lba, BufferSizeInBytes, Buffer);
|
||||
- }
|
||||
-
|
||||
- return Status;
|
||||
-}
|
||||
-
|
||||
-//
|
||||
-// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks
|
||||
-//
|
||||
-EFI_STATUS
|
||||
-EFIAPI
|
||||
-NorFlashBlockIoFlushBlocks (
|
||||
- IN EFI_BLOCK_IO_PROTOCOL *This
|
||||
- )
|
||||
-{
|
||||
- // No Flush required for the NOR Flash driver
|
||||
- // because cache operations are not permitted.
|
||||
-
|
||||
- DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoFlushBlocks: Function NOT IMPLEMENTED (not required).\n"));
|
||||
-
|
||||
- // Nothing to do so just return without error
|
||||
- return EFI_SUCCESS;
|
||||
-}
|
||||
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c
|
||||
index 819425545e..4875b057d5 100644
|
||||
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c
|
||||
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c
|
||||
@@ -58,12 +58,6 @@ NOR_FLASH_INSTANCE mNorFlashInstanceTemplate = {
|
||||
1, // LogicalBlocksPerPhysicalBlock
|
||||
}, // Media;
|
||||
|
||||
- {
|
||||
- EFI_DISK_IO_PROTOCOL_REVISION, // Revision
|
||||
- NorFlashDiskIoReadDisk, // ReadDisk
|
||||
- NorFlashDiskIoWriteDisk // WriteDisk
|
||||
- },
|
||||
-
|
||||
{
|
||||
FvbGetAttributes, // GetAttributes
|
||||
FvbSetAttributes, // SetAttributes
|
||||
@@ -159,8 +153,6 @@ NorFlashCreateInstance (
|
||||
&Instance->DevicePath,
|
||||
&gEfiBlockIoProtocolGuid,
|
||||
&Instance->BlockIoProtocol,
|
||||
- &gEfiDiskIoProtocolGuid,
|
||||
- &Instance->DiskIoProtocol,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,216 @@
|
||||
From c4d2144caff4eddb7021752fce6c2dec6d5e1632 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Tue, 9 Jan 2024 12:29:02 +0100
|
||||
Subject: [PATCH 10/18] OvmfPkg/VirtNorFlashDxe: sanity-check variables
|
||||
|
||||
RH-Author: Gerd Hoffmann <None>
|
||||
RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport
|
||||
RH-Jira: RHEL-17587
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [12/20] 2ad3957478b82a4ca29249ceb9620f97c591a1fe
|
||||
|
||||
Extend the ValidateFvHeader function, additionally to the header checks
|
||||
walk over the list of variables and sanity check them.
|
||||
|
||||
In case we find inconsistencies indicating variable store corruption
|
||||
return EFI_NOT_FOUND so the variable store will be re-initialized.
|
||||
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Message-Id: <20240109112902.30002-4-kraxel@redhat.com>
|
||||
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
|
||||
[lersek@redhat.com: fix StartId initialization/assignment coding style]
|
||||
(cherry picked from commit 4a443f73fd67ca8caaf0a3e1a01f8231b330d2e0)
|
||||
---
|
||||
OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf | 1 +
|
||||
OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c | 149 +++++++++++++++++++-
|
||||
2 files changed, 145 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf
|
||||
index 2a3d4a218e..f549400280 100644
|
||||
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf
|
||||
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf
|
||||
@@ -34,6 +34,7 @@
|
||||
DxeServicesTableLib
|
||||
HobLib
|
||||
IoLib
|
||||
+ SafeIntLib
|
||||
UefiBootServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
UefiLib
|
||||
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c
|
||||
index c503272a2b..acc4a413ee 100644
|
||||
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c
|
||||
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
+#include <Library/SafeIntLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
|
||||
#include <Guid/NvVarStoreFormatted.h>
|
||||
@@ -185,11 +186,12 @@ ValidateFvHeader (
|
||||
IN NOR_FLASH_INSTANCE *Instance
|
||||
)
|
||||
{
|
||||
- UINT16 Checksum;
|
||||
- EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
|
||||
- VARIABLE_STORE_HEADER *VariableStoreHeader;
|
||||
- UINTN VariableStoreLength;
|
||||
- UINTN FvLength;
|
||||
+ UINT16 Checksum;
|
||||
+ CONST EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
|
||||
+ CONST VARIABLE_STORE_HEADER *VariableStoreHeader;
|
||||
+ UINTN VarOffset;
|
||||
+ UINTN VariableStoreLength;
|
||||
+ UINTN FvLength;
|
||||
|
||||
FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)Instance->RegionBaseAddress;
|
||||
|
||||
@@ -258,6 +260,143 @@ ValidateFvHeader (
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
+ //
|
||||
+ // check variables
|
||||
+ //
|
||||
+ DEBUG ((DEBUG_INFO, "%a: checking variables\n", __func__));
|
||||
+ VarOffset = sizeof (*VariableStoreHeader);
|
||||
+ for ( ; ;) {
|
||||
+ UINTN VarHeaderEnd;
|
||||
+ UINTN VarNameEnd;
|
||||
+ UINTN VarEnd;
|
||||
+ UINTN VarPadding;
|
||||
+ CONST AUTHENTICATED_VARIABLE_HEADER *VarHeader;
|
||||
+ CONST CHAR16 *VarName;
|
||||
+ CONST CHAR8 *VarState;
|
||||
+ RETURN_STATUS Status;
|
||||
+
|
||||
+ Status = SafeUintnAdd (VarOffset, sizeof (*VarHeader), &VarHeaderEnd);
|
||||
+ if (RETURN_ERROR (Status)) {
|
||||
+ DEBUG ((DEBUG_ERROR, "%a: integer overflow\n", __func__));
|
||||
+ return EFI_NOT_FOUND;
|
||||
+ }
|
||||
+
|
||||
+ if (VarHeaderEnd >= VariableStoreHeader->Size) {
|
||||
+ if (VarOffset <= VariableStoreHeader->Size - sizeof (UINT16)) {
|
||||
+ CONST UINT16 *StartId;
|
||||
+
|
||||
+ StartId = (VOID *)((UINTN)VariableStoreHeader + VarOffset);
|
||||
+ if (*StartId == 0x55aa) {
|
||||
+ DEBUG ((DEBUG_ERROR, "%a: startid at invalid location\n", __func__));
|
||||
+ return EFI_NOT_FOUND;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ DEBUG ((DEBUG_INFO, "%a: end of var list (no space left)\n", __func__));
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ VarHeader = (VOID *)((UINTN)VariableStoreHeader + VarOffset);
|
||||
+ if (VarHeader->StartId != 0x55aa) {
|
||||
+ DEBUG ((DEBUG_INFO, "%a: end of var list (no startid)\n", __func__));
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ VarName = NULL;
|
||||
+ switch (VarHeader->State) {
|
||||
+ // usage: State = VAR_HEADER_VALID_ONLY
|
||||
+ case VAR_HEADER_VALID_ONLY:
|
||||
+ VarState = "header-ok";
|
||||
+ VarName = L"<unknown>";
|
||||
+ break;
|
||||
+
|
||||
+ // usage: State = VAR_ADDED
|
||||
+ case VAR_ADDED:
|
||||
+ VarState = "ok";
|
||||
+ break;
|
||||
+
|
||||
+ // usage: State &= VAR_IN_DELETED_TRANSITION
|
||||
+ case VAR_ADDED &VAR_IN_DELETED_TRANSITION:
|
||||
+ VarState = "del-in-transition";
|
||||
+ break;
|
||||
+
|
||||
+ // usage: State &= VAR_DELETED
|
||||
+ case VAR_ADDED &VAR_DELETED:
|
||||
+ case VAR_ADDED &VAR_DELETED &VAR_IN_DELETED_TRANSITION:
|
||||
+ VarState = "deleted";
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ DEBUG ((
|
||||
+ DEBUG_ERROR,
|
||||
+ "%a: invalid variable state: 0x%x\n",
|
||||
+ __func__,
|
||||
+ VarHeader->State
|
||||
+ ));
|
||||
+ return EFI_NOT_FOUND;
|
||||
+ }
|
||||
+
|
||||
+ Status = SafeUintnAdd (VarHeaderEnd, VarHeader->NameSize, &VarNameEnd);
|
||||
+ if (RETURN_ERROR (Status)) {
|
||||
+ DEBUG ((DEBUG_ERROR, "%a: integer overflow\n", __func__));
|
||||
+ return EFI_NOT_FOUND;
|
||||
+ }
|
||||
+
|
||||
+ Status = SafeUintnAdd (VarNameEnd, VarHeader->DataSize, &VarEnd);
|
||||
+ if (RETURN_ERROR (Status)) {
|
||||
+ DEBUG ((DEBUG_ERROR, "%a: integer overflow\n", __func__));
|
||||
+ return EFI_NOT_FOUND;
|
||||
+ }
|
||||
+
|
||||
+ if (VarEnd > VariableStoreHeader->Size) {
|
||||
+ DEBUG ((
|
||||
+ DEBUG_ERROR,
|
||||
+ "%a: invalid variable size: 0x%Lx + 0x%Lx + 0x%x + 0x%x > 0x%x\n",
|
||||
+ __func__,
|
||||
+ (UINT64)VarOffset,
|
||||
+ (UINT64)(sizeof (*VarHeader)),
|
||||
+ VarHeader->NameSize,
|
||||
+ VarHeader->DataSize,
|
||||
+ VariableStoreHeader->Size
|
||||
+ ));
|
||||
+ return EFI_NOT_FOUND;
|
||||
+ }
|
||||
+
|
||||
+ if (((VarHeader->NameSize & 1) != 0) ||
|
||||
+ (VarHeader->NameSize < 4))
|
||||
+ {
|
||||
+ DEBUG ((DEBUG_ERROR, "%a: invalid name size\n", __func__));
|
||||
+ return EFI_NOT_FOUND;
|
||||
+ }
|
||||
+
|
||||
+ if (VarName == NULL) {
|
||||
+ VarName = (VOID *)((UINTN)VariableStoreHeader + VarHeaderEnd);
|
||||
+ if (VarName[VarHeader->NameSize / 2 - 1] != L'\0') {
|
||||
+ DEBUG ((DEBUG_ERROR, "%a: name is not null terminated\n", __func__));
|
||||
+ return EFI_NOT_FOUND;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ DEBUG ((
|
||||
+ DEBUG_VERBOSE,
|
||||
+ "%a: +0x%04Lx: name=0x%x data=0x%x guid=%g '%s' (%a)\n",
|
||||
+ __func__,
|
||||
+ (UINT64)VarOffset,
|
||||
+ VarHeader->NameSize,
|
||||
+ VarHeader->DataSize,
|
||||
+ &VarHeader->VendorGuid,
|
||||
+ VarName,
|
||||
+ VarState
|
||||
+ ));
|
||||
+
|
||||
+ VarPadding = (4 - (VarEnd & 3)) & 3;
|
||||
+ Status = SafeUintnAdd (VarEnd, VarPadding, &VarOffset);
|
||||
+ if (RETURN_ERROR (Status)) {
|
||||
+ DEBUG ((DEBUG_ERROR, "%a: integer overflow\n", __func__));
|
||||
+ return EFI_NOT_FOUND;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
--
|
||||
2.41.0
|
||||
|
@ -1,13 +1,13 @@
|
||||
From bfdee279c563129ad1847a081e9b675e322e0788 Mon Sep 17 00:00:00 2001
|
||||
From c4eef747624d41aaa09dc64ccafdb84bf1fe656e Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Tue, 9 Jan 2024 12:29:02 +0100
|
||||
Subject: [PATCH 2/2] OvmfPkg/VirtNorFlashDxe: sanity-check variables
|
||||
|
||||
RH-Author: Gerd Hoffmann <None>
|
||||
RH-MergeRequest: 41: OvmfPkg/VirtNorFlashDxe: sanity-check variables
|
||||
RH-Jira: RHEL-20351
|
||||
RH-Acked-by: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-Commit: [2/2] da1ecd33775421c2cd77e3b0c1bea94de3aca22d
|
||||
RH-MergeRequest: 42: OvmfPkg/VirtNorFlashDxe: sanity-check variables
|
||||
RH-Jira: RHEL-17587
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [2/2] 56ff961f754d517c0e27ccf46a95b228efe7ab4b
|
||||
|
||||
Extend the ValidateFvHeader function, additionally to the header checks
|
||||
walk over the list of variables and sanity check them.
|
@ -0,0 +1,49 @@
|
||||
From 1444157aad1b98ce9c1193ef109011b084113890 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Tue, 9 Jan 2024 12:29:01 +0100
|
||||
Subject: [PATCH 09/18] OvmfPkg/VirtNorFlashDxe: stop accepting
|
||||
gEfiVariableGuid
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
RH-Author: Gerd Hoffmann <None>
|
||||
RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport
|
||||
RH-Jira: RHEL-17587
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [11/20] c7b9cd1b716e1b8163b8094fbea8117241901815
|
||||
|
||||
Only accept gEfiAuthenticatedVariableGuid when checking the variable
|
||||
store header in ValidateFvHeader().
|
||||
|
||||
The edk2 code base has been switched to use the authenticated varstore
|
||||
format unconditionally (even in case secure boot is not used or
|
||||
supported) a few years ago.
|
||||
|
||||
Suggested-by: László Érsek <lersek@redhat.com>
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
|
||||
Message-Id: <20240109112902.30002-3-kraxel@redhat.com>
|
||||
(cherry picked from commit ae22b2f136bcbd27135a5f4dd76d3a68a172d00e)
|
||||
---
|
||||
OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c | 4 +---
|
||||
1 file changed, 1 insertion(+), 3 deletions(-)
|
||||
|
||||
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c
|
||||
index cc5eefaaf3..c503272a2b 100644
|
||||
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c
|
||||
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c
|
||||
@@ -239,9 +239,7 @@ ValidateFvHeader (
|
||||
VariableStoreHeader = (VARIABLE_STORE_HEADER *)((UINTN)FwVolHeader + FwVolHeader->HeaderLength);
|
||||
|
||||
// Check the Variable Store Guid
|
||||
- if (!CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid) &&
|
||||
- !CompareGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid))
|
||||
- {
|
||||
+ if (!CompareGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid)) {
|
||||
DEBUG ((
|
||||
DEBUG_INFO,
|
||||
"%a: Variable Store Guid non-compatible\n",
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,150 @@
|
||||
From e65da48afdabc9a5cba1c212b4323898b91ef2a4 Mon Sep 17 00:00:00 2001
|
||||
From: Ard Biesheuvel <ardb@kernel.org>
|
||||
Date: Mon, 24 Oct 2022 18:16:18 +0200
|
||||
Subject: [PATCH 07/18] OvmfPkg/VirtNorFlashDxe: use EFI_MEMORY_WC and drop
|
||||
AlignedCopyMem()
|
||||
|
||||
RH-Author: Gerd Hoffmann <None>
|
||||
RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport
|
||||
RH-Jira: RHEL-17587
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [9/20] 0c01619eff8282d08e05fae8c37175b944449f59
|
||||
|
||||
NOR flash emulation under KVM involves switching between two modes,
|
||||
where array mode is backed by a read-only memslot, and programming mode
|
||||
is fully emulated, i.e., the memory region is not backed by anything,
|
||||
and the faulting accesses are forwarded to the VMM by the hypervisor,
|
||||
which translates them into NOR flash programming commands.
|
||||
|
||||
Normally, we are limited to the use of device attributes when mapping
|
||||
such regions, given that the programming mode has MMIO semantics.
|
||||
However, when running under KVM, the chosen memory attributes only take
|
||||
effect when in array mode, since no memory mapping exists otherwise.
|
||||
|
||||
This means we can tune the memory mapping so it behaves a bit more like
|
||||
a ROM, by switching to EFI_MEMORY_WC attributes. This means we no longer
|
||||
need a special CopyMem() implementation that avoids unaligned accesses
|
||||
at all cost.
|
||||
|
||||
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
|
||||
Reviewed-by: Sunil V L <sunilvl@ventanamicro.com>
|
||||
(cherry picked from commit 789a723285533f35652ebd6029976e2ddc955655)
|
||||
---
|
||||
OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 65 +----------------------
|
||||
OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c | 4 +-
|
||||
2 files changed, 4 insertions(+), 65 deletions(-)
|
||||
|
||||
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
index 0343131a54..1afd60ce66 100644
|
||||
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
|
||||
@@ -401,67 +401,6 @@ NorFlashWriteBlocks (
|
||||
return Status;
|
||||
}
|
||||
|
||||
-#define BOTH_ALIGNED(a, b, align) ((((UINTN)(a) | (UINTN)(b)) & ((align) - 1)) == 0)
|
||||
-
|
||||
-/**
|
||||
- Copy Length bytes from Source to Destination, using aligned accesses only.
|
||||
- Note that this implementation uses memcpy() semantics rather then memmove()
|
||||
- semantics, i.e., SourceBuffer and DestinationBuffer should not overlap.
|
||||
-
|
||||
- @param DestinationBuffer The target of the copy request.
|
||||
- @param SourceBuffer The place to copy from.
|
||||
- @param Length The number of bytes to copy.
|
||||
-
|
||||
- @return Destination
|
||||
-
|
||||
-**/
|
||||
-STATIC
|
||||
-VOID *
|
||||
-AlignedCopyMem (
|
||||
- OUT VOID *DestinationBuffer,
|
||||
- IN CONST VOID *SourceBuffer,
|
||||
- IN UINTN Length
|
||||
- )
|
||||
-{
|
||||
- UINT8 *Destination8;
|
||||
- CONST UINT8 *Source8;
|
||||
- UINT32 *Destination32;
|
||||
- CONST UINT32 *Source32;
|
||||
- UINT64 *Destination64;
|
||||
- CONST UINT64 *Source64;
|
||||
-
|
||||
- if (BOTH_ALIGNED (DestinationBuffer, SourceBuffer, 8) && (Length >= 8)) {
|
||||
- Destination64 = DestinationBuffer;
|
||||
- Source64 = SourceBuffer;
|
||||
- while (Length >= 8) {
|
||||
- *Destination64++ = *Source64++;
|
||||
- Length -= 8;
|
||||
- }
|
||||
-
|
||||
- Destination8 = (UINT8 *)Destination64;
|
||||
- Source8 = (CONST UINT8 *)Source64;
|
||||
- } else if (BOTH_ALIGNED (DestinationBuffer, SourceBuffer, 4) && (Length >= 4)) {
|
||||
- Destination32 = DestinationBuffer;
|
||||
- Source32 = SourceBuffer;
|
||||
- while (Length >= 4) {
|
||||
- *Destination32++ = *Source32++;
|
||||
- Length -= 4;
|
||||
- }
|
||||
-
|
||||
- Destination8 = (UINT8 *)Destination32;
|
||||
- Source8 = (CONST UINT8 *)Source32;
|
||||
- } else {
|
||||
- Destination8 = DestinationBuffer;
|
||||
- Source8 = SourceBuffer;
|
||||
- }
|
||||
-
|
||||
- while (Length-- != 0) {
|
||||
- *Destination8++ = *Source8++;
|
||||
- }
|
||||
-
|
||||
- return DestinationBuffer;
|
||||
-}
|
||||
-
|
||||
EFI_STATUS
|
||||
NorFlashReadBlocks (
|
||||
IN NOR_FLASH_INSTANCE *Instance,
|
||||
@@ -516,7 +455,7 @@ NorFlashReadBlocks (
|
||||
SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
|
||||
|
||||
// Readout the data
|
||||
- AlignedCopyMem (Buffer, (VOID *)StartAddress, BufferSizeInBytes);
|
||||
+ CopyMem (Buffer, (VOID *)StartAddress, BufferSizeInBytes);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
@@ -558,7 +497,7 @@ NorFlashRead (
|
||||
SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
|
||||
|
||||
// Readout the data
|
||||
- AlignedCopyMem (Buffer, (VOID *)(StartAddress + Offset), BufferSizeInBytes);
|
||||
+ CopyMem (Buffer, (VOID *)(StartAddress + Offset), BufferSizeInBytes);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c
|
||||
index f9a41f6aab..ff3121af2a 100644
|
||||
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c
|
||||
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c
|
||||
@@ -394,14 +394,14 @@ NorFlashFvbInitialize (
|
||||
EfiGcdMemoryTypeMemoryMappedIo,
|
||||
Instance->DeviceBaseAddress,
|
||||
RuntimeMmioRegionSize,
|
||||
- EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
|
||||
+ EFI_MEMORY_WC | EFI_MEMORY_RUNTIME
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
Status = gDS->SetMemorySpaceAttributes (
|
||||
Instance->DeviceBaseAddress,
|
||||
RuntimeMmioRegionSize,
|
||||
- EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
|
||||
+ EFI_MEMORY_WC | EFI_MEMORY_RUNTIME
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,80 @@
|
||||
From 59fb955aa77b75345f7828bf9f83764adf4bed46 Mon Sep 17 00:00:00 2001
|
||||
From: Ard Biesheuvel <ardb@kernel.org>
|
||||
Date: Mon, 24 Oct 2022 18:35:10 +0200
|
||||
Subject: [PATCH 18/18] OvmfPkg: clone NorFlashPlatformLib into
|
||||
VirtNorFlashPlatformLib
|
||||
|
||||
RH-Author: Gerd Hoffmann <None>
|
||||
RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport
|
||||
RH-Jira: RHEL-17587
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [20/20] 50ea104b99a997d7d08c1fdef617df1d930ffae6
|
||||
|
||||
Create a new library class in Ovmf that duplicates the existing
|
||||
NorFlashPlatformLib, but which will be tied to the VirtNorFlashDxe
|
||||
driver that will be introduced in a subsequent patch. This allows us to
|
||||
retire the original from ArmPlatformPkg.
|
||||
|
||||
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
|
||||
Reviewed-by: Sunil V L <sunilvl@ventanamicro.com>
|
||||
(cherry picked from commit 16bf588b604a9f190accb71ada715b81756c94e2)
|
||||
---
|
||||
.../Include/Library/VirtNorFlashPlatformLib.h | 30 +++++++++++++++++++
|
||||
OvmfPkg/OvmfPkg.dec | 4 +++
|
||||
2 files changed, 34 insertions(+)
|
||||
create mode 100644 OvmfPkg/Include/Library/VirtNorFlashPlatformLib.h
|
||||
|
||||
diff --git a/OvmfPkg/Include/Library/VirtNorFlashPlatformLib.h b/OvmfPkg/Include/Library/VirtNorFlashPlatformLib.h
|
||||
new file mode 100644
|
||||
index 0000000000..8f5b5e972d
|
||||
--- /dev/null
|
||||
+++ b/OvmfPkg/Include/Library/VirtNorFlashPlatformLib.h
|
||||
@@ -0,0 +1,30 @@
|
||||
+/** @file
|
||||
+
|
||||
+ Copyright (c) 2011-2012, ARM Ltd. All rights reserved.<BR>
|
||||
+
|
||||
+ SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
+
|
||||
+ **/
|
||||
+
|
||||
+#ifndef __VIRT_NOR_FLASH_PLATFORM_LIB__
|
||||
+#define __VIRT_NOR_FLASH_PLATFORM_LIB__
|
||||
+
|
||||
+typedef struct {
|
||||
+ UINTN DeviceBaseAddress; // Start address of the Device Base Address (DBA)
|
||||
+ UINTN RegionBaseAddress; // Start address of one single region
|
||||
+ UINTN Size;
|
||||
+ UINTN BlockSize;
|
||||
+} VIRT_NOR_FLASH_DESCRIPTION;
|
||||
+
|
||||
+EFI_STATUS
|
||||
+VirtNorFlashPlatformInitialization (
|
||||
+ VOID
|
||||
+ );
|
||||
+
|
||||
+EFI_STATUS
|
||||
+VirtNorFlashPlatformGetDevices (
|
||||
+ OUT VIRT_NOR_FLASH_DESCRIPTION **NorFlashDescriptions,
|
||||
+ OUT UINT32 *Count
|
||||
+ );
|
||||
+
|
||||
+#endif /* __VIRT_NOR_FLASH_PLATFORM_LIB__ */
|
||||
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
|
||||
index 340d83f794..e65ebd81c8 100644
|
||||
--- a/OvmfPkg/OvmfPkg.dec
|
||||
+++ b/OvmfPkg/OvmfPkg.dec
|
||||
@@ -97,6 +97,10 @@
|
||||
# transports.
|
||||
VirtioMmioDeviceLib|Include/Library/VirtioMmioDeviceLib.h
|
||||
|
||||
+ ## @libraryclass Provides a Nor flash interface.
|
||||
+ #
|
||||
+ VirtNorFlashPlatformLib|Include/Library/VirtNorFlashPlatformLib.h
|
||||
+
|
||||
## @libraryclass Invoke Xen hypercalls
|
||||
#
|
||||
XenHypercallLib|Include/Library/XenHypercallLib.h
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,68 @@
|
||||
From 2794a967f43f2bbdfcd2cb5197ac8cad4b13c3de Mon Sep 17 00:00:00 2001
|
||||
From: Jon Maloy <jmaloy@redhat.com>
|
||||
Date: Wed, 17 Jan 2024 12:20:52 -0500
|
||||
Subject: [PATCH 08/17] SecurityPkg: Adding CVE 2022-36763 to
|
||||
SecurityFixes.yaml
|
||||
|
||||
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-MergeRequest: 44: edk2: heap buffer overflow in Tcg2MeasureGptTable()
|
||||
RH-Jira: RHEL-21154 RHEL-21156
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [8/13] 74117caf760e403566f6511332b2c0f41483f28c (jmaloy/jons_fork)
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-21154
|
||||
Upstream: Merged
|
||||
CVE: CVE-2022-36763
|
||||
|
||||
commit 1ddcb9fc6b4164e882687b031e8beacfcf7df29e
|
||||
Author: Douglas Flick [MSFT] <doug.edk2@gmail.com>
|
||||
Date: Fri Jan 12 02:16:03 2024 +0800
|
||||
|
||||
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>
|
||||
|
||||
Signed-off-by: Jon Maloy <jmaloy@redhat.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.41.0
|
||||
|
@ -0,0 +1,403 @@
|
||||
From e2ccaef3baa2eb045019558c325bb94cabf65e1a Mon Sep 17 00:00:00 2001
|
||||
From: Jon Maloy <jmaloy@redhat.com>
|
||||
Date: Wed, 7 Feb 2024 11:56:37 -0500
|
||||
Subject: [PATCH 02/17] SecurityPkg: Change OPTIONAL keyword usage style
|
||||
|
||||
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-MergeRequest: 44: edk2: heap buffer overflow in Tcg2MeasureGptTable()
|
||||
RH-Jira: RHEL-21154 RHEL-21156
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [2/13] 6a2141d871e3efc3aeea1994ab9c325614ddce57 (jmaloy/jons_fork)
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-21154
|
||||
CVE: CVE-2022-36763
|
||||
Upstream: Merged
|
||||
|
||||
commit 948f4003ee399241a40dc147a738f05ad2e37375
|
||||
Author: Michael D Kinney <michael.d.kinney@intel.com>
|
||||
Date: Thu Dec 2 18:00:56 2021 -0800
|
||||
|
||||
SecurityPkg: Change OPTIONAL keyword usage style
|
||||
|
||||
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3760
|
||||
|
||||
Update all use of ', OPTIONAL' to ' OPTIONAL,' for function params.
|
||||
|
||||
Cc: Andrew Fish <afish@apple.com>
|
||||
Cc: Leif Lindholm <leif@nuviainc.com>
|
||||
Cc: Michael Kubacki <michael.kubacki@microsoft.com>
|
||||
Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
|
||||
Reviewed-by: Jian J Wang <jian.j.wang@intel.com>
|
||||
|
||||
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
|
||||
---
|
||||
SecurityPkg/Include/Library/Tcg2PpVendorLib.h | 2 +-
|
||||
SecurityPkg/Include/Library/Tpm2CommandLib.h | 14 +++++++-------
|
||||
SecurityPkg/Library/AuthVariableLib/AuthService.c | 6 +++---
|
||||
.../DxeImageAuthenticationStatusLib.c | 2 +-
|
||||
.../DxeImageVerificationLib.c | 2 +-
|
||||
.../DxeRsa2048Sha256GuidedSectionExtractLib.c | 2 +-
|
||||
.../DxeTcg2PhysicalPresenceLib.c | 4 ++--
|
||||
.../DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c | 2 +-
|
||||
.../DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c | 2 +-
|
||||
.../PeiRsa2048Sha256GuidedSectionExtractLib.c | 2 +-
|
||||
.../Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.c | 2 +-
|
||||
.../Tpm2CommandLib/Tpm2EnhancedAuthorization.c | 2 +-
|
||||
SecurityPkg/Library/Tpm2CommandLib/Tpm2Help.c | 2 +-
|
||||
SecurityPkg/Library/Tpm2CommandLib/Tpm2Hierarchy.c | 2 +-
|
||||
SecurityPkg/Library/Tpm2CommandLib/Tpm2Integrity.c | 2 +-
|
||||
SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c | 6 +++---
|
||||
.../RandomNumberGenerator/RngDxe/AArch64/RngDxe.c | 2 +-
|
||||
.../RandomNumberGenerator/RngDxe/Rand/RngDxe.c | 2 +-
|
||||
.../RandomNumberGenerator/RngDxe/RngDxeInternals.h | 2 +-
|
||||
SecurityPkg/Tcg/TcgConfigDxe/TcgConfigImpl.c | 2 +-
|
||||
20 files changed, 31 insertions(+), 31 deletions(-)
|
||||
|
||||
diff --git a/SecurityPkg/Include/Library/Tcg2PpVendorLib.h b/SecurityPkg/Include/Library/Tcg2PpVendorLib.h
|
||||
index 569eba6874..914517f034 100644
|
||||
--- a/SecurityPkg/Include/Library/Tcg2PpVendorLib.h
|
||||
+++ b/SecurityPkg/Include/Library/Tcg2PpVendorLib.h
|
||||
@@ -40,7 +40,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
UINT32
|
||||
EFIAPI
|
||||
Tcg2PpVendorLibExecutePendingRequest (
|
||||
- IN TPM2B_AUTH *PlatformAuth, OPTIONAL
|
||||
+ IN TPM2B_AUTH *PlatformAuth OPTIONAL,
|
||||
IN UINT32 OperationRequest,
|
||||
IN OUT UINT32 *ManagementFlags,
|
||||
OUT BOOLEAN *ResetRequired
|
||||
diff --git a/SecurityPkg/Include/Library/Tpm2CommandLib.h b/SecurityPkg/Include/Library/Tpm2CommandLib.h
|
||||
index ee8eb62295..ad3b982d48 100644
|
||||
--- a/SecurityPkg/Include/Library/Tpm2CommandLib.h
|
||||
+++ b/SecurityPkg/Include/Library/Tpm2CommandLib.h
|
||||
@@ -186,7 +186,7 @@ EFI_STATUS
|
||||
EFIAPI
|
||||
Tpm2ClearControl (
|
||||
IN TPMI_RH_CLEAR AuthHandle,
|
||||
- IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL
|
||||
+ IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL,
|
||||
IN TPMI_YES_NO Disable
|
||||
);
|
||||
|
||||
@@ -340,7 +340,7 @@ EFI_STATUS
|
||||
EFIAPI
|
||||
Tpm2NvDefineSpace (
|
||||
IN TPMI_RH_PROVISION AuthHandle,
|
||||
- IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL
|
||||
+ IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL,
|
||||
IN TPM2B_AUTH *Auth,
|
||||
IN TPM2B_NV_PUBLIC *NvPublic
|
||||
);
|
||||
@@ -383,7 +383,7 @@ EFIAPI
|
||||
Tpm2NvRead (
|
||||
IN TPMI_RH_NV_AUTH AuthHandle,
|
||||
IN TPMI_RH_NV_INDEX NvIndex,
|
||||
- IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL
|
||||
+ IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL,
|
||||
IN UINT16 Size,
|
||||
IN UINT16 Offset,
|
||||
IN OUT TPM2B_MAX_BUFFER *OutData
|
||||
@@ -407,7 +407,7 @@ EFIAPI
|
||||
Tpm2NvWrite (
|
||||
IN TPMI_RH_NV_AUTH AuthHandle,
|
||||
IN TPMI_RH_NV_INDEX NvIndex,
|
||||
- IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL
|
||||
+ IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL,
|
||||
IN TPM2B_MAX_BUFFER *InData,
|
||||
IN UINT16 Offset
|
||||
);
|
||||
@@ -566,7 +566,7 @@ Tpm2PcrAllocate (
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tpm2PcrAllocateBanks (
|
||||
- IN TPM2B_AUTH *PlatformAuth, OPTIONAL
|
||||
+ IN TPM2B_AUTH *PlatformAuth OPTIONAL,
|
||||
IN UINT32 SupportedPCRBanks,
|
||||
IN UINT32 PCRBanks
|
||||
);
|
||||
@@ -908,7 +908,7 @@ EFIAPI
|
||||
Tpm2PolicySecret (
|
||||
IN TPMI_DH_ENTITY AuthHandle,
|
||||
IN TPMI_SH_POLICY PolicySession,
|
||||
- IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL
|
||||
+ IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL,
|
||||
IN TPM2B_NONCE *NonceTPM,
|
||||
IN TPM2B_DIGEST *CpHashA,
|
||||
IN TPM2B_NONCE *PolicyRef,
|
||||
@@ -1004,7 +1004,7 @@ Tpm2ReadPublic (
|
||||
UINT32
|
||||
EFIAPI
|
||||
CopyAuthSessionCommand (
|
||||
- IN TPMS_AUTH_COMMAND *AuthSessionIn, OPTIONAL
|
||||
+ IN TPMS_AUTH_COMMAND *AuthSessionIn OPTIONAL,
|
||||
OUT UINT8 *AuthSessionOut
|
||||
);
|
||||
|
||||
diff --git a/SecurityPkg/Library/AuthVariableLib/AuthService.c b/SecurityPkg/Library/AuthVariableLib/AuthService.c
|
||||
index aa9ebaf3be..3059e5d256 100644
|
||||
--- a/SecurityPkg/Library/AuthVariableLib/AuthService.c
|
||||
+++ b/SecurityPkg/Library/AuthVariableLib/AuthService.c
|
||||
@@ -1183,9 +1183,9 @@ FindCertsFromDb (
|
||||
IN EFI_GUID *VendorGuid,
|
||||
IN UINT8 *Data,
|
||||
IN UINTN DataSize,
|
||||
- OUT UINT32 *CertOffset, OPTIONAL
|
||||
- OUT UINT32 *CertDataSize, OPTIONAL
|
||||
- OUT UINT32 *CertNodeOffset,OPTIONAL
|
||||
+ OUT UINT32 *CertOffset OPTIONAL,
|
||||
+ OUT UINT32 *CertDataSize OPTIONAL,
|
||||
+ OUT UINT32 *CertNodeOffset OPTIONAL,
|
||||
OUT UINT32 *CertNodeSize OPTIONAL
|
||||
)
|
||||
{
|
||||
diff --git a/SecurityPkg/Library/DxeImageAuthenticationStatusLib/DxeImageAuthenticationStatusLib.c b/SecurityPkg/Library/DxeImageAuthenticationStatusLib/DxeImageAuthenticationStatusLib.c
|
||||
index ec77151c9c..9acff2ae7d 100644
|
||||
--- a/SecurityPkg/Library/DxeImageAuthenticationStatusLib/DxeImageAuthenticationStatusLib.c
|
||||
+++ b/SecurityPkg/Library/DxeImageAuthenticationStatusLib/DxeImageAuthenticationStatusLib.c
|
||||
@@ -32,7 +32,7 @@ EFI_STATUS
|
||||
EFIAPI
|
||||
DxeImageAuthenticationStatusHandler (
|
||||
IN UINT32 AuthenticationStatus,
|
||||
- IN CONST EFI_DEVICE_PATH_PROTOCOL *File, OPTIONAL
|
||||
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *File OPTIONAL,
|
||||
IN VOID *FileBuffer,
|
||||
IN UINTN FileSize,
|
||||
IN BOOLEAN BootPolicy
|
||||
diff --git a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
|
||||
index 1252927664..0a12692454 100644
|
||||
--- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
|
||||
+++ b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
|
||||
@@ -1636,7 +1636,7 @@ EFI_STATUS
|
||||
EFIAPI
|
||||
DxeImageVerificationHandler (
|
||||
IN UINT32 AuthenticationStatus,
|
||||
- IN CONST EFI_DEVICE_PATH_PROTOCOL *File, OPTIONAL
|
||||
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *File OPTIONAL,
|
||||
IN VOID *FileBuffer,
|
||||
IN UINTN FileSize,
|
||||
IN BOOLEAN BootPolicy
|
||||
diff --git a/SecurityPkg/Library/DxeRsa2048Sha256GuidedSectionExtractLib/DxeRsa2048Sha256GuidedSectionExtractLib.c b/SecurityPkg/Library/DxeRsa2048Sha256GuidedSectionExtractLib/DxeRsa2048Sha256GuidedSectionExtractLib.c
|
||||
index 28807d4d98..5124b884c9 100644
|
||||
--- a/SecurityPkg/Library/DxeRsa2048Sha256GuidedSectionExtractLib/DxeRsa2048Sha256GuidedSectionExtractLib.c
|
||||
+++ b/SecurityPkg/Library/DxeRsa2048Sha256GuidedSectionExtractLib/DxeRsa2048Sha256GuidedSectionExtractLib.c
|
||||
@@ -123,7 +123,7 @@ EFIAPI
|
||||
Rsa2048Sha256GuidedSectionHandler (
|
||||
IN CONST VOID *InputSection,
|
||||
OUT VOID **OutputBuffer,
|
||||
- IN VOID *ScratchBuffer, OPTIONAL
|
||||
+ IN VOID *ScratchBuffer OPTIONAL,
|
||||
OUT UINT32 *AuthenticationStatus
|
||||
)
|
||||
{
|
||||
diff --git a/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c b/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c
|
||||
index fce5c0af50..d92658f80d 100644
|
||||
--- a/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c
|
||||
+++ b/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c
|
||||
@@ -147,7 +147,7 @@ Tpm2CommandChangeEps (
|
||||
**/
|
||||
UINT32
|
||||
Tcg2ExecutePhysicalPresence (
|
||||
- IN TPM2B_AUTH *PlatformAuth, OPTIONAL
|
||||
+ IN TPM2B_AUTH *PlatformAuth OPTIONAL,
|
||||
IN UINT32 CommandCode,
|
||||
IN UINT32 CommandParameter,
|
||||
IN OUT EFI_TCG2_PHYSICAL_PRESENCE_FLAGS *PpiFlags
|
||||
@@ -720,7 +720,7 @@ Tcg2HaveValidTpmRequest (
|
||||
**/
|
||||
VOID
|
||||
Tcg2ExecutePendingTpmRequest (
|
||||
- IN TPM2B_AUTH *PlatformAuth, OPTIONAL
|
||||
+ IN TPM2B_AUTH *PlatformAuth OPTIONAL,
|
||||
IN OUT EFI_TCG2_PHYSICAL_PRESENCE *TcgPpData,
|
||||
IN OUT EFI_TCG2_PHYSICAL_PRESENCE_FLAGS *Flags
|
||||
)
|
||||
diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c
|
||||
index a531385f81..95682ac567 100644
|
||||
--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c
|
||||
+++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c
|
||||
@@ -416,7 +416,7 @@ EFI_STATUS
|
||||
EFIAPI
|
||||
DxeTpm2MeasureBootHandler (
|
||||
IN UINT32 AuthenticationStatus,
|
||||
- IN CONST EFI_DEVICE_PATH_PROTOCOL *File, OPTIONAL
|
||||
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *File OPTIONAL,
|
||||
IN VOID *FileBuffer,
|
||||
IN UINTN FileSize,
|
||||
IN BOOLEAN BootPolicy
|
||||
diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c
|
||||
index 4e74cd9db6..27c0ea48ca 100644
|
||||
--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c
|
||||
+++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c
|
||||
@@ -710,7 +710,7 @@ EFI_STATUS
|
||||
EFIAPI
|
||||
DxeTpmMeasureBootHandler (
|
||||
IN UINT32 AuthenticationStatus,
|
||||
- IN CONST EFI_DEVICE_PATH_PROTOCOL *File, OPTIONAL
|
||||
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *File OPTIONAL,
|
||||
IN VOID *FileBuffer,
|
||||
IN UINTN FileSize,
|
||||
IN BOOLEAN BootPolicy
|
||||
diff --git a/SecurityPkg/Library/PeiRsa2048Sha256GuidedSectionExtractLib/PeiRsa2048Sha256GuidedSectionExtractLib.c b/SecurityPkg/Library/PeiRsa2048Sha256GuidedSectionExtractLib/PeiRsa2048Sha256GuidedSectionExtractLib.c
|
||||
index a759183d20..96638e26aa 100644
|
||||
--- a/SecurityPkg/Library/PeiRsa2048Sha256GuidedSectionExtractLib/PeiRsa2048Sha256GuidedSectionExtractLib.c
|
||||
+++ b/SecurityPkg/Library/PeiRsa2048Sha256GuidedSectionExtractLib/PeiRsa2048Sha256GuidedSectionExtractLib.c
|
||||
@@ -121,7 +121,7 @@ EFIAPI
|
||||
Rsa2048Sha256GuidedSectionHandler (
|
||||
IN CONST VOID *InputSection,
|
||||
OUT VOID **OutputBuffer,
|
||||
- IN VOID *ScratchBuffer, OPTIONAL
|
||||
+ IN VOID *ScratchBuffer OPTIONAL,
|
||||
OUT UINT32 *AuthenticationStatus
|
||||
)
|
||||
{
|
||||
diff --git a/SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.c b/SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.c
|
||||
index 895d05a28d..aa3dcb6beb 100644
|
||||
--- a/SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.c
|
||||
+++ b/SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.c
|
||||
@@ -30,7 +30,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
UINT32
|
||||
EFIAPI
|
||||
Tcg2PpVendorLibExecutePendingRequest (
|
||||
- IN TPM2B_AUTH *PlatformAuth, OPTIONAL
|
||||
+ IN TPM2B_AUTH *PlatformAuth OPTIONAL,
|
||||
IN UINT32 OperationRequest,
|
||||
IN OUT UINT32 *ManagementFlags,
|
||||
OUT BOOLEAN *ResetRequired
|
||||
diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2EnhancedAuthorization.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2EnhancedAuthorization.c
|
||||
index 0404c0f321..53983d745b 100644
|
||||
--- a/SecurityPkg/Library/Tpm2CommandLib/Tpm2EnhancedAuthorization.c
|
||||
+++ b/SecurityPkg/Library/Tpm2CommandLib/Tpm2EnhancedAuthorization.c
|
||||
@@ -90,7 +90,7 @@ EFIAPI
|
||||
Tpm2PolicySecret (
|
||||
IN TPMI_DH_ENTITY AuthHandle,
|
||||
IN TPMI_SH_POLICY PolicySession,
|
||||
- IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL
|
||||
+ IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL,
|
||||
IN TPM2B_NONCE *NonceTPM,
|
||||
IN TPM2B_DIGEST *CpHashA,
|
||||
IN TPM2B_NONCE *PolicyRef,
|
||||
diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Help.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Help.c
|
||||
index 13eeb6ec18..44115cded3 100644
|
||||
--- a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Help.c
|
||||
+++ b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Help.c
|
||||
@@ -84,7 +84,7 @@ GetHashMaskFromAlgo (
|
||||
UINT32
|
||||
EFIAPI
|
||||
CopyAuthSessionCommand (
|
||||
- IN TPMS_AUTH_COMMAND *AuthSessionIn, OPTIONAL
|
||||
+ IN TPMS_AUTH_COMMAND *AuthSessionIn OPTIONAL,
|
||||
OUT UINT8 *AuthSessionOut
|
||||
)
|
||||
{
|
||||
diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Hierarchy.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Hierarchy.c
|
||||
index 043d358a06..957d694431 100644
|
||||
--- a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Hierarchy.c
|
||||
+++ b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Hierarchy.c
|
||||
@@ -305,7 +305,7 @@ EFI_STATUS
|
||||
EFIAPI
|
||||
Tpm2ClearControl (
|
||||
IN TPMI_RH_CLEAR AuthHandle,
|
||||
- IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL
|
||||
+ IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL,
|
||||
IN TPMI_YES_NO Disable
|
||||
)
|
||||
{
|
||||
diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Integrity.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Integrity.c
|
||||
index 8c87de0b0c..d232fe725d 100644
|
||||
--- a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Integrity.c
|
||||
+++ b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Integrity.c
|
||||
@@ -566,7 +566,7 @@ Done:
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tpm2PcrAllocateBanks (
|
||||
- IN TPM2B_AUTH *PlatformAuth, OPTIONAL
|
||||
+ IN TPM2B_AUTH *PlatformAuth OPTIONAL,
|
||||
IN UINT32 SupportedPCRBanks,
|
||||
IN UINT32 PCRBanks
|
||||
)
|
||||
diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c
|
||||
index fb46af0fed..d9171fb9a0 100644
|
||||
--- a/SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c
|
||||
+++ b/SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c
|
||||
@@ -281,7 +281,7 @@ EFI_STATUS
|
||||
EFIAPI
|
||||
Tpm2NvDefineSpace (
|
||||
IN TPMI_RH_PROVISION AuthHandle,
|
||||
- IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL
|
||||
+ IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL,
|
||||
IN TPM2B_AUTH *Auth,
|
||||
IN TPM2B_NV_PUBLIC *NvPublic
|
||||
)
|
||||
@@ -525,7 +525,7 @@ EFIAPI
|
||||
Tpm2NvRead (
|
||||
IN TPMI_RH_NV_AUTH AuthHandle,
|
||||
IN TPMI_RH_NV_INDEX NvIndex,
|
||||
- IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL
|
||||
+ IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL,
|
||||
IN UINT16 Size,
|
||||
IN UINT16 Offset,
|
||||
IN OUT TPM2B_MAX_BUFFER *OutData
|
||||
@@ -670,7 +670,7 @@ EFIAPI
|
||||
Tpm2NvWrite (
|
||||
IN TPMI_RH_NV_AUTH AuthHandle,
|
||||
IN TPMI_RH_NV_INDEX NvIndex,
|
||||
- IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL
|
||||
+ IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL,
|
||||
IN TPM2B_MAX_BUFFER *InData,
|
||||
IN UINT16 Offset
|
||||
)
|
||||
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c b/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c
|
||||
index 282fdca9d3..1cdc842966 100644
|
||||
--- a/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c
|
||||
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c
|
||||
@@ -53,7 +53,7 @@ EFI_STATUS
|
||||
EFIAPI
|
||||
RngGetRNG (
|
||||
IN EFI_RNG_PROTOCOL *This,
|
||||
- IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL
|
||||
+ IN EFI_RNG_ALGORITHM *RNGAlgorithm OPTIONAL,
|
||||
IN UINTN RNGValueLength,
|
||||
OUT UINT8 *RNGValue
|
||||
)
|
||||
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c
|
||||
index d0e6b7de06..834123b945 100644
|
||||
--- a/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c
|
||||
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c
|
||||
@@ -49,7 +49,7 @@ EFI_STATUS
|
||||
EFIAPI
|
||||
RngGetRNG (
|
||||
IN EFI_RNG_PROTOCOL *This,
|
||||
- IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL
|
||||
+ IN EFI_RNG_ALGORITHM *RNGAlgorithm OPTIONAL,
|
||||
IN UINTN RNGValueLength,
|
||||
OUT UINT8 *RNGValue
|
||||
)
|
||||
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h
|
||||
index 2660ed5875..25cccbe92c 100644
|
||||
--- a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h
|
||||
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h
|
||||
@@ -67,7 +67,7 @@ EFI_STATUS
|
||||
EFIAPI
|
||||
RngGetRNG (
|
||||
IN EFI_RNG_PROTOCOL *This,
|
||||
- IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL
|
||||
+ IN EFI_RNG_ALGORITHM *RNGAlgorithm OPTIONAL,
|
||||
IN UINTN RNGValueLength,
|
||||
OUT UINT8 *RNGValue
|
||||
);
|
||||
diff --git a/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigImpl.c b/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigImpl.c
|
||||
index 68cd62307c..09cb4b0ee9 100644
|
||||
--- a/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigImpl.c
|
||||
+++ b/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigImpl.c
|
||||
@@ -56,7 +56,7 @@ HII_VENDOR_DEVICE_PATH mTcgHiiVendorDevicePath = {
|
||||
EFI_STATUS
|
||||
GetTpmState (
|
||||
IN EFI_TCG_PROTOCOL *TcgProtocol,
|
||||
- OUT BOOLEAN *TpmEnable, OPTIONAL
|
||||
+ OUT BOOLEAN *TpmEnable OPTIONAL,
|
||||
OUT BOOLEAN *TpmActivate OPTIONAL
|
||||
)
|
||||
{
|
||||
--
|
||||
2.41.0
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,272 @@
|
||||
From 7b5040e857f1a16bed935f7944bda8bc6f6999ac Mon Sep 17 00:00:00 2001
|
||||
From: Jon Maloy <jmaloy@redhat.com>
|
||||
Date: Tue, 13 Feb 2024 16:30:10 -0500
|
||||
Subject: [PATCH 11/17] SecurityPkg: DxeTpm2MeasureBootLib: SECURITY PATCH
|
||||
4117/4118 symbol rename
|
||||
|
||||
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-MergeRequest: 44: edk2: heap buffer overflow in Tcg2MeasureGptTable()
|
||||
RH-Jira: RHEL-21154 RHEL-21156
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [11/13] 45fc2658aaa726b57219789bb1af64f5c4e2cfdc (jmaloy/jons_fork)
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-21156
|
||||
CVE: CVE-2022-36764
|
||||
Upstream: Merged
|
||||
|
||||
commit 40adbb7f628dee79156c679fb0857968b61b7620
|
||||
Author: Doug Flick <dougflick@microsoft.com>
|
||||
Date: Wed Jan 17 14:47:20 2024 -0800
|
||||
|
||||
SecurityPkg: DxeTpm2MeasureBootLib: SECURITY PATCH 4117/4118 symbol rename
|
||||
|
||||
Updates the sanitation function names to be lib unique names
|
||||
|
||||
Cc: Jiewen Yao <jiewen.yao@intel.com>
|
||||
Cc: Rahul Kumar <rahul1.kumar@intel.com>
|
||||
|
||||
Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
|
||||
Message-Id: <7b18434c8a8b561654efd40ced3becb8b378c8f1.1705529990.git.doug.edk2@gmail.com>
|
||||
Reviewed-by: Jiewen Yao <Jiewen.yao@intel.com>
|
||||
|
||||
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
|
||||
---
|
||||
.../DxeTpm2MeasureBootLib.c | 8 +++---
|
||||
.../DxeTpm2MeasureBootLibSanitization.c | 8 +++---
|
||||
.../DxeTpm2MeasureBootLibSanitization.h | 8 +++---
|
||||
.../DxeTpm2MeasureBootLibSanitizationTest.c | 26 +++++++++----------
|
||||
4 files changed, 25 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c
|
||||
index f06926e631..8f8bef1d0b 100644
|
||||
--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c
|
||||
+++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c
|
||||
@@ -197,7 +197,7 @@ Tcg2MeasureGptTable (
|
||||
BlockIo->Media->BlockSize,
|
||||
(UINT8 *)PrimaryHeader
|
||||
);
|
||||
- if (EFI_ERROR (Status) || EFI_ERROR (SanitizeEfiPartitionTableHeader (PrimaryHeader, BlockIo))) {
|
||||
+ if (EFI_ERROR (Status) || EFI_ERROR (Tpm2SanitizeEfiPartitionTableHeader (PrimaryHeader, BlockIo))) {
|
||||
DEBUG ((DEBUG_ERROR, "Failed to read Partition Table Header or invalid Partition Table Header!\n"));
|
||||
FreePool (PrimaryHeader);
|
||||
return EFI_DEVICE_ERROR;
|
||||
@@ -206,7 +206,7 @@ Tcg2MeasureGptTable (
|
||||
//
|
||||
// Read the partition entry.
|
||||
//
|
||||
- Status = SanitizePrimaryHeaderAllocationSize (PrimaryHeader, &AllocSize);
|
||||
+ Status = Tpm2SanitizePrimaryHeaderAllocationSize (PrimaryHeader, &AllocSize);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (PrimaryHeader);
|
||||
return EFI_BAD_BUFFER_SIZE;
|
||||
@@ -245,7 +245,7 @@ Tcg2MeasureGptTable (
|
||||
//
|
||||
// Prepare Data for Measurement (CcProtocol and Tcg2Protocol)
|
||||
//
|
||||
- Status = SanitizePrimaryHeaderGptEventSize (PrimaryHeader, NumberOfPartition, &TcgEventSize);
|
||||
+ Status = Tpm2SanitizePrimaryHeaderGptEventSize (PrimaryHeader, NumberOfPartition, &TcgEventSize);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (PrimaryHeader);
|
||||
FreePool (EntryPtr);
|
||||
@@ -414,7 +414,7 @@ Tcg2MeasurePeImage (
|
||||
}
|
||||
|
||||
FilePathSize = (UINT32)GetDevicePathSize (FilePath);
|
||||
- Status = SanitizePeImageEventSize (FilePathSize, &EventSize);
|
||||
+ Status = Tpm2SanitizePeImageEventSize (FilePathSize, &EventSize);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c
|
||||
index 2a4d52c6d5..809a3bfd89 100644
|
||||
--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c
|
||||
+++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c
|
||||
@@ -63,7 +63,7 @@
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
-SanitizeEfiPartitionTableHeader (
|
||||
+Tpm2SanitizeEfiPartitionTableHeader (
|
||||
IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader,
|
||||
IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo
|
||||
)
|
||||
@@ -169,7 +169,7 @@ SanitizeEfiPartitionTableHeader (
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
-SanitizePrimaryHeaderAllocationSize (
|
||||
+Tpm2SanitizePrimaryHeaderAllocationSize (
|
||||
IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader,
|
||||
OUT UINT32 *AllocationSize
|
||||
)
|
||||
@@ -221,7 +221,7 @@ SanitizePrimaryHeaderAllocationSize (
|
||||
One of the passed parameters was invalid.
|
||||
**/
|
||||
EFI_STATUS
|
||||
-SanitizePrimaryHeaderGptEventSize (
|
||||
+Tpm2SanitizePrimaryHeaderGptEventSize (
|
||||
IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader,
|
||||
IN UINTN NumberOfPartition,
|
||||
OUT UINT32 *EventSize
|
||||
@@ -292,7 +292,7 @@ SanitizePrimaryHeaderGptEventSize (
|
||||
One of the passed parameters was invalid.
|
||||
**/
|
||||
EFI_STATUS
|
||||
-SanitizePeImageEventSize (
|
||||
+Tpm2SanitizePeImageEventSize (
|
||||
IN UINT32 FilePathSize,
|
||||
OUT UINT32 *EventSize
|
||||
)
|
||||
diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h
|
||||
index 8f72ba4240..8526bc7537 100644
|
||||
--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h
|
||||
+++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h
|
||||
@@ -54,7 +54,7 @@
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
-SanitizeEfiPartitionTableHeader (
|
||||
+Tpm2SanitizeEfiPartitionTableHeader (
|
||||
IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader,
|
||||
IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo
|
||||
);
|
||||
@@ -78,7 +78,7 @@ SanitizeEfiPartitionTableHeader (
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
-SanitizePrimaryHeaderAllocationSize (
|
||||
+Tpm2SanitizePrimaryHeaderAllocationSize (
|
||||
IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader,
|
||||
OUT UINT32 *AllocationSize
|
||||
);
|
||||
@@ -107,7 +107,7 @@ SanitizePrimaryHeaderAllocationSize (
|
||||
One of the passed parameters was invalid.
|
||||
**/
|
||||
EFI_STATUS
|
||||
-SanitizePrimaryHeaderGptEventSize (
|
||||
+Tpm2SanitizePrimaryHeaderGptEventSize (
|
||||
IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader,
|
||||
IN UINTN NumberOfPartition,
|
||||
OUT UINT32 *EventSize
|
||||
@@ -131,7 +131,7 @@ SanitizePrimaryHeaderGptEventSize (
|
||||
One of the passed parameters was invalid.
|
||||
**/
|
||||
EFI_STATUS
|
||||
-SanitizePeImageEventSize (
|
||||
+Tpm2SanitizePeImageEventSize (
|
||||
IN UINT32 FilePathSize,
|
||||
OUT UINT32 *EventSize
|
||||
);
|
||||
diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c
|
||||
index 820e99aeb9..50a68e1076 100644
|
||||
--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c
|
||||
+++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c
|
||||
@@ -84,27 +84,27 @@ TestSanitizeEfiPartitionTableHeader (
|
||||
PrimaryHeader.Header.CRC32 = CalculateCrc32 ((UINT8 *)&PrimaryHeader, PrimaryHeader.Header.HeaderSize);
|
||||
|
||||
// Test that a normal PrimaryHeader passes validation
|
||||
- Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo);
|
||||
+ Status = Tpm2SanitizeEfiPartitionTableHeader (&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);
|
||||
+ Status = Tpm2SanitizeEfiPartitionTableHeader (&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);
|
||||
+ Status = Tpm2SanitizeEfiPartitionTableHeader (&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);
|
||||
+ Status = Tpm2SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo);
|
||||
UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR);
|
||||
|
||||
DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));
|
||||
@@ -137,7 +137,7 @@ TestSanitizePrimaryHeaderAllocationSize (
|
||||
PrimaryHeader.NumberOfPartitionEntries = 5;
|
||||
PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;
|
||||
|
||||
- Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);
|
||||
+ Status = Tpm2SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);
|
||||
UT_ASSERT_NOT_EFI_ERROR (Status);
|
||||
|
||||
// Test that the allocation size is correct compared to the existing logic
|
||||
@@ -146,19 +146,19 @@ TestSanitizePrimaryHeaderAllocationSize (
|
||||
// Test that an overflow is detected
|
||||
PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32;
|
||||
PrimaryHeader.SizeOfPartitionEntry = 5;
|
||||
- Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);
|
||||
+ Status = Tpm2SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);
|
||||
UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
|
||||
|
||||
// Test the inverse
|
||||
PrimaryHeader.NumberOfPartitionEntries = 5;
|
||||
PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32;
|
||||
- Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);
|
||||
+ Status = Tpm2SanitizePrimaryHeaderAllocationSize (&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);
|
||||
+ Status = Tpm2SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);
|
||||
UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
|
||||
|
||||
DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));
|
||||
@@ -196,7 +196,7 @@ TestSanitizePrimaryHeaderGptEventSize (
|
||||
NumberOfPartition = 13;
|
||||
|
||||
// that the primary event size is correct
|
||||
- Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize);
|
||||
+ Status = Tpm2SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize);
|
||||
UT_ASSERT_NOT_EFI_ERROR (Status);
|
||||
|
||||
// Calculate the existing logic event size
|
||||
@@ -207,12 +207,12 @@ TestSanitizePrimaryHeaderGptEventSize (
|
||||
UT_ASSERT_EQUAL (EventSize, ExistingLogicEventSize);
|
||||
|
||||
// Tests that the primary event size may not overflow
|
||||
- Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, MAX_UINT32, &EventSize);
|
||||
+ Status = Tpm2SanitizePrimaryHeaderGptEventSize (&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);
|
||||
+ Status = Tpm2SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize);
|
||||
UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
|
||||
|
||||
DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));
|
||||
@@ -245,7 +245,7 @@ TestSanitizePeImageEventSize (
|
||||
FilePathSize = 255;
|
||||
|
||||
// Test that a normal PE image passes validation
|
||||
- Status = SanitizePeImageEventSize (FilePathSize, &EventSize);
|
||||
+ Status = Tpm2SanitizePeImageEventSize (FilePathSize, &EventSize);
|
||||
UT_ASSERT_EQUAL (Status, EFI_SUCCESS);
|
||||
|
||||
// Test that the event size is correct compared to the existing logic
|
||||
@@ -258,7 +258,7 @@ TestSanitizePeImageEventSize (
|
||||
}
|
||||
|
||||
// Test that the event size may not overflow
|
||||
- Status = SanitizePeImageEventSize (MAX_UINT32, &EventSize);
|
||||
+ Status = Tpm2SanitizePeImageEventSize (MAX_UINT32, &EventSize);
|
||||
UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
|
||||
|
||||
DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));
|
||||
--
|
||||
2.41.0
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,286 @@
|
||||
From 7c3fefb0c857acb9e7e14b150c4c3131e78fbb63 Mon Sep 17 00:00:00 2001
|
||||
From: Jon Maloy <jmaloy@redhat.com>
|
||||
Date: Wed, 7 Feb 2024 15:43:10 -0500
|
||||
Subject: [PATCH 09/17] SecurityPkg: DxeTpm2MeasureBootLib: SECURITY PATCH 4118
|
||||
- CVE 2022-36764
|
||||
|
||||
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-MergeRequest: 44: edk2: heap buffer overflow in Tcg2MeasureGptTable()
|
||||
RH-Jira: RHEL-21154 RHEL-21156
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [9/13] c7890fc5c5d7fef2fc1daa931ea2d48f3a76b9e3 (jmaloy/jons_fork)
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-21156
|
||||
CVE: CVE-2022-36764
|
||||
Upstream: Merged
|
||||
|
||||
commit c7b27944218130cca3bbb20314ba5b88b5de4aa4
|
||||
Author: Douglas Flick [MSFT] <doug.edk2@gmail.com>
|
||||
Date: Fri Jan 12 02:16:04 2024 +0800
|
||||
|
||||
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>
|
||||
|
||||
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
|
||||
---
|
||||
.../DxeTpm2MeasureBootLib.c | 15 +++--
|
||||
.../DxeTpm2MeasureBootLibSanitization.c | 46 +++++++++++++-
|
||||
.../DxeTpm2MeasureBootLibSanitization.h | 28 ++++++++-
|
||||
.../DxeTpm2MeasureBootLibSanitizationTest.c | 60 ++++++++++++++++---
|
||||
4 files changed, 133 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c
|
||||
index 476c8d543f..f06926e631 100644
|
||||
--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c
|
||||
+++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c
|
||||
@@ -372,7 +372,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
|
||||
@@ -399,6 +398,7 @@ Tcg2MeasurePeImage (
|
||||
Status = EFI_UNSUPPORTED;
|
||||
ImageLoad = NULL;
|
||||
EventPtr = NULL;
|
||||
+ Tcg2Event = NULL;
|
||||
|
||||
Tcg2Protocol = MeasureBootProtocols->Tcg2Protocol;
|
||||
CcProtocol = MeasureBootProtocols->CcProtocol;
|
||||
@@ -413,19 +413,24 @@ Tcg2MeasurePeImage (
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
- FilePathSize = (UINT32) GetDevicePathSize (FilePath);
|
||||
+ 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->Header.HeaderSize = sizeof(EFI_TCG2_EVENT_HEADER);
|
||||
+ 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.41.0
|
||||
|
@ -0,0 +1,279 @@
|
||||
From ac25c501c8d97c7520a7c75ae708fb4c43bae035 Mon Sep 17 00:00:00 2001
|
||||
From: Jon Maloy <jmaloy@redhat.com>
|
||||
Date: Tue, 13 Feb 2024 16:30:10 -0500
|
||||
Subject: [PATCH 12/17] SecurityPkg: DxeTpmMeasureBootLib: SECURITY PATCH
|
||||
4117/4118 symbol rename
|
||||
|
||||
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-MergeRequest: 44: edk2: heap buffer overflow in Tcg2MeasureGptTable()
|
||||
RH-Jira: RHEL-21154 RHEL-21156
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [12/13] 6ef41050fb68f984a5ae6104ccc102afb5290f9f (jmaloy/jons_fork)
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-21156
|
||||
CVE: CVE-2022-36764
|
||||
Upstream: Merged
|
||||
|
||||
commit 326db0c9072004dea89427ea3a44393a84966f2b
|
||||
Author: Doug Flick <dougflick@microsoft.com>
|
||||
Date: Wed Jan 17 14:47:21 2024 -0800
|
||||
|
||||
SecurityPkg: DxeTpmMeasureBootLib: SECURITY PATCH 4117/4118 symbol rename
|
||||
|
||||
Updates the sanitation function names to be lib unique names
|
||||
|
||||
Cc: Jiewen Yao <jiewen.yao@intel.com>
|
||||
Cc: Rahul Kumar <rahul1.kumar@intel.com>
|
||||
|
||||
Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
|
||||
Message-Id: <355aa846a99ca6ac0f7574cf5982661da0d9fea6.1705529990.git.doug.edk2@gmail.com>
|
||||
Reviewed-by: Jiewen Yao <Jiewen.yao@intel.com>
|
||||
|
||||
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
|
||||
---
|
||||
.../DxeTpmMeasureBootLib.c | 8 +++---
|
||||
.../DxeTpmMeasureBootLibSanitization.c | 10 +++----
|
||||
.../DxeTpmMeasureBootLibSanitization.h | 8 +++---
|
||||
.../DxeTpmMeasureBootLibSanitizationTest.c | 26 +++++++++----------
|
||||
4 files changed, 26 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c
|
||||
index 1598015176..c39018d7e4 100644
|
||||
--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c
|
||||
+++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c
|
||||
@@ -171,7 +171,7 @@ TcgMeasureGptTable (
|
||||
BlockIo->Media->BlockSize,
|
||||
(UINT8 *)PrimaryHeader
|
||||
);
|
||||
- if (EFI_ERROR (Status) || EFI_ERROR (SanitizeEfiPartitionTableHeader (PrimaryHeader, BlockIo))) {
|
||||
+ if (EFI_ERROR (Status) || EFI_ERROR (TpmSanitizeEfiPartitionTableHeader (PrimaryHeader, BlockIo))) {
|
||||
DEBUG ((DEBUG_ERROR, "Failed to read Partition Table Header or invalid Partition Table Header!\n"));
|
||||
FreePool (PrimaryHeader);
|
||||
return EFI_DEVICE_ERROR;
|
||||
@@ -179,7 +179,7 @@ TcgMeasureGptTable (
|
||||
//
|
||||
// Read the partition entry.
|
||||
//
|
||||
- Status = SanitizePrimaryHeaderAllocationSize (PrimaryHeader, &AllocSize);
|
||||
+ Status = TpmSanitizePrimaryHeaderAllocationSize (PrimaryHeader, &AllocSize);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (PrimaryHeader);
|
||||
return EFI_DEVICE_ERROR;
|
||||
@@ -218,7 +218,7 @@ TcgMeasureGptTable (
|
||||
//
|
||||
// Prepare Data for Measurement
|
||||
//
|
||||
- Status = SanitizePrimaryHeaderGptEventSize (PrimaryHeader, NumberOfPartition, &EventSize);
|
||||
+ Status = TpmSanitizePrimaryHeaderGptEventSize (PrimaryHeader, NumberOfPartition, &EventSize);
|
||||
TcgEvent = (TCG_PCR_EVENT *)AllocateZeroPool (EventSize);
|
||||
if (TcgEvent == NULL) {
|
||||
FreePool (PrimaryHeader);
|
||||
@@ -344,7 +344,7 @@ TcgMeasurePeImage (
|
||||
|
||||
// Determine destination PCR by BootPolicy
|
||||
//
|
||||
- Status = SanitizePeImageEventSize (FilePathSize, &EventSize);
|
||||
+ Status = TpmSanitizePeImageEventSize (FilePathSize, &EventSize);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c
|
||||
index bcf8c6de6f..7f17af56cd 100644
|
||||
--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c
|
||||
+++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/** @file
|
||||
- The library instance provides security service of TPM2 measure boot and
|
||||
+ The library instance provides security service of TPM measure boot and
|
||||
Confidential Computing (CC) measure boot.
|
||||
|
||||
Caution: This file requires additional review when modified.
|
||||
@@ -63,7 +63,7 @@
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
-SanitizeEfiPartitionTableHeader (
|
||||
+TpmSanitizeEfiPartitionTableHeader (
|
||||
IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader,
|
||||
IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo
|
||||
)
|
||||
@@ -145,7 +145,7 @@ SanitizeEfiPartitionTableHeader (
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
-SanitizePrimaryHeaderAllocationSize (
|
||||
+TpmSanitizePrimaryHeaderAllocationSize (
|
||||
IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader,
|
||||
OUT UINT32 *AllocationSize
|
||||
)
|
||||
@@ -194,7 +194,7 @@ SanitizePrimaryHeaderAllocationSize (
|
||||
One of the passed parameters was invalid.
|
||||
**/
|
||||
EFI_STATUS
|
||||
-SanitizePrimaryHeaderGptEventSize (
|
||||
+TpmSanitizePrimaryHeaderGptEventSize (
|
||||
IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader,
|
||||
IN UINTN NumberOfPartition,
|
||||
OUT UINT32 *EventSize
|
||||
@@ -258,7 +258,7 @@ SanitizePrimaryHeaderGptEventSize (
|
||||
One of the passed parameters was invalid.
|
||||
**/
|
||||
EFI_STATUS
|
||||
-SanitizePeImageEventSize (
|
||||
+TpmSanitizePeImageEventSize (
|
||||
IN UINT32 FilePathSize,
|
||||
OUT UINT32 *EventSize
|
||||
)
|
||||
diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h
|
||||
index 2248495813..db6e9c3752 100644
|
||||
--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h
|
||||
+++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h
|
||||
@@ -53,7 +53,7 @@
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
-SanitizeEfiPartitionTableHeader (
|
||||
+TpmSanitizeEfiPartitionTableHeader (
|
||||
IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader,
|
||||
IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo
|
||||
);
|
||||
@@ -77,7 +77,7 @@ SanitizeEfiPartitionTableHeader (
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
-SanitizePrimaryHeaderAllocationSize (
|
||||
+TpmSanitizePrimaryHeaderAllocationSize (
|
||||
IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader,
|
||||
OUT UINT32 *AllocationSize
|
||||
);
|
||||
@@ -105,7 +105,7 @@ SanitizePrimaryHeaderAllocationSize (
|
||||
One of the passed parameters was invalid.
|
||||
**/
|
||||
EFI_STATUS
|
||||
-SanitizePrimaryHeaderGptEventSize (
|
||||
+TpmSanitizePrimaryHeaderGptEventSize (
|
||||
IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader,
|
||||
IN UINTN NumberOfPartition,
|
||||
OUT UINT32 *EventSize
|
||||
@@ -129,7 +129,7 @@ SanitizePrimaryHeaderGptEventSize (
|
||||
One of the passed parameters was invalid.
|
||||
**/
|
||||
EFI_STATUS
|
||||
-SanitizePeImageEventSize (
|
||||
+TpmSanitizePeImageEventSize (
|
||||
IN UINT32 FilePathSize,
|
||||
OUT UINT32 *EventSize
|
||||
);
|
||||
diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c
|
||||
index c41498be45..de1740af41 100644
|
||||
--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c
|
||||
+++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c
|
||||
@@ -83,27 +83,27 @@ TestSanitizeEfiPartitionTableHeader (
|
||||
PrimaryHeader.Header.CRC32 = CalculateCrc32 ((UINT8 *)&PrimaryHeader, PrimaryHeader.Header.HeaderSize);
|
||||
|
||||
// Test that a normal PrimaryHeader passes validation
|
||||
- Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo);
|
||||
+ Status = TpmSanitizeEfiPartitionTableHeader (&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);
|
||||
+ Status = TpmSanitizeEfiPartitionTableHeader (&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);
|
||||
+ Status = TpmSanitizeEfiPartitionTableHeader (&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);
|
||||
+ Status = TpmSanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo);
|
||||
UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR);
|
||||
|
||||
DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));
|
||||
@@ -136,7 +136,7 @@ TestSanitizePrimaryHeaderAllocationSize (
|
||||
PrimaryHeader.NumberOfPartitionEntries = 5;
|
||||
PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;
|
||||
|
||||
- Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);
|
||||
+ Status = TpmSanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);
|
||||
UT_ASSERT_NOT_EFI_ERROR (Status);
|
||||
|
||||
// Test that the allocation size is correct compared to the existing logic
|
||||
@@ -145,19 +145,19 @@ TestSanitizePrimaryHeaderAllocationSize (
|
||||
// Test that an overflow is detected
|
||||
PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32;
|
||||
PrimaryHeader.SizeOfPartitionEntry = 5;
|
||||
- Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);
|
||||
+ Status = TpmSanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);
|
||||
UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
|
||||
|
||||
// Test the inverse
|
||||
PrimaryHeader.NumberOfPartitionEntries = 5;
|
||||
PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32;
|
||||
- Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);
|
||||
+ Status = TpmSanitizePrimaryHeaderAllocationSize (&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);
|
||||
+ Status = TpmSanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);
|
||||
UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
|
||||
|
||||
DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));
|
||||
@@ -195,7 +195,7 @@ TestSanitizePrimaryHeaderGptEventSize (
|
||||
NumberOfPartition = 13;
|
||||
|
||||
// that the primary event size is correct
|
||||
- Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize);
|
||||
+ Status = TpmSanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize);
|
||||
UT_ASSERT_NOT_EFI_ERROR (Status);
|
||||
|
||||
// Calculate the existing logic event size
|
||||
@@ -206,12 +206,12 @@ TestSanitizePrimaryHeaderGptEventSize (
|
||||
UT_ASSERT_EQUAL (EventSize, ExistingLogicEventSize);
|
||||
|
||||
// Tests that the primary event size may not overflow
|
||||
- Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, MAX_UINT32, &EventSize);
|
||||
+ Status = TpmSanitizePrimaryHeaderGptEventSize (&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);
|
||||
+ Status = TpmSanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize);
|
||||
UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
|
||||
|
||||
DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));
|
||||
@@ -269,7 +269,7 @@ TestSanitizePeImageEventSize (
|
||||
FilePathSize = 255;
|
||||
|
||||
// Test that a normal PE image passes validation
|
||||
- Status = SanitizePeImageEventSize (FilePathSize, &EventSize);
|
||||
+ Status = TpmSanitizePeImageEventSize (FilePathSize, &EventSize);
|
||||
if (EFI_ERROR (Status)) {
|
||||
UT_LOG_ERROR ("SanitizePeImageEventSize failed with %r\n", Status);
|
||||
goto Exit;
|
||||
@@ -285,7 +285,7 @@ TestSanitizePeImageEventSize (
|
||||
}
|
||||
|
||||
// Test that the event size may not overflow
|
||||
- Status = SanitizePeImageEventSize (MAX_UINT32, &EventSize);
|
||||
+ Status = TpmSanitizePeImageEventSize (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;
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,960 @@
|
||||
From cb36d95002013ae8d4e5120383cd756a2a6c4124 Mon Sep 17 00:00:00 2001
|
||||
From: Jon Maloy <jmaloy@redhat.com>
|
||||
Date: Wed, 17 Jan 2024 12:20:52 -0500
|
||||
Subject: [PATCH 07/17] SecurityPkg: DxeTpmMeasureBootLib: SECURITY PATCH 4117
|
||||
- CVE 2022-36763
|
||||
|
||||
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-MergeRequest: 44: edk2: heap buffer overflow in Tcg2MeasureGptTable()
|
||||
RH-Jira: RHEL-21154 RHEL-21156
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [7/13] f5a5d2b0a33dc1efdb83e501eda2716df0e904a0 (jmaloy/jons_fork)
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-21154
|
||||
CVE: CVE-2022-36763
|
||||
Upstream: Merged
|
||||
Conflicts: We get function definiton clash for the following three functions:
|
||||
- SanitizeEfiPartitionTableHeader()
|
||||
- SanitizePrimaryHeaderAllocationSize()
|
||||
- SanitizePrimaryHeaderGptEventSize()
|
||||
Those are are defined both in
|
||||
- SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitazion.c
|
||||
and
|
||||
- SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitazion.c
|
||||
Closer investigation reveals that they are identical in functionality (although
|
||||
not in comment style).
|
||||
I chose to leave them as is now, meaning that this package will be
|
||||
unbuildable until I add a commit renaming these symbols later in
|
||||
this series.
|
||||
|
||||
commit 4776a1b39ee08fc45c70c1eab5a0195f325000d3
|
||||
Author: Douglas Flick [MSFT] <doug.edk2@gmail.com>
|
||||
Date: Fri Jan 12 02:16:02 2024 +0800
|
||||
|
||||
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>
|
||||
|
||||
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
|
||||
---
|
||||
.../DxeTpmMeasureBootLib.c | 74 +++--
|
||||
.../DxeTpmMeasureBootLib.inf | 4 +-
|
||||
.../DxeTpmMeasureBootLibSanitization.c | 242 ++++++++++++++
|
||||
.../DxeTpmMeasureBootLibSanitization.h | 114 +++++++
|
||||
.../DxeTpmMeasureBootLibSanitizationTest.c | 301 ++++++++++++++++++
|
||||
...eTpmMeasureBootLibSanitizationTestHost.inf | 28 ++
|
||||
SecurityPkg/SecurityPkg.ci.yaml | 1 +
|
||||
SecurityPkg/Test/SecurityPkgHostTest.dsc | 1 +
|
||||
8 files changed, 734 insertions(+), 31 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 27c0ea48ca..d44422dee8 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.
|
||||
//
|
||||
@@ -123,19 +127,22 @@ TcgMeasureGptTable (
|
||||
IN EFI_HANDLE GptHandle
|
||||
)
|
||||
{
|
||||
- EFI_STATUS Status;
|
||||
- EFI_BLOCK_IO_PROTOCOL *BlockIo;
|
||||
- EFI_DISK_IO_PROTOCOL *DiskIo;
|
||||
- EFI_PARTITION_TABLE_HEADER *PrimaryHeader;
|
||||
- EFI_PARTITION_ENTRY *PartitionEntry;
|
||||
- UINT8 *EntryPtr;
|
||||
- UINTN NumberOfPartition;
|
||||
- UINT32 Index;
|
||||
- TCG_PCR_EVENT *TcgEvent;
|
||||
- EFI_GPT_DATA *GptData;
|
||||
- UINT32 EventSize;
|
||||
- UINT32 EventNumber;
|
||||
- EFI_PHYSICAL_ADDRESS EventLogLastEntry;
|
||||
+ EFI_STATUS Status;
|
||||
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
|
||||
+ EFI_DISK_IO_PROTOCOL *DiskIo;
|
||||
+ EFI_PARTITION_TABLE_HEADER *PrimaryHeader;
|
||||
+ EFI_PARTITION_ENTRY *PartitionEntry;
|
||||
+ UINT8 *EntryPtr;
|
||||
+ UINTN NumberOfPartition;
|
||||
+ UINT32 Index;
|
||||
+ TCG_PCR_EVENT *TcgEvent;
|
||||
+ EFI_GPT_DATA *GptData;
|
||||
+ UINT32 EventSize;
|
||||
+ UINT32 EventNumber;
|
||||
+ EFI_PHYSICAL_ADDRESS EventLogLastEntry;
|
||||
+ UINT32 AllocSize;
|
||||
+
|
||||
+ GptData = NULL;
|
||||
|
||||
if (mMeasureGptCount > 0) {
|
||||
return EFI_SUCCESS;
|
||||
@@ -163,15 +170,21 @@ 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;
|
||||
}
|
||||
//
|
||||
// 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;
|
||||
@@ -179,8 +192,8 @@ TcgMeasureGptTable (
|
||||
Status = DiskIo->ReadDisk (
|
||||
DiskIo,
|
||||
BlockIo->Media->MediaId,
|
||||
- MultU64x32(PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),
|
||||
- PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry,
|
||||
+ MultU64x32 (PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),
|
||||
+ AllocSize,
|
||||
EntryPtr
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
@@ -204,19 +217,18 @@ 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);
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
- TcgEvent->PCRIndex = 5;
|
||||
- TcgEvent->EventType = EV_EFI_GPT_EVENT;
|
||||
- TcgEvent->EventSize = EventSize;
|
||||
- GptData = (EFI_GPT_DATA *) TcgEvent->Event;
|
||||
+ TcgEvent->PCRIndex = 5;
|
||||
+ TcgEvent->EventType = EV_EFI_GPT_EVENT;
|
||||
+ TcgEvent->EventSize = EventSize - sizeof (TCG_PCR_EVENT_HDR);
|
||||
+ GptData = (EFI_GPT_DATA *)TcgEvent->Event;
|
||||
|
||||
//
|
||||
// Copy the EFI_PARTITION_TABLE_HEADER and NumberOfPartition
|
||||
@@ -354,11 +366,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..37cd3ed0ea
|
||||
--- /dev/null
|
||||
+++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c
|
||||
@@ -0,0 +1,242 @@
|
||||
+/** @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 aa8496d6d9..26865cb15a 100644
|
||||
--- a/SecurityPkg/SecurityPkg.ci.yaml
|
||||
+++ b/SecurityPkg/SecurityPkg.ci.yaml
|
||||
@@ -17,6 +17,7 @@
|
||||
"ExceptionList": [
|
||||
"8005", "gRT",
|
||||
"8001", "DxeTpm2MeasureBootLibUnitTestMain",
|
||||
+ "8001", "DxeTpmMeasureBootLibUnitTestMain"
|
||||
],
|
||||
## Both file path and directory path are accepted.
|
||||
"IgnoreFiles": [
|
||||
diff --git a/SecurityPkg/Test/SecurityPkgHostTest.dsc b/SecurityPkg/Test/SecurityPkgHostTest.dsc
|
||||
index 788c1ab6fe..1655e573ea 100644
|
||||
--- a/SecurityPkg/Test/SecurityPkgHostTest.dsc
|
||||
+++ b/SecurityPkg/Test/SecurityPkgHostTest.dsc
|
||||
@@ -27,6 +27,7 @@
|
||||
SecurityPkg/Library/SecureBootVariableLib/UnitTest/MockUefiLib.inf
|
||||
SecurityPkg/Test/Mock/Library/GoogleTest/MockPlatformPKProtectionLib/MockPlatformPKProtectionLib.inf
|
||||
SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTestHost.inf
|
||||
+ SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTestHost.inf
|
||||
|
||||
#
|
||||
# Build SecurityPkg HOST_APPLICATION Tests
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,307 @@
|
||||
From f6f72373630d901f331df719a0fb55e8f1143c4f Mon Sep 17 00:00:00 2001
|
||||
From: Jon Maloy <jmaloy@redhat.com>
|
||||
Date: Wed, 7 Feb 2024 15:43:10 -0500
|
||||
Subject: [PATCH 10/17] SecurityPkg: DxeTpmMeasureBootLib: SECURITY PATCH 4118
|
||||
- CVE 2022-36764
|
||||
|
||||
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-MergeRequest: 44: edk2: heap buffer overflow in Tcg2MeasureGptTable()
|
||||
RH-Jira: RHEL-21154 RHEL-21156
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [10/13] 5ed702e16f390c79d1abb0ec0b04d886e0094c0b (jmaloy/jons_fork)
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-21156
|
||||
CVE: CVE-2022-36764
|
||||
Upstream: Merged
|
||||
Conflicts: We get function definiton clash for the following three functions:
|
||||
- SanitizePeImageEventSize()
|
||||
This is defined both in
|
||||
- SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitazion.c
|
||||
and
|
||||
- SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitazion.c
|
||||
Closer investigation reveals that they are identical in functionality (although
|
||||
not in comment style).
|
||||
I chose to leave them as is now, meaning that this package will be
|
||||
unbuildable until I add a commit renaming these symbols later in
|
||||
this series.
|
||||
|
||||
commit 0d341c01eeabe0ab5e76693b36e728b8f538a40e
|
||||
Author: Douglas Flick [MSFT] <doug.edk2@gmail.com>
|
||||
Date: Fri Jan 12 02:16:05 2024 +0800
|
||||
|
||||
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>
|
||||
|
||||
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
|
||||
---
|
||||
.../DxeTpmMeasureBootLib.c | 17 ++--
|
||||
.../DxeTpmMeasureBootLibSanitization.c | 44 +++++++++
|
||||
.../DxeTpmMeasureBootLibSanitization.h | 23 +++++
|
||||
.../DxeTpmMeasureBootLibSanitizationTest.c | 98 +++++++++++++++++--
|
||||
4 files changed, 170 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c
|
||||
index d44422dee8..1598015176 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
|
||||
@@ -338,19 +339,23 @@ TcgMeasurePeImage (
|
||||
ImageLoad = NULL;
|
||||
SectionHeader = NULL;
|
||||
Sha1Ctx = NULL;
|
||||
- FilePathSize = (UINT32) GetDevicePathSize (FilePath);
|
||||
+ 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;
|
||||
- ImageLoad = (EFI_IMAGE_LOAD_EVENT *) TcgEvent->Event;
|
||||
+ TcgEvent->EventSize = EventSize - sizeof (TCG_PCR_EVENT_HDR);
|
||||
+ ImageLoad = (EFI_IMAGE_LOAD_EVENT *)TcgEvent->Event;
|
||||
|
||||
switch (ImageType) {
|
||||
case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:
|
||||
diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c
|
||||
index 37cd3ed0ea..bcf8c6de6f 100644
|
||||
--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c
|
||||
+++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c
|
||||
@@ -240,3 +240,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.41.0
|
||||
|
@ -0,0 +1,584 @@
|
||||
From e138f66708415704ad1133938c0dce5243795656 Mon Sep 17 00:00:00 2001
|
||||
From: Jon Maloy <jmaloy@redhat.com>
|
||||
Date: Tue, 13 Feb 2024 16:30:10 -0500
|
||||
Subject: [PATCH 04/17] SecurityPkg: Support CcMeasurementProtocol in
|
||||
DxeTpm2MeasureBootLib
|
||||
|
||||
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-MergeRequest: 44: edk2: heap buffer overflow in Tcg2MeasureGptTable()
|
||||
RH-Jira: RHEL-21154 RHEL-21156
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [4/13] 8038fb605dbdaccfd40cb9d9d56db559ee9df639 (jmaloy/jons_fork)
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-21154
|
||||
CVE: CVE-2022-36763
|
||||
Upstream: Merged
|
||||
Conflicts: Only cosmetic, due to the uncrustify changes made
|
||||
in the newer version.
|
||||
|
||||
commit a124cd4ef92a349a6c823ea6701fcfd3a17db255
|
||||
Author: Min Xu <min.m.xu@intel.com>
|
||||
Date: Sat Dec 11 21:08:41 2021 +0800
|
||||
|
||||
SecurityPkg: Support CcMeasurementProtocol in DxeTpm2MeasureBootLib
|
||||
|
||||
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3625
|
||||
|
||||
DxeTpm2MeasureBootLib supports TPM2 based measure boot. After
|
||||
CcMeasurementProtocol is introduced, CC based measure boot needs to
|
||||
be supported in DxeTpm2MeasureBootLib as well.
|
||||
|
||||
There are 2 major changes in this commit.
|
||||
|
||||
1. A platform should have only one RTS/RTR. Only one of (virtual)TPM1.2,
|
||||
(virtual)TPM2.0 and CC MR exists. Then only one TCG_SERVICE_PROTOCOL,
|
||||
TCG2_PROTOCOL, CC_MEASUREMENT_PROTOCOL is exposed. In this library when
|
||||
do measure boot only one of TCG2_PROTOCOL / CC_MEASUREMENT_PROTOCOL
|
||||
will be called. MEASURE_BOOT_PROTOCOLS is defined to store the instances
|
||||
of TCG2 protocol and CC Measurement protocol.
|
||||
|
||||
2. CcEvent is similar to Tcg2Event except the MrIndex and PcrIndex.
|
||||
So in the code Tcg2Event will be first created and intialized. If
|
||||
CcMeasurementProtocol is called to do the measure boot, then CcEvent
|
||||
points to Tcg2Event and the MrIndex is adjusted.
|
||||
|
||||
Cc: Michael D Kinney <michael.d.kinney@intel.com>
|
||||
Cc: Liming Gao <gaoliming@byosoft.com.cn>
|
||||
Cc: Zhiguang Liu <zhiguang.liu@intel.com>
|
||||
Cc: Jiewen Yao <jiewen.yao@intel.com>
|
||||
Cc: Jian J Wang <jian.j.wang@intel.com>
|
||||
Cc: Sami Mujawar <sami.mujawar@arm.com>
|
||||
Cc: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>
|
||||
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
|
||||
Signed-off-by: Min Xu <min.m.xu@intel.com>
|
||||
|
||||
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
|
||||
---
|
||||
.../DxeTpm2MeasureBootLib.c | 347 ++++++++++++++----
|
||||
.../DxeTpm2MeasureBootLib.inf | 3 +-
|
||||
2 files changed, 271 insertions(+), 79 deletions(-)
|
||||
|
||||
diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c
|
||||
index 95682ac567..7abacdbc0a 100644
|
||||
--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c
|
||||
+++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c
|
||||
@@ -1,5 +1,6 @@
|
||||
/** @file
|
||||
- The library instance provides security service of TPM2 measure boot.
|
||||
+ 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.
|
||||
@@ -41,6 +42,12 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#include <Library/PeCoffLib.h>
|
||||
#include <Library/SecurityManagementLib.h>
|
||||
#include <Library/HobLib.h>
|
||||
+#include <Protocol/CcMeasurement.h>
|
||||
+
|
||||
+typedef struct {
|
||||
+ EFI_TCG2_PROTOCOL *Tcg2Protocol;
|
||||
+ EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol;
|
||||
+} MEASURE_BOOT_PROTOCOLS;
|
||||
|
||||
//
|
||||
// Flag to check GPT partition. It only need be measured once.
|
||||
@@ -109,7 +116,7 @@ DxeTpm2MeasureBootLibImageRead (
|
||||
Caution: This function may receive untrusted input.
|
||||
The GPT partition table is external input, so this function should parse partition data carefully.
|
||||
|
||||
- @param Tcg2Protocol Pointer to the located TCG2 protocol instance.
|
||||
+ @param MeasureBootProtocols Pointer to the located MeasureBoot protocol instances (i.e. TCG2/CC protocol).
|
||||
@param GptHandle Handle that GPT partition was installed.
|
||||
|
||||
@retval EFI_SUCCESS Successfully measure GPT table.
|
||||
@@ -121,26 +128,48 @@ DxeTpm2MeasureBootLibImageRead (
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcg2MeasureGptTable (
|
||||
- IN EFI_TCG2_PROTOCOL *Tcg2Protocol,
|
||||
- IN EFI_HANDLE GptHandle
|
||||
+ IN MEASURE_BOOT_PROTOCOLS *MeasureBootProtocols,
|
||||
+ IN EFI_HANDLE GptHandle
|
||||
)
|
||||
{
|
||||
- EFI_STATUS Status;
|
||||
- EFI_BLOCK_IO_PROTOCOL *BlockIo;
|
||||
- EFI_DISK_IO_PROTOCOL *DiskIo;
|
||||
- EFI_PARTITION_TABLE_HEADER *PrimaryHeader;
|
||||
- EFI_PARTITION_ENTRY *PartitionEntry;
|
||||
- UINT8 *EntryPtr;
|
||||
- UINTN NumberOfPartition;
|
||||
- UINT32 Index;
|
||||
- EFI_TCG2_EVENT *Tcg2Event;
|
||||
- EFI_GPT_DATA *GptData;
|
||||
- UINT32 EventSize;
|
||||
+ EFI_STATUS Status;
|
||||
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
|
||||
+ EFI_DISK_IO_PROTOCOL *DiskIo;
|
||||
+ EFI_PARTITION_TABLE_HEADER *PrimaryHeader;
|
||||
+ EFI_PARTITION_ENTRY *PartitionEntry;
|
||||
+ UINT8 *EntryPtr;
|
||||
+ UINTN NumberOfPartition;
|
||||
+ UINT32 Index;
|
||||
+ UINT8 *EventPtr;
|
||||
+ EFI_TCG2_EVENT *Tcg2Event;
|
||||
+ EFI_CC_EVENT *CcEvent;
|
||||
+ EFI_GPT_DATA *GptData;
|
||||
+ UINT32 EventSize;
|
||||
+ EFI_TCG2_PROTOCOL *Tcg2Protocol;
|
||||
+ EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol;
|
||||
+ EFI_CC_MR_INDEX MrIndex;
|
||||
|
||||
if (mTcg2MeasureGptCount > 0) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
+ PrimaryHeader = NULL;
|
||||
+ EntryPtr = NULL;
|
||||
+ EventPtr = NULL;
|
||||
+
|
||||
+ Tcg2Protocol = MeasureBootProtocols->Tcg2Protocol;
|
||||
+ CcProtocol = MeasureBootProtocols->CcProtocol;
|
||||
+
|
||||
+ if ((Tcg2Protocol == NULL) && (CcProtocol == NULL)) {
|
||||
+ ASSERT (FALSE);
|
||||
+ return EFI_UNSUPPORTED;
|
||||
+ }
|
||||
+
|
||||
+ if (sizeof (EFI_CC_EVENT) != sizeof (EFI_TCG2_EVENT)) {
|
||||
+ ASSERT (FALSE);
|
||||
+ return EFI_UNSUPPORTED;
|
||||
+ }
|
||||
+
|
||||
Status = gBS->HandleProtocol (GptHandle, &gEfiBlockIoProtocolGuid, (VOID**)&BlockIo);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
@@ -168,6 +197,16 @@ Tcg2MeasureGptTable (
|
||||
FreePool (PrimaryHeader);
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
+
|
||||
+ //
|
||||
+ // PrimaryHeader->SizeOfPartitionEntry should not be zero
|
||||
+ //
|
||||
+ if (PrimaryHeader->SizeOfPartitionEntry == 0) {
|
||||
+ DEBUG ((DEBUG_ERROR, "SizeOfPartitionEntry should not be zero!\n"));
|
||||
+ FreePool (PrimaryHeader);
|
||||
+ return EFI_BAD_BUFFER_SIZE;
|
||||
+ }
|
||||
+
|
||||
//
|
||||
// Read the partition entry.
|
||||
//
|
||||
@@ -202,11 +241,17 @@ Tcg2MeasureGptTable (
|
||||
}
|
||||
|
||||
//
|
||||
- // Prepare Data for Measurement
|
||||
+ // Prepare Data for Measurement (CcProtocol and Tcg2Protocol)
|
||||
//
|
||||
EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions)
|
||||
+ NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry);
|
||||
- Tcg2Event = (EFI_TCG2_EVENT *) AllocateZeroPool (EventSize + sizeof (EFI_TCG2_EVENT) - sizeof(Tcg2Event->Event));
|
||||
+ EventPtr = (UINT8 *)AllocateZeroPool (EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event));
|
||||
+ if (EventPtr == NULL) {
|
||||
+ Status = EFI_OUT_OF_RESOURCES;
|
||||
+ goto Exit;
|
||||
+ }
|
||||
+
|
||||
+ Tcg2Event = (EFI_TCG2_EVENT *)EventPtr;
|
||||
if (Tcg2Event == NULL) {
|
||||
FreePool (PrimaryHeader);
|
||||
FreePool (EntryPtr);
|
||||
@@ -243,22 +288,66 @@ Tcg2MeasureGptTable (
|
||||
}
|
||||
|
||||
//
|
||||
- // Measure the GPT data
|
||||
+ // Only one of TCG2_PROTOCOL or CC_MEASUREMENT_PROTOCOL is exposed.
|
||||
+ // So Measure the GPT data with one of the protocol.
|
||||
//
|
||||
- Status = Tcg2Protocol->HashLogExtendEvent (
|
||||
- Tcg2Protocol,
|
||||
- 0,
|
||||
- (EFI_PHYSICAL_ADDRESS) (UINTN) (VOID *) GptData,
|
||||
- (UINT64) EventSize,
|
||||
- Tcg2Event
|
||||
- );
|
||||
- if (!EFI_ERROR (Status)) {
|
||||
- mTcg2MeasureGptCount++;
|
||||
+ if (CcProtocol != NULL) {
|
||||
+ //
|
||||
+ // EFI_CC_EVENT share the same data structure with EFI_TCG2_EVENT
|
||||
+ // except the MrIndex and PCRIndex in Header.
|
||||
+ // Tcg2Event has been created and initialized before. So only the MrIndex need
|
||||
+ // be adjusted.
|
||||
+ //
|
||||
+ Status = CcProtocol->MapPcrToMrIndex (CcProtocol, Tcg2Event->Header.PCRIndex, &MrIndex);
|
||||
+ if (EFI_ERROR (Status)) {
|
||||
+ DEBUG ((DEBUG_ERROR, "Cannot map PcrIndex(%d) to MrIndex\n", Tcg2Event->Header.PCRIndex));
|
||||
+ goto Exit;
|
||||
+ }
|
||||
+
|
||||
+ CcEvent = (EFI_CC_EVENT *)EventPtr;
|
||||
+ CcEvent->Header.MrIndex = MrIndex;
|
||||
+ Status = CcProtocol->HashLogExtendEvent (
|
||||
+ CcProtocol,
|
||||
+ 0,
|
||||
+ (EFI_PHYSICAL_ADDRESS)(UINTN)(VOID *)GptData,
|
||||
+ (UINT64)EventSize,
|
||||
+ CcEvent
|
||||
+ );
|
||||
+ if (!EFI_ERROR (Status)) {
|
||||
+ mTcg2MeasureGptCount++;
|
||||
+ }
|
||||
+
|
||||
+ DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - Cc MeasureGptTable - %r\n", Status));
|
||||
+ } else if (Tcg2Protocol != NULL) {
|
||||
+ //
|
||||
+ // If Tcg2Protocol is installed, then Measure GPT data with this protocol.
|
||||
+ //
|
||||
+ Status = Tcg2Protocol->HashLogExtendEvent (
|
||||
+ Tcg2Protocol,
|
||||
+ 0,
|
||||
+ (EFI_PHYSICAL_ADDRESS)(UINTN)(VOID *)GptData,
|
||||
+ (UINT64)EventSize,
|
||||
+ Tcg2Event
|
||||
+ );
|
||||
+ if (!EFI_ERROR (Status)) {
|
||||
+ mTcg2MeasureGptCount++;
|
||||
+ }
|
||||
+
|
||||
+ DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - Tcg2 MeasureGptTable - %r\n", Status));
|
||||
}
|
||||
|
||||
- FreePool (PrimaryHeader);
|
||||
- FreePool (EntryPtr);
|
||||
- FreePool (Tcg2Event);
|
||||
+Exit:
|
||||
+ if (PrimaryHeader != NULL) {
|
||||
+ FreePool (PrimaryHeader);
|
||||
+ }
|
||||
+
|
||||
+ if (EntryPtr != NULL) {
|
||||
+ FreePool (EntryPtr);
|
||||
+ }
|
||||
+
|
||||
+ if (EventPtr != NULL) {
|
||||
+ FreePool (EventPtr);
|
||||
+ }
|
||||
|
||||
return Status;
|
||||
}
|
||||
@@ -271,12 +360,12 @@ Tcg2MeasureGptTable (
|
||||
PE/COFF image is external input, so this function will validate its data structure
|
||||
within this image buffer before use.
|
||||
|
||||
- @param[in] Tcg2Protocol Pointer to the located TCG2 protocol instance.
|
||||
- @param[in] ImageAddress Start address of image buffer.
|
||||
- @param[in] ImageSize Image size
|
||||
- @param[in] LinkTimeBase Address that the image is loaded into memory.
|
||||
- @param[in] ImageType Image subsystem type.
|
||||
- @param[in] FilePath File path is corresponding to the input image.
|
||||
+ @param[in] MeasureBootProtocols Pointer to the located MeasureBoot protocol instances.
|
||||
+ @param[in] ImageAddress Start address of image buffer.
|
||||
+ @param[in] ImageSize Image size
|
||||
+ @param[in] LinkTimeBase Address that the image is loaded into memory.
|
||||
+ @param[in] ImageType Image subsystem type.
|
||||
+ @param[in] FilePath File path is corresponding to the input image.
|
||||
|
||||
@retval EFI_SUCCESS Successfully measure image.
|
||||
@retval EFI_OUT_OF_RESOURCES No enough resource to measure image.
|
||||
@@ -287,7 +376,7 @@ Tcg2MeasureGptTable (
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcg2MeasurePeImage (
|
||||
- IN EFI_TCG2_PROTOCOL *Tcg2Protocol,
|
||||
+ IN MEASURE_BOOT_PROTOCOLS *MeasureBootProtocols,
|
||||
IN EFI_PHYSICAL_ADDRESS ImageAddress,
|
||||
IN UINTN ImageSize,
|
||||
IN UINTN LinkTimeBase,
|
||||
@@ -295,26 +384,46 @@ Tcg2MeasurePeImage (
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *FilePath
|
||||
)
|
||||
{
|
||||
- EFI_STATUS Status;
|
||||
- EFI_TCG2_EVENT *Tcg2Event;
|
||||
- EFI_IMAGE_LOAD_EVENT *ImageLoad;
|
||||
- UINT32 FilePathSize;
|
||||
- UINT32 EventSize;
|
||||
+ EFI_STATUS Status;
|
||||
+ EFI_TCG2_EVENT *Tcg2Event;
|
||||
+ EFI_IMAGE_LOAD_EVENT *ImageLoad;
|
||||
+ UINT32 FilePathSize;
|
||||
+ UINT32 EventSize;
|
||||
+ EFI_CC_EVENT *CcEvent;
|
||||
+ EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol;
|
||||
+ EFI_TCG2_PROTOCOL *Tcg2Protocol;
|
||||
+ UINT8 *EventPtr;
|
||||
+ EFI_CC_MR_INDEX MrIndex;
|
||||
+
|
||||
+ Status = EFI_UNSUPPORTED;
|
||||
+ ImageLoad = NULL;
|
||||
+ EventPtr = NULL;
|
||||
+
|
||||
+ Tcg2Protocol = MeasureBootProtocols->Tcg2Protocol;
|
||||
+ CcProtocol = MeasureBootProtocols->CcProtocol;
|
||||
+
|
||||
+ if ((Tcg2Protocol == NULL) && (CcProtocol == NULL)) {
|
||||
+ ASSERT (FALSE);
|
||||
+ return EFI_UNSUPPORTED;
|
||||
+ }
|
||||
+
|
||||
+ if (sizeof (EFI_CC_EVENT) != sizeof (EFI_TCG2_EVENT)) {
|
||||
+ ASSERT (FALSE);
|
||||
+ return EFI_UNSUPPORTED;
|
||||
+ }
|
||||
|
||||
- Status = EFI_UNSUPPORTED;
|
||||
- ImageLoad = NULL;
|
||||
FilePathSize = (UINT32) GetDevicePathSize (FilePath);
|
||||
|
||||
//
|
||||
// Determine destination PCR by BootPolicy
|
||||
//
|
||||
EventSize = sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath) + FilePathSize;
|
||||
- Tcg2Event = AllocateZeroPool (EventSize + sizeof (EFI_TCG2_EVENT) - sizeof(Tcg2Event->Event));
|
||||
- if (Tcg2Event == NULL) {
|
||||
+ EventPtr = AllocateZeroPool (EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event));
|
||||
+ if (EventPtr == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
- Tcg2Event->Size = EventSize + sizeof (EFI_TCG2_EVENT) - sizeof(Tcg2Event->Event);
|
||||
+ Tcg2Event = (EFI_TCG2_EVENT *)EventPtr;
|
||||
Tcg2Event->Header.HeaderSize = sizeof(EFI_TCG2_EVENT_HEADER);
|
||||
Tcg2Event->Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION;
|
||||
ImageLoad = (EFI_IMAGE_LOAD_EVENT *) Tcg2Event->Event;
|
||||
@@ -352,13 +461,35 @@ Tcg2MeasurePeImage (
|
||||
//
|
||||
// Log the PE data
|
||||
//
|
||||
- Status = Tcg2Protocol->HashLogExtendEvent (
|
||||
- Tcg2Protocol,
|
||||
- PE_COFF_IMAGE,
|
||||
- ImageAddress,
|
||||
- ImageSize,
|
||||
- Tcg2Event
|
||||
- );
|
||||
+ if (CcProtocol != NULL) {
|
||||
+ Status = CcProtocol->MapPcrToMrIndex (CcProtocol, Tcg2Event->Header.PCRIndex, &MrIndex);
|
||||
+ if (EFI_ERROR (Status)) {
|
||||
+ DEBUG ((DEBUG_ERROR, "Cannot map PcrIndex(%d) to MrIndex\n", Tcg2Event->Header.PCRIndex));
|
||||
+ goto Finish;
|
||||
+ }
|
||||
+
|
||||
+ CcEvent = (EFI_CC_EVENT *)EventPtr;
|
||||
+ CcEvent->Header.MrIndex = MrIndex;
|
||||
+
|
||||
+ Status = CcProtocol->HashLogExtendEvent (
|
||||
+ CcProtocol,
|
||||
+ PE_COFF_IMAGE,
|
||||
+ ImageAddress,
|
||||
+ ImageSize,
|
||||
+ CcEvent
|
||||
+ );
|
||||
+ DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - Cc MeasurePeImage - %r\n", Status));
|
||||
+ } else if (Tcg2Protocol != NULL) {
|
||||
+ Status = Tcg2Protocol->HashLogExtendEvent (
|
||||
+ Tcg2Protocol,
|
||||
+ PE_COFF_IMAGE,
|
||||
+ ImageAddress,
|
||||
+ ImageSize,
|
||||
+ Tcg2Event
|
||||
+ );
|
||||
+ DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - Tcg2 MeasurePeImage - %r\n", Status));
|
||||
+ }
|
||||
+
|
||||
if (Status == EFI_VOLUME_FULL) {
|
||||
//
|
||||
// Volume full here means the image is hashed and its result is extended to PCR.
|
||||
@@ -369,11 +500,77 @@ Tcg2MeasurePeImage (
|
||||
}
|
||||
|
||||
Finish:
|
||||
- FreePool (Tcg2Event);
|
||||
+ if (EventPtr != NULL) {
|
||||
+ FreePool (EventPtr);
|
||||
+ }
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
+/**
|
||||
+ Get the measure boot protocols.
|
||||
+
|
||||
+ There are 2 measure boot, TCG2 protocol based and Cc measurement protocol based.
|
||||
+
|
||||
+ @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_UNSUPPORTED Measure boot is not supported.
|
||||
+**/
|
||||
+EFI_STATUS
|
||||
+EFIAPI
|
||||
+GetMeasureBootProtocols (
|
||||
+ MEASURE_BOOT_PROTOCOLS *MeasureBootProtocols
|
||||
+ )
|
||||
+{
|
||||
+ EFI_STATUS Status;
|
||||
+ EFI_TCG2_PROTOCOL *Tcg2Protocol;
|
||||
+ EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol;
|
||||
+ EFI_TCG2_BOOT_SERVICE_CAPABILITY Tcg2ProtocolCapability;
|
||||
+ EFI_CC_BOOT_SERVICE_CAPABILITY CcProtocolCapability;
|
||||
+
|
||||
+ CcProtocol = NULL;
|
||||
+ Status = gBS->LocateProtocol (&gEfiCcMeasurementProtocolGuid, NULL, (VOID **)&CcProtocol);
|
||||
+ if (EFI_ERROR (Status)) {
|
||||
+ //
|
||||
+ // Cc Measurement protocol is not installed.
|
||||
+ //
|
||||
+ DEBUG ((DEBUG_VERBOSE, "CcMeasurementProtocol is not installed. - %r\n", Status));
|
||||
+ } else {
|
||||
+ ZeroMem (&CcProtocolCapability, sizeof (CcProtocolCapability));
|
||||
+ CcProtocolCapability.Size = sizeof (CcProtocolCapability);
|
||||
+ Status = CcProtocol->GetCapability (CcProtocol, &CcProtocolCapability);
|
||||
+ if (EFI_ERROR (Status) || (CcProtocolCapability.CcType.Type == EFI_CC_TYPE_NONE)) {
|
||||
+ DEBUG ((DEBUG_ERROR, " CcProtocol->GetCapability returns : %x, %r\n", CcProtocolCapability.CcType.Type, Status));
|
||||
+ CcProtocol = NULL;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ Tcg2Protocol = NULL;
|
||||
+ Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **)&Tcg2Protocol);
|
||||
+ if (EFI_ERROR (Status)) {
|
||||
+ //
|
||||
+ // Tcg2 protocol is not installed. So, TPM2 is not present.
|
||||
+ //
|
||||
+ DEBUG ((DEBUG_VERBOSE, "Tcg2Protocol is not installed. - %r\n", Status));
|
||||
+ } else {
|
||||
+ Tcg2ProtocolCapability.Size = (UINT8)sizeof (Tcg2ProtocolCapability);
|
||||
+ Status = Tcg2Protocol->GetCapability (Tcg2Protocol, &Tcg2ProtocolCapability);
|
||||
+ if (EFI_ERROR (Status) || (!Tcg2ProtocolCapability.TPMPresentFlag)) {
|
||||
+ //
|
||||
+ // TPM device doesn't work or activate.
|
||||
+ //
|
||||
+ DEBUG ((DEBUG_ERROR, "TPMPresentFlag=FALSE %r\n", Status));
|
||||
+ Tcg2Protocol = NULL;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ MeasureBootProtocols->Tcg2Protocol = Tcg2Protocol;
|
||||
+ MeasureBootProtocols->CcProtocol = CcProtocol;
|
||||
+
|
||||
+ return (Tcg2Protocol == NULL && CcProtocol == NULL) ? EFI_UNSUPPORTED : EFI_SUCCESS;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
The security handler is used to abstract platform-specific policy
|
||||
from the DXE core response to an attempt to use a file that returns a
|
||||
@@ -422,9 +619,8 @@ DxeTpm2MeasureBootHandler (
|
||||
IN BOOLEAN BootPolicy
|
||||
)
|
||||
{
|
||||
- EFI_TCG2_PROTOCOL *Tcg2Protocol;
|
||||
+ MEASURE_BOOT_PROTOCOLS MeasureBootProtocols;
|
||||
EFI_STATUS Status;
|
||||
- EFI_TCG2_BOOT_SERVICE_CAPABILITY ProtocolCapability;
|
||||
EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
|
||||
EFI_DEVICE_PATH_PROTOCOL *OrigDevicePathNode;
|
||||
EFI_HANDLE Handle;
|
||||
@@ -435,29 +631,25 @@ DxeTpm2MeasureBootHandler (
|
||||
EFI_PHYSICAL_ADDRESS FvAddress;
|
||||
UINT32 Index;
|
||||
|
||||
- Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &Tcg2Protocol);
|
||||
+ MeasureBootProtocols.Tcg2Protocol = NULL;
|
||||
+ MeasureBootProtocols.CcProtocol = NULL;
|
||||
+
|
||||
+ Status = GetMeasureBootProtocols (&MeasureBootProtocols);
|
||||
+
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
- // Tcg2 protocol is not installed. So, TPM2 is not present.
|
||||
+ // None of Measured boot protocols (Tcg2, Cc) is installed.
|
||||
// Don't do any measurement, and directly return EFI_SUCCESS.
|
||||
//
|
||||
- DEBUG ((DEBUG_VERBOSE, "DxeTpm2MeasureBootHandler - Tcg2 - %r\n", Status));
|
||||
+ DEBUG ((DEBUG_INFO, "None of Tcg2Protocol/CcMeasurementProtocol is installed.\n"));
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
-
|
||||
- ProtocolCapability.Size = (UINT8) sizeof (ProtocolCapability);
|
||||
- Status = Tcg2Protocol->GetCapability (
|
||||
- Tcg2Protocol,
|
||||
- &ProtocolCapability
|
||||
- );
|
||||
- if (EFI_ERROR (Status) || (!ProtocolCapability.TPMPresentFlag)) {
|
||||
- //
|
||||
- // TPM device doesn't work or activate.
|
||||
- //
|
||||
- DEBUG ((DEBUG_ERROR, "DxeTpm2MeasureBootHandler (%r) - TPMPresentFlag - %x\n", Status, ProtocolCapability.TPMPresentFlag));
|
||||
- return EFI_SUCCESS;
|
||||
- }
|
||||
-
|
||||
+ DEBUG ((
|
||||
+ DEBUG_INFO,
|
||||
+ "Tcg2Protocol = %p, CcMeasurementProtocol = %p\n",
|
||||
+ MeasureBootProtocols.Tcg2Protocol,
|
||||
+ MeasureBootProtocols.CcProtocol
|
||||
+ ));
|
||||
//
|
||||
// Copy File Device Path
|
||||
//
|
||||
@@ -502,8 +694,8 @@ DxeTpm2MeasureBootHandler (
|
||||
//
|
||||
// Measure GPT disk.
|
||||
//
|
||||
- Status = Tcg2MeasureGptTable (Tcg2Protocol, Handle);
|
||||
- DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - Tcg2MeasureGptTable - %r\n", Status));
|
||||
+ Status = Tcg2MeasureGptTable (&MeasureBootProtocols, Handle);
|
||||
+
|
||||
if (!EFI_ERROR (Status)) {
|
||||
//
|
||||
// GPT disk check done.
|
||||
@@ -647,14 +839,13 @@ DxeTpm2MeasureBootHandler (
|
||||
// Measure PE image into TPM log.
|
||||
//
|
||||
Status = Tcg2MeasurePeImage (
|
||||
- Tcg2Protocol,
|
||||
+ &MeasureBootProtocols,
|
||||
(EFI_PHYSICAL_ADDRESS) (UINTN) FileBuffer,
|
||||
FileSize,
|
||||
(UINTN) ImageContext.ImageAddress,
|
||||
ImageContext.ImageType,
|
||||
DevicePathNode
|
||||
);
|
||||
- DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - Tcg2MeasurePeImage - %r\n", Status));
|
||||
}
|
||||
|
||||
//
|
||||
diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf
|
||||
index 2506abbe7c..6dca79a20c 100644
|
||||
--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf
|
||||
+++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf
|
||||
@@ -1,5 +1,5 @@
|
||||
## @file
|
||||
-# Provides security service for TPM 2.0 measured boot
|
||||
+# Provides security service for TPM 2.0 measured boot and Confidential Computing measure boot.
|
||||
#
|
||||
# Spec Compliance Info:
|
||||
# "TCG PC Client Platform Firmware Profile Specification for TPM Family 2.0 Level 00 Revision 1.03 v51"
|
||||
@@ -61,6 +61,7 @@
|
||||
|
||||
[Protocols]
|
||||
gEfiTcg2ProtocolGuid ## SOMETIMES_CONSUMES
|
||||
+ gEfiCcMeasurementProtocolGuid ## SOMETIMES_CONSUMES
|
||||
gEfiFirmwareVolumeBlockProtocolGuid ## SOMETIMES_CONSUMES
|
||||
gEfiBlockIoProtocolGuid ## SOMETIMES_CONSUMES
|
||||
gEfiDiskIoProtocolGuid ## SOMETIMES_CONSUMES
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,255 @@
|
||||
From a35a08c5c8d9308ba2b63a15a40e4ddc3e265dbd Mon Sep 17 00:00:00 2001
|
||||
From: Jon Maloy <jmaloy@redhat.com>
|
||||
Date: Tue, 13 Feb 2024 16:30:10 -0500
|
||||
Subject: [PATCH 05/17] SecurityPkg: Support CcMeasurementProtocol in
|
||||
DxeTpmMeasurementLib
|
||||
|
||||
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-MergeRequest: 44: edk2: heap buffer overflow in Tcg2MeasureGptTable()
|
||||
RH-Jira: RHEL-21154 RHEL-21156
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [5/13] fa844740ca589cabb52ae7dfa0dd329315dc168f (jmaloy/jons_fork)
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-21154
|
||||
CVE: CVE-2022-36763
|
||||
Upstream: Merged
|
||||
Conflicts: Only cosmetic, due to the uncrustify changes made
|
||||
in the newer version.
|
||||
|
||||
commit 314ff1dc8c9a9597280b50e44a5c861cb6a58517 (HEAD -> CVE-2022-36763_RHEL-21154_rhel-8.10.0)
|
||||
Author: Min Xu <min.m.xu@intel.com>
|
||||
Date: Sat Dec 11 21:08:42 2021 +0800
|
||||
|
||||
SecurityPkg: Support CcMeasurementProtocol in DxeTpmMeasurementLib
|
||||
|
||||
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3625
|
||||
|
||||
DxeTpmMeasurementLib supports TPM based measurement in DXE phase.
|
||||
After CcMeasurementProtocol is introduced, CC based measurement needs
|
||||
to be supported in DxeTpmMeasurementLib as well.
|
||||
|
||||
A platform should have only one RTS/RTR. Only one of (virtual)TPM1.2,
|
||||
(virtual)TPM2.0 and CC MR exists. Then only one TCG_SERVICE_PROTOCOL,
|
||||
TCG2_PROTOCOL, CC_MEASUREMENT_PROTOCOL is exposed.
|
||||
|
||||
In this library when do measurement only one of above 3 protocols will
|
||||
be called.
|
||||
|
||||
Cc: Michael D Kinney <michael.d.kinney@intel.com>
|
||||
Cc: Liming Gao <gaoliming@byosoft.com.cn>
|
||||
Cc: Zhiguang Liu <zhiguang.liu@intel.com>
|
||||
Cc: Jiewen Yao <jiewen.yao@intel.com>
|
||||
Cc: Jian J Wang <jian.j.wang@intel.com>
|
||||
Cc: Sami Mujawar <sami.mujawar@arm.com>
|
||||
Cc: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>
|
||||
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
|
||||
Signed-off-by: Min Xu <min.m.xu@intel.com>
|
||||
|
||||
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
|
||||
---
|
||||
.../DxeTpmMeasurementLib.c | 122 +++++++++++++++---
|
||||
.../DxeTpmMeasurementLib.inf | 9 +-
|
||||
2 files changed, 111 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.c b/SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.c
|
||||
index 061136ee78..802bc3c3cd 100644
|
||||
--- a/SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.c
|
||||
+++ b/SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.c
|
||||
@@ -1,5 +1,6 @@
|
||||
/** @file
|
||||
- This library is used by other modules to measure data to TPM.
|
||||
+ This library is used by other modules to measure data to TPM and Confidential
|
||||
+ Computing (CC) measure registers.
|
||||
|
||||
Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved. <BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
@@ -19,6 +20,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
#include <Guid/Acpi.h>
|
||||
#include <IndustryStandard/Acpi.h>
|
||||
+#include <Protocol/CcMeasurement.h>
|
||||
|
||||
|
||||
|
||||
@@ -37,6 +39,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
@retval EFI_OUT_OF_RESOURCES Out of memory.
|
||||
@retval EFI_DEVICE_ERROR The operation was unsuccessful.
|
||||
**/
|
||||
+STATIC
|
||||
EFI_STATUS
|
||||
Tpm12MeasureAndLogData (
|
||||
IN UINT32 PcrIndex,
|
||||
@@ -103,6 +106,7 @@ Tpm12MeasureAndLogData (
|
||||
@retval EFI_OUT_OF_RESOURCES Out of memory.
|
||||
@retval EFI_DEVICE_ERROR The operation was unsuccessful.
|
||||
**/
|
||||
+STATIC
|
||||
EFI_STATUS
|
||||
Tpm20MeasureAndLogData (
|
||||
IN UINT32 PcrIndex,
|
||||
@@ -149,6 +153,73 @@ Tpm20MeasureAndLogData (
|
||||
return Status;
|
||||
}
|
||||
|
||||
+/**
|
||||
+ Cc measure and log data, and extend the measurement result into a
|
||||
+ specific CC MR.
|
||||
+
|
||||
+ @param[in] CcProtocol Instance of CC measurement protocol
|
||||
+ @param[in] PcrIndex PCR Index.
|
||||
+ @param[in] EventType Event type.
|
||||
+ @param[in] EventLog Measurement event log.
|
||||
+ @param[in] LogLen Event log length in bytes.
|
||||
+ @param[in] HashData The start of the data buffer to be hashed, extended.
|
||||
+ @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData
|
||||
+
|
||||
+ @retval EFI_SUCCESS Operation completed successfully.
|
||||
+ @retval EFI_UNSUPPORTED CC guest not available.
|
||||
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
|
||||
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.
|
||||
+ @retval EFI_INVALID_PARAMETER The input parameter is invalid.
|
||||
+**/
|
||||
+STATIC
|
||||
+EFI_STATUS
|
||||
+CcMeasureAndLogData (
|
||||
+ IN EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol,
|
||||
+ IN UINT32 PcrIndex,
|
||||
+ IN UINT32 EventType,
|
||||
+ IN VOID *EventLog,
|
||||
+ IN UINT32 LogLen,
|
||||
+ IN VOID *HashData,
|
||||
+ IN UINT64 HashDataLen
|
||||
+ )
|
||||
+{
|
||||
+ EFI_STATUS Status;
|
||||
+ EFI_CC_EVENT *EfiCcEvent;
|
||||
+ EFI_CC_MR_INDEX MrIndex;
|
||||
+
|
||||
+ if (CcProtocol == NULL) {
|
||||
+ return EFI_INVALID_PARAMETER;
|
||||
+ }
|
||||
+
|
||||
+ Status = CcProtocol->MapPcrToMrIndex (CcProtocol, PcrIndex, &MrIndex);
|
||||
+ if (EFI_ERROR (Status)) {
|
||||
+ return Status;
|
||||
+ }
|
||||
+
|
||||
+ EfiCcEvent = (EFI_CC_EVENT *)AllocateZeroPool (LogLen + sizeof (EFI_CC_EVENT));
|
||||
+ if (EfiCcEvent == NULL) {
|
||||
+ return EFI_OUT_OF_RESOURCES;
|
||||
+ }
|
||||
+
|
||||
+ EfiCcEvent->Size = (UINT32)LogLen + sizeof (EFI_CC_EVENT) - sizeof (EfiCcEvent->Event);
|
||||
+ EfiCcEvent->Header.HeaderSize = sizeof (EFI_CC_EVENT_HEADER);
|
||||
+ EfiCcEvent->Header.HeaderVersion = EFI_CC_EVENT_HEADER_VERSION;
|
||||
+ EfiCcEvent->Header.MrIndex = MrIndex;
|
||||
+ EfiCcEvent->Header.EventType = EventType;
|
||||
+ CopyMem (&EfiCcEvent->Event[0], EventLog, LogLen);
|
||||
+
|
||||
+ Status = CcProtocol->HashLogExtendEvent (
|
||||
+ CcProtocol,
|
||||
+ 0,
|
||||
+ (EFI_PHYSICAL_ADDRESS)(UINTN)HashData,
|
||||
+ HashDataLen,
|
||||
+ EfiCcEvent
|
||||
+ );
|
||||
+ FreePool (EfiCcEvent);
|
||||
+
|
||||
+ return Status;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
Tpm measure and log data, and extend the measurement result into a specific PCR.
|
||||
|
||||
@@ -175,25 +246,16 @@ TpmMeasureAndLogData (
|
||||
IN UINT64 HashDataLen
|
||||
)
|
||||
{
|
||||
- EFI_STATUS Status;
|
||||
-
|
||||
- //
|
||||
- // Try to measure using Tpm20 protocol
|
||||
- //
|
||||
- Status = Tpm20MeasureAndLogData(
|
||||
- PcrIndex,
|
||||
- EventType,
|
||||
- EventLog,
|
||||
- LogLen,
|
||||
- HashData,
|
||||
- HashDataLen
|
||||
- );
|
||||
+ EFI_STATUS Status;
|
||||
+ EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol;
|
||||
|
||||
- if (EFI_ERROR (Status)) {
|
||||
+ Status = gBS->LocateProtocol (&gEfiCcMeasurementProtocolGuid, NULL, (VOID **)&CcProtocol);
|
||||
+ if (!EFI_ERROR (Status)) {
|
||||
//
|
||||
- // Try to measure using Tpm1.2 protocol
|
||||
+ // Try to measure using Cc measurement protocol
|
||||
//
|
||||
- Status = Tpm12MeasureAndLogData(
|
||||
+ Status = CcMeasureAndLogData (
|
||||
+ CcProtocol,
|
||||
PcrIndex,
|
||||
EventType,
|
||||
EventLog,
|
||||
@@ -201,6 +263,32 @@ TpmMeasureAndLogData (
|
||||
HashData,
|
||||
HashDataLen
|
||||
);
|
||||
+ } else {
|
||||
+ //
|
||||
+ // Try to measure using Tpm20 protocol
|
||||
+ //
|
||||
+ Status = Tpm20MeasureAndLogData (
|
||||
+ PcrIndex,
|
||||
+ EventType,
|
||||
+ EventLog,
|
||||
+ LogLen,
|
||||
+ HashData,
|
||||
+ HashDataLen
|
||||
+ );
|
||||
+
|
||||
+ if (EFI_ERROR (Status)) {
|
||||
+ //
|
||||
+ // Try to measure using Tpm1.2 protocol
|
||||
+ //
|
||||
+ Status = Tpm12MeasureAndLogData (
|
||||
+ PcrIndex,
|
||||
+ EventType,
|
||||
+ EventLog,
|
||||
+ LogLen,
|
||||
+ HashData,
|
||||
+ HashDataLen
|
||||
+ );
|
||||
+ }
|
||||
}
|
||||
|
||||
return Status;
|
||||
diff --git a/SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf b/SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf
|
||||
index 7d41bc41f9..3af3d4e33b 100644
|
||||
--- a/SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf
|
||||
+++ b/SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf
|
||||
@@ -1,5 +1,7 @@
|
||||
## @file
|
||||
-# Provides TPM measurement functions for TPM1.2 and TPM 2.0
|
||||
+# Provides below measurement functions:
|
||||
+# 1. TPM measurement functions for TPM1.2 and TPM 2.0
|
||||
+# 2. Confidential Computing (CC) measurement functions
|
||||
#
|
||||
# This library provides TpmMeasureAndLogData() to measure and log data, and
|
||||
# extend the measurement result into a specific PCR.
|
||||
@@ -40,5 +42,6 @@
|
||||
UefiBootServicesTableLib
|
||||
|
||||
[Protocols]
|
||||
- gEfiTcgProtocolGuid ## SOMETIMES_CONSUMES
|
||||
- gEfiTcg2ProtocolGuid ## SOMETIMES_CONSUMES
|
||||
+ gEfiTcgProtocolGuid ## SOMETIMES_CONSUMES
|
||||
+ gEfiTcg2ProtocolGuid ## SOMETIMES_CONSUMES
|
||||
+ gEfiCcMeasurementProtocolGuid ## SOMETIMES_CONSUMES
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,84 @@
|
||||
From fa892c7112cfb5aa742f358544da3788a831e431 Mon Sep 17 00:00:00 2001
|
||||
From: Jon Maloy <jmaloy@redhat.com>
|
||||
Date: Tue, 13 Feb 2024 16:30:10 -0500
|
||||
Subject: [PATCH 13/17] SecurityPkg: : Updating SecurityFixes.yaml after symbol
|
||||
rename
|
||||
|
||||
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-MergeRequest: 44: edk2: heap buffer overflow in Tcg2MeasureGptTable()
|
||||
RH-Jira: RHEL-21154 RHEL-21156
|
||||
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||
RH-Commit: [13/13] 3bf59dbb583b67eddb54361781054cc650398309 (jmaloy/jons_fork)
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-21156
|
||||
CVE: CVE-2022-36764
|
||||
Upstream: Merged
|
||||
|
||||
commit 264636d8e6983e0f6dc6be2fca9d84ec81315954
|
||||
Author: Doug Flick <dougflick@microsoft.com>
|
||||
Date: Wed Jan 17 14:47:22 2024 -0800
|
||||
|
||||
SecurityPkg: : Updating SecurityFixes.yaml after symbol rename
|
||||
|
||||
Adding the new commit titles for the symbol renames
|
||||
|
||||
Cc: Jiewen Yao <jiewen.yao@intel.com>
|
||||
Cc: Rahul Kumar <rahul1.kumar@intel.com>
|
||||
|
||||
Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
|
||||
Message-Id: <5e0e851e97459e183420178888d4fcdadc2f1ae1.1705529990.git.doug.edk2@gmail.com>
|
||||
Reviewed-by: Jiewen Yao <Jiewen.yao@intel.com>
|
||||
|
||||
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
|
||||
---
|
||||
SecurityPkg/SecurityFixes.yaml | 31 ++++++++++++++++++++++++++-----
|
||||
1 file changed, 26 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/SecurityPkg/SecurityFixes.yaml b/SecurityPkg/SecurityFixes.yaml
|
||||
index f9e3e7be74..dc1bb83489 100644
|
||||
--- a/SecurityPkg/SecurityFixes.yaml
|
||||
+++ b/SecurityPkg/SecurityFixes.yaml
|
||||
@@ -9,14 +9,35 @@ CVE_2022_36763:
|
||||
- "SecurityPkg: DxeTpm2Measurement: SECURITY PATCH 4117 - CVE 2022-36763"
|
||||
- "SecurityPkg: DxeTpmMeasurement: SECURITY PATCH 4117 - CVE 2022-36763"
|
||||
- "SecurityPkg: : Adding CVE 2022-36763 to SecurityFixes.yaml"
|
||||
+ - "SecurityPkg: DxeTpm2MeasureBootLib: SECURITY PATCH 4117/4118 symbol rename"
|
||||
+ - "SecurityPkg: DxeTpmMeasureBootLib: SECURITY PATCH 4117/4118 symbol rename"
|
||||
+ - "SecurityPkg: : Updating SecurityFixes.yaml after symbol rename"
|
||||
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
|
||||
+ - 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
|
||||
+ - 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"
|
||||
+ - "SecurityPkg: DxeTpm2MeasureBootLib: SECURITY PATCH 4117/4118 symbol rename"
|
||||
+ - "SecurityPkg: DxeTpmMeasureBootLib: SECURITY PATCH 4117/4118 symbol rename"
|
||||
+ - "SecurityPkg: : Updating SecurityFixes.yaml after symbol rename"
|
||||
+ 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.41.0
|
||||
|
@ -0,0 +1,150 @@
|
||||
From 155eceaf831492dcd77172833350072e4156e1c9 Mon Sep 17 00:00:00 2001
|
||||
From: Jon Maloy <jmaloy@redhat.com>
|
||||
Date: Tue, 5 Mar 2024 16:38:49 -0500
|
||||
Subject: [PATCH 2/2] StandaloneMmPkg/Hob: Integer Overflow in CreateHob()
|
||||
|
||||
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-MergeRequest: 66: EmbeddedPkg/Hob: Integer Overflow in CreateHob()
|
||||
RH-Jira: RHEL-21158
|
||||
RH-Acked-by: Oliver Steffen <osteffen@redhat.com>
|
||||
RH-Acked-by: Gerd Hoffmann <None>
|
||||
RH-Commit: [2/2] be7ee11a65a56faec07c249a35940cf9b95b9ec1
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-21158
|
||||
CVE: CVE-2022-36765
|
||||
Upstream: Merged
|
||||
|
||||
commit 9a75b030cf27d2530444e9a2f9f11867f79bf679
|
||||
Author: Gua Guo <gua.guo@intel.com>
|
||||
Date: Thu Jan 11 13:03:26 2024 +0800
|
||||
|
||||
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>
|
||||
|
||||
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
|
||||
---
|
||||
.../Arm/StandaloneMmCoreHobLib.c | 37 ++++++++++++++++++-
|
||||
1 file changed, 36 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/Arm/StandaloneMmCoreHobLib.c b/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/Arm/StandaloneMmCoreHobLib.c
|
||||
index 0ec2d4ad6f..3b13249e33 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;
|
||||
@@ -87,6 +94,10 @@ BuildModuleHob (
|
||||
((ModuleLength & (EFI_PAGE_SIZE - 1)) == 0));
|
||||
|
||||
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;
|
||||
@@ -127,6 +138,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;
|
||||
@@ -164,7 +178,12 @@ BuildGuidHob (
|
||||
//
|
||||
ASSERT (DataLength <= (0xffff - sizeof (EFI_HOB_GUID_TYPE)));
|
||||
|
||||
- Hob = CreateHob (EFI_HOB_TYPE_GUID_EXTENSION, (UINT16) (sizeof (EFI_HOB_GUID_TYPE) + DataLength));
|
||||
+ 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;
|
||||
}
|
||||
@@ -225,6 +244,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;
|
||||
@@ -283,6 +310,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;
|
||||
@@ -318,6 +349,10 @@ BuildMemoryAllocationHob (
|
||||
((Length & (EFI_PAGE_SIZE - 1)) == 0));
|
||||
|
||||
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.39.3
|
||||
|
Loading…
Reference in new issue