From: Chen A Chen <chen.a.chen@intel.com>
To: edk2-devel@lists.01.org
Cc: Chen A Chen <chen.a.chen@intel.com>, Ray Ni <ray.ni@intel.com>,
Eric Dong <eric.dong@intel.com>
Subject: [PATCH 2/2] UefiCpuPkg/Microcode: Add verification logic before parsing payload
Date: Thu, 28 Feb 2019 14:02:52 +0800 [thread overview]
Message-ID: <20190228060252.23944-3-chen.a.chen@intel.com> (raw)
In-Reply-To: <20190228060252.23944-1-chen.a.chen@intel.com>
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1020
The function MicrocodeDetect may receive untrusted input. Add verification
logic to check Microcode Payload Header.
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Chen A Chen <chen.a.chen@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
---
UefiCpuPkg/Library/MpInitLib/Microcode.c | 190 +++++++++++++++++++++----------
1 file changed, 127 insertions(+), 63 deletions(-)
diff --git a/UefiCpuPkg/Library/MpInitLib/Microcode.c b/UefiCpuPkg/Library/MpInitLib/Microcode.c
index 5f9ae22794..1d5e964791 100644
--- a/UefiCpuPkg/Library/MpInitLib/Microcode.c
+++ b/UefiCpuPkg/Library/MpInitLib/Microcode.c
@@ -32,6 +32,69 @@ GetCurrentMicrocodeSignature (
return BiosSignIdMsr.Bits.MicrocodeUpdateSignature;
}
+/**
+ Verify Microcode.
+
+ @param[in] MicrocodeHeader Point to the Microcode payload buffer.
+
+ @retval TRUE Valid payload
+ @retval FALSE Invalid payload
+**/
+BOOLEAN
+VerifyMicrocodeHeader (
+ IN CPU_MICROCODE_HEADER *MicrocodeHeader
+ )
+{
+ UINTN TotalSize;
+ UINTN DataSize;
+
+ if (MicrocodeHeader == NULL) {
+ return FALSE;
+ }
+
+ ///
+ /// Verify Version
+ ///
+ if (MicrocodeHeader->HeaderVersion != 0x1) {
+ return FALSE;
+ }
+ if (MicrocodeHeader->LoaderRevision != 0x1) {
+ return FALSE;
+ }
+
+ ///
+ /// Verify TotalSize
+ ///
+ if (MicrocodeHeader->DataSize == 0) {
+ TotalSize = 2048;
+ } else {
+ TotalSize = MicrocodeHeader->TotalSize;
+ }
+ if (TotalSize <= sizeof (CPU_MICROCODE_HEADER)) {
+ return FALSE;
+ }
+ if ((TotalSize & (SIZE_1KB - 1)) != 0) {
+ return FALSE;
+ }
+
+ ///
+ /// Verify DataSize
+ ///
+ if (MicrocodeHeader->DataSize == 0) {
+ DataSize = 2048 - sizeof (CPU_MICROCODE_HEADER);
+ } else {
+ DataSize = MicrocodeHeader->DataSize;
+ }
+ if (DataSize > TotalSize - sizeof (CPU_MICROCODE_HEADER)) {
+ return FALSE;
+ }
+ if ((DataSize & 0x3) != 0) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
/**
Detect whether specified processor can find matching microcode patch and load it.
@@ -166,6 +229,18 @@ MicrocodeDetect (
//
CorrectMicrocode = FALSE;
+ if (!VerifyMicrocodeHeader (MicrocodeEntryPoint)) {
+ //
+ // It is the padding data between the microcode patches for microcode patches alignment.
+ // Because the microcode patch is the multiple of 1-KByte, the padding data should not
+ // exist if the microcode patch alignment value is not larger than 1-KByte. So, the microcode
+ // alignment value should be larger than 1-KByte. We could skip SIZE_1KB padding data to
+ // find the next possible microcode patch header.
+ //
+ MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + SIZE_1KB);
+ continue;
+ }
+
//
// Save an in-complete CheckSum32 from CheckSum Part1 for common parts.
//
@@ -184,90 +259,79 @@ MicrocodeDetect (
InCompleteCheckSum32 -= MicrocodeEntryPoint->ProcessorFlags;
InCompleteCheckSum32 -= MicrocodeEntryPoint->Checksum;
- if (MicrocodeEntryPoint->HeaderVersion == 0x1) {
+ //
+ // It is the microcode header. It is not the padding data between microcode patches
+ // because the padding data should not include 0x00000001 and it should be the repeated
+ // byte format (like 0xXYXYXYXY....).
+ //
+ if (MicrocodeEntryPoint->ProcessorSignature.Uint32 == Eax.Uint32 &&
+ MicrocodeEntryPoint->UpdateRevision > LatestRevision &&
+ (MicrocodeEntryPoint->ProcessorFlags & (1 << PlatformId))
+ ) {
//
- // It is the microcode header. It is not the padding data between microcode patches
- // because the padding data should not include 0x00000001 and it should be the repeated
- // byte format (like 0xXYXYXYXY....).
+ // Calculate CheckSum Part1.
//
- if (MicrocodeEntryPoint->ProcessorSignature.Uint32 == Eax.Uint32 &&
- MicrocodeEntryPoint->UpdateRevision > LatestRevision &&
- (MicrocodeEntryPoint->ProcessorFlags & (1 << PlatformId))
- ) {
+ CheckSum32 = InCompleteCheckSum32;
+ CheckSum32 += MicrocodeEntryPoint->ProcessorSignature.Uint32;
+ CheckSum32 += MicrocodeEntryPoint->ProcessorFlags;
+ CheckSum32 += MicrocodeEntryPoint->Checksum;
+ if (CheckSum32 == 0) {
+ CorrectMicrocode = TRUE;
+ ProcessorFlags = MicrocodeEntryPoint->ProcessorFlags;
+ }
+ } else if ((MicrocodeEntryPoint->DataSize != 0) &&
+ (MicrocodeEntryPoint->UpdateRevision > LatestRevision)) {
+ ExtendedTableLength = MicrocodeEntryPoint->TotalSize - (MicrocodeEntryPoint->DataSize +
+ sizeof (CPU_MICROCODE_HEADER));
+ if (ExtendedTableLength != 0) {
//
- // Calculate CheckSum Part1.
+ // Extended Table exist, check if the CPU in support list
//
- CheckSum32 = InCompleteCheckSum32;
- CheckSum32 += MicrocodeEntryPoint->ProcessorSignature.Uint32;
- CheckSum32 += MicrocodeEntryPoint->ProcessorFlags;
- CheckSum32 += MicrocodeEntryPoint->Checksum;
- if (CheckSum32 == 0) {
- CorrectMicrocode = TRUE;
- ProcessorFlags = MicrocodeEntryPoint->ProcessorFlags;
- }
- } else if ((MicrocodeEntryPoint->DataSize != 0) &&
- (MicrocodeEntryPoint->UpdateRevision > LatestRevision)) {
- ExtendedTableLength = MicrocodeEntryPoint->TotalSize - (MicrocodeEntryPoint->DataSize +
- sizeof (CPU_MICROCODE_HEADER));
- if (ExtendedTableLength != 0) {
- //
- // Extended Table exist, check if the CPU in support list
- //
- ExtendedTableHeader = (CPU_MICROCODE_EXTENDED_TABLE_HEADER *) ((UINT8 *) (MicrocodeEntryPoint)
- + MicrocodeEntryPoint->DataSize + sizeof (CPU_MICROCODE_HEADER));
+ ExtendedTableHeader = (CPU_MICROCODE_EXTENDED_TABLE_HEADER *) ((UINT8 *) (MicrocodeEntryPoint)
+ + MicrocodeEntryPoint->DataSize + sizeof (CPU_MICROCODE_HEADER));
+ //
+ // Calculate Extended Checksum
+ //
+ if ((ExtendedTableLength % 4) == 0) {
//
- // Calculate Extended Checksum
+ // Calculate CheckSum Part2.
//
- if ((ExtendedTableLength % 4) == 0) {
+ CheckSum32 = CalculateSum32 ((UINT32 *) ExtendedTableHeader, ExtendedTableLength);
+ if (CheckSum32 == 0) {
//
- // Calculate CheckSum Part2.
+ // Checksum correct
//
- CheckSum32 = CalculateSum32 ((UINT32 *) ExtendedTableHeader, ExtendedTableLength);
- if (CheckSum32 == 0) {
+ ExtendedTableCount = ExtendedTableHeader->ExtendedSignatureCount;
+ ExtendedTable = (CPU_MICROCODE_EXTENDED_TABLE *) (ExtendedTableHeader + 1);
+ for (Index = 0; Index < ExtendedTableCount; Index ++) {
//
- // Checksum correct
+ // Calculate CheckSum Part3.
//
- ExtendedTableCount = ExtendedTableHeader->ExtendedSignatureCount;
- ExtendedTable = (CPU_MICROCODE_EXTENDED_TABLE *) (ExtendedTableHeader + 1);
- for (Index = 0; Index < ExtendedTableCount; Index ++) {
+ CheckSum32 = InCompleteCheckSum32;
+ CheckSum32 += ExtendedTable->ProcessorSignature.Uint32;
+ CheckSum32 += ExtendedTable->ProcessorFlag;
+ CheckSum32 += ExtendedTable->Checksum;
+ if (CheckSum32 == 0) {
//
- // Calculate CheckSum Part3.
+ // Verify Header
//
- CheckSum32 = InCompleteCheckSum32;
- CheckSum32 += ExtendedTable->ProcessorSignature.Uint32;
- CheckSum32 += ExtendedTable->ProcessorFlag;
- CheckSum32 += ExtendedTable->Checksum;
- if (CheckSum32 == 0) {
+ if ((ExtendedTable->ProcessorSignature.Uint32 == Eax.Uint32) &&
+ (ExtendedTable->ProcessorFlag & (1 << PlatformId)) ) {
//
- // Verify Header
+ // Find one
//
- if ((ExtendedTable->ProcessorSignature.Uint32 == Eax.Uint32) &&
- (ExtendedTable->ProcessorFlag & (1 << PlatformId)) ) {
- //
- // Find one
- //
- CorrectMicrocode = TRUE;
- ProcessorFlags = ExtendedTable->ProcessorFlag;
- break;
- }
+ CorrectMicrocode = TRUE;
+ ProcessorFlags = ExtendedTable->ProcessorFlag;
+ break;
}
- ExtendedTable ++;
}
+ ExtendedTable ++;
}
}
}
}
- } else {
- //
- // It is the padding data between the microcode patches for microcode patches alignment.
- // Because the microcode patch is the multiple of 1-KByte, the padding data should not
- // exist if the microcode patch alignment value is not larger than 1-KByte. So, the microcode
- // alignment value should be larger than 1-KByte. We could skip SIZE_1KB padding data to
- // find the next possible microcode patch header.
- //
- MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + SIZE_1KB);
- continue;
}
+
//
// Get the next patch.
//
--
2.16.2.windows.1
next prev parent reply other threads:[~2019-02-28 6:03 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-02-28 6:02 [PATCH 0/2] Fix Microcode failure issue Chen A Chen
2019-02-28 6:02 ` [PATCH 1/2] UefiCpuPkg/Microcode: Fix InComplete CheckSum32 issue Chen A Chen
2019-02-28 6:14 ` Ni, Ray
2019-02-28 6:02 ` Chen A Chen [this message]
2019-02-28 6:54 ` [PATCH 2/2] UefiCpuPkg/Microcode: Add verification logic before parsing payload Ni, Ray
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190228060252.23944-3-chen.a.chen@intel.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox