|
|
3c2ede |
From 9e68568e34bef0037bb16b3cbe361e559b8da369 Mon Sep 17 00:00:00 2001
|
|
|
3c2ede |
From: Laszlo Ersek <lersek@redhat.com>
|
|
|
3c2ede |
Date: Fri, 22 Mar 2019 17:39:35 +0100
|
|
|
3c2ede |
Subject: [PATCH 1/8] MdeModulePkg/HiiDatabase: Fix potential integer overflow
|
|
|
3c2ede |
(CVE-2018-12181)
|
|
|
3c2ede |
MIME-Version: 1.0
|
|
|
3c2ede |
Content-Type: text/plain; charset=UTF-8
|
|
|
3c2ede |
Content-Transfer-Encoding: 8bit
|
|
|
3c2ede |
|
|
|
3c2ede |
Message-id: <20190322163936.10835-2-lersek@redhat.com>
|
|
|
3c2ede |
Patchwork-id: 85124
|
|
|
3c2ede |
O-Subject: [RHEL-7.7 ovmf PATCH 1/2] MdeModulePkg/HiiDatabase: Fix potential
|
|
|
3c2ede |
integer overflow (CVE-2018-12181)
|
|
|
3c2ede |
Bugzilla: 1691479
|
|
|
3c2ede |
Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
|
|
|
3c2ede |
Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
|
|
3c2ede |
|
|
|
3c2ede |
From: Ray Ni <ray.ni@intel.com>
|
|
|
3c2ede |
|
|
|
3c2ede |
--v-- RHEL7 note --v--
|
|
|
3c2ede |
|
|
|
3c2ede |
A contextual conflict had to be resolved manually because we don't have
|
|
|
3c2ede |
upstream commit 979b7d802c31 ("MdeModulePkg/HiiDB: Make sure database
|
|
|
3c2ede |
update behaviors are atomic", 2018-10-26), which was written for upstream
|
|
|
3c2ede |
BZ <https://bugzilla.tianocore.org/show_bug.cgi?id=1235>. More
|
|
|
3c2ede |
specifically, the context to which upstream ffe5f7a6b4e9 (i.e. the patch
|
|
|
3c2ede |
being backported) applies includes EfiAcquireLock() added in 979b7d802c31,
|
|
|
3c2ede |
and our downstream context lacks that.
|
|
|
3c2ede |
|
|
|
3c2ede |
While reviewing this, I noticed that some of the new error paths
|
|
|
3c2ede |
introduced by the more rigorous checking in upstream ffe5f7a6b4e9 fail to
|
|
|
3c2ede |
release the lock. For upstream I reported a new BZ about this
|
|
|
3c2ede |
<https://bugzilla.tianocore.org/show_bug.cgi?id=1652>, but down-stream, we
|
|
|
3c2ede |
don't have the EfiAcquireLock() in the first place, so there is no leak.
|
|
|
3c2ede |
|
|
|
3c2ede |
--^-- RHEL7 note --^--
|
|
|
3c2ede |
|
|
|
3c2ede |
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1135
|
|
|
3c2ede |
|
|
|
3c2ede |
Contributed-under: TianoCore Contribution Agreement 1.1
|
|
|
3c2ede |
Signed-off-by: Ray Ni <ray.ni@intel.com>
|
|
|
3c2ede |
Cc: Dandan Bi <dandan.bi@intel.com>
|
|
|
3c2ede |
Cc: Hao A Wu <hao.a.wu@intel.com>
|
|
|
3c2ede |
Reviewed-by: Hao Wu <hao.a.wu@intel.com>
|
|
|
3c2ede |
Reviewed-by: Jian J Wang <jian.j.wang@intel.com>
|
|
|
3c2ede |
(cherry picked from commit ffe5f7a6b4e978dffbe1df228963adc914451106)
|
|
|
3c2ede |
---
|
|
|
3c2ede |
MdeModulePkg/Universal/HiiDatabaseDxe/Image.c | 126 +++++++++++++++++++++-----
|
|
|
3c2ede |
1 file changed, 103 insertions(+), 23 deletions(-)
|
|
|
3c2ede |
|
|
|
3c2ede |
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c b/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c
|
|
|
3c2ede |
index 431a5b8..dc9566b 100644
|
|
|
3c2ede |
--- a/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c
|
|
|
3c2ede |
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c
|
|
|
3c2ede |
@@ -16,6 +16,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
|
3c2ede |
|
|
|
3c2ede |
#include "HiiDatabase.h"
|
|
|
3c2ede |
|
|
|
3c2ede |
+#define MAX_UINT24 0xFFFFFF
|
|
|
3c2ede |
|
|
|
3c2ede |
/**
|
|
|
3c2ede |
Get the imageid of last image block: EFI_HII_IIBT_END_BLOCK when input
|
|
|
3c2ede |
@@ -649,8 +650,16 @@ HiiNewImage (
|
|
|
3c2ede |
return EFI_NOT_FOUND;
|
|
|
3c2ede |
}
|
|
|
3c2ede |
|
|
|
3c2ede |
- NewBlockSize = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +
|
|
|
3c2ede |
- BITMAP_LEN_24_BIT ((UINT32) Image->Width, Image->Height);
|
|
|
3c2ede |
+ //
|
|
|
3c2ede |
+ // Calcuate the size of new image.
|
|
|
3c2ede |
+ // Make sure the size doesn't overflow UINT32.
|
|
|
3c2ede |
+ // Note: 24Bit BMP occpuies 3 bytes per pixel.
|
|
|
3c2ede |
+ //
|
|
|
3c2ede |
+ NewBlockSize = (UINT32)Image->Width * Image->Height;
|
|
|
3c2ede |
+ if (NewBlockSize > (MAX_UINT32 - (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL))) / 3) {
|
|
|
3c2ede |
+ return EFI_OUT_OF_RESOURCES;
|
|
|
3c2ede |
+ }
|
|
|
3c2ede |
+ NewBlockSize = NewBlockSize * 3 + (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL));
|
|
|
3c2ede |
|
|
|
3c2ede |
//
|
|
|
3c2ede |
// Get the image package in the package list,
|
|
|
3c2ede |
@@ -669,6 +678,18 @@ HiiNewImage (
|
|
|
3c2ede |
//
|
|
|
3c2ede |
// Update the package's image block by appending the new block to the end.
|
|
|
3c2ede |
//
|
|
|
3c2ede |
+
|
|
|
3c2ede |
+ //
|
|
|
3c2ede |
+ // Make sure the final package length doesn't overflow.
|
|
|
3c2ede |
+ // Length of the package header is represented using 24 bits. So MAX length is MAX_UINT24.
|
|
|
3c2ede |
+ //
|
|
|
3c2ede |
+ if (NewBlockSize > MAX_UINT24 - ImagePackage->ImagePkgHdr.Header.Length) {
|
|
|
3c2ede |
+ return EFI_OUT_OF_RESOURCES;
|
|
|
3c2ede |
+ }
|
|
|
3c2ede |
+ //
|
|
|
3c2ede |
+ // Because ImagePackage->ImageBlockSize < ImagePackage->ImagePkgHdr.Header.Length,
|
|
|
3c2ede |
+ // So (ImagePackage->ImageBlockSize + NewBlockSize) <= MAX_UINT24
|
|
|
3c2ede |
+ //
|
|
|
3c2ede |
ImageBlocks = AllocatePool (ImagePackage->ImageBlockSize + NewBlockSize);
|
|
|
3c2ede |
if (ImageBlocks == NULL) {
|
|
|
3c2ede |
return EFI_OUT_OF_RESOURCES;
|
|
|
3c2ede |
@@ -699,6 +720,13 @@ HiiNewImage (
|
|
|
3c2ede |
|
|
|
3c2ede |
} else {
|
|
|
3c2ede |
//
|
|
|
3c2ede |
+ // Make sure the final package length doesn't overflow.
|
|
|
3c2ede |
+ // Length of the package header is represented using 24 bits. So MAX length is MAX_UINT24.
|
|
|
3c2ede |
+ //
|
|
|
3c2ede |
+ if (NewBlockSize > MAX_UINT24 - (sizeof (EFI_HII_IMAGE_PACKAGE_HDR) + sizeof (EFI_HII_IIBT_END_BLOCK))) {
|
|
|
3c2ede |
+ return EFI_OUT_OF_RESOURCES;
|
|
|
3c2ede |
+ }
|
|
|
3c2ede |
+ //
|
|
|
3c2ede |
// The specified package list does not contain image package.
|
|
|
3c2ede |
// Create one to add this image block.
|
|
|
3c2ede |
//
|
|
|
3c2ede |
@@ -895,8 +923,11 @@ IGetImage (
|
|
|
3c2ede |
// Use the common block code since the definition of these structures is the same.
|
|
|
3c2ede |
//
|
|
|
3c2ede |
CopyMem (&Iibt1bit, CurrentImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK));
|
|
|
3c2ede |
- ImageLength = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) *
|
|
|
3c2ede |
- ((UINT32) Iibt1bit.Bitmap.Width * Iibt1bit.Bitmap.Height);
|
|
|
3c2ede |
+ ImageLength = (UINTN) Iibt1bit.Bitmap.Width * Iibt1bit.Bitmap.Height;
|
|
|
3c2ede |
+ if (ImageLength > MAX_UINTN / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) {
|
|
|
3c2ede |
+ return EFI_OUT_OF_RESOURCES;
|
|
|
3c2ede |
+ }
|
|
|
3c2ede |
+ ImageLength *= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
|
|
|
3c2ede |
Image->Bitmap = AllocateZeroPool (ImageLength);
|
|
|
3c2ede |
if (Image->Bitmap == NULL) {
|
|
|
3c2ede |
return EFI_OUT_OF_RESOURCES;
|
|
|
3c2ede |
@@ -945,9 +976,13 @@ IGetImage (
|
|
|
3c2ede |
// fall through
|
|
|
3c2ede |
//
|
|
|
3c2ede |
case EFI_HII_IIBT_IMAGE_24BIT:
|
|
|
3c2ede |
- Width = ReadUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width);
|
|
|
3c2ede |
+ Width = ReadUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width);
|
|
|
3c2ede |
Height = ReadUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height);
|
|
|
3c2ede |
- ImageLength = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * ((UINT32) Width * Height);
|
|
|
3c2ede |
+ ImageLength = (UINTN)Width * Height;
|
|
|
3c2ede |
+ if (ImageLength > MAX_UINTN / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) {
|
|
|
3c2ede |
+ return EFI_OUT_OF_RESOURCES;
|
|
|
3c2ede |
+ }
|
|
|
3c2ede |
+ ImageLength *= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
|
|
|
3c2ede |
Image->Bitmap = AllocateZeroPool (ImageLength);
|
|
|
3c2ede |
if (Image->Bitmap == NULL) {
|
|
|
3c2ede |
return EFI_OUT_OF_RESOURCES;
|
|
|
3c2ede |
@@ -1114,8 +1149,23 @@ HiiSetImage (
|
|
|
3c2ede |
//
|
|
|
3c2ede |
// Create the new image block according to input image.
|
|
|
3c2ede |
//
|
|
|
3c2ede |
- NewBlockSize = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +
|
|
|
3c2ede |
- BITMAP_LEN_24_BIT ((UINT32) Image->Width, Image->Height);
|
|
|
3c2ede |
+
|
|
|
3c2ede |
+ //
|
|
|
3c2ede |
+ // Make sure the final package length doesn't overflow.
|
|
|
3c2ede |
+ // Length of the package header is represented using 24 bits. So MAX length is MAX_UINT24.
|
|
|
3c2ede |
+ // 24Bit BMP occpuies 3 bytes per pixel.
|
|
|
3c2ede |
+ //
|
|
|
3c2ede |
+ NewBlockSize = (UINT32)Image->Width * Image->Height;
|
|
|
3c2ede |
+ if (NewBlockSize > (MAX_UINT32 - (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL))) / 3) {
|
|
|
3c2ede |
+ return EFI_OUT_OF_RESOURCES;
|
|
|
3c2ede |
+ }
|
|
|
3c2ede |
+ NewBlockSize = NewBlockSize * 3 + (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL));
|
|
|
3c2ede |
+ if ((NewBlockSize > OldBlockSize) &&
|
|
|
3c2ede |
+ (NewBlockSize - OldBlockSize > MAX_UINT24 - ImagePackage->ImagePkgHdr.Header.Length)
|
|
|
3c2ede |
+ ) {
|
|
|
3c2ede |
+ return EFI_OUT_OF_RESOURCES;
|
|
|
3c2ede |
+ }
|
|
|
3c2ede |
+
|
|
|
3c2ede |
//
|
|
|
3c2ede |
// Adjust the image package to remove the original block firstly then add the new block.
|
|
|
3c2ede |
//
|
|
|
3c2ede |
@@ -1207,8 +1257,8 @@ HiiDrawImage (
|
|
|
3c2ede |
EFI_IMAGE_OUTPUT *ImageOut;
|
|
|
3c2ede |
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
|
|
|
3c2ede |
UINTN BufferLen;
|
|
|
3c2ede |
- UINTN Width;
|
|
|
3c2ede |
- UINTN Height;
|
|
|
3c2ede |
+ UINT16 Width;
|
|
|
3c2ede |
+ UINT16 Height;
|
|
|
3c2ede |
UINTN Xpos;
|
|
|
3c2ede |
UINTN Ypos;
|
|
|
3c2ede |
UINTN OffsetY1;
|
|
|
3c2ede |
@@ -1269,21 +1319,36 @@ HiiDrawImage (
|
|
|
3c2ede |
//
|
|
|
3c2ede |
if (*Blt != NULL) {
|
|
|
3c2ede |
//
|
|
|
3c2ede |
+ // Make sure the BltX and BltY is inside the Blt area.
|
|
|
3c2ede |
+ //
|
|
|
3c2ede |
+ if ((BltX >= (*Blt)->Width) || (BltY >= (*Blt)->Height)) {
|
|
|
3c2ede |
+ return EFI_INVALID_PARAMETER;
|
|
|
3c2ede |
+ }
|
|
|
3c2ede |
+
|
|
|
3c2ede |
+ //
|
|
|
3c2ede |
// Clip the image by (Width, Height)
|
|
|
3c2ede |
//
|
|
|
3c2ede |
|
|
|
3c2ede |
Width = Image->Width;
|
|
|
3c2ede |
Height = Image->Height;
|
|
|
3c2ede |
|
|
|
3c2ede |
- if (Width > (*Blt)->Width - BltX) {
|
|
|
3c2ede |
- Width = (*Blt)->Width - BltX;
|
|
|
3c2ede |
+ if (Width > (*Blt)->Width - (UINT16)BltX) {
|
|
|
3c2ede |
+ Width = (*Blt)->Width - (UINT16)BltX;
|
|
|
3c2ede |
}
|
|
|
3c2ede |
- if (Height > (*Blt)->Height - BltY) {
|
|
|
3c2ede |
- Height = (*Blt)->Height - BltY;
|
|
|
3c2ede |
+ if (Height > (*Blt)->Height - (UINT16)BltY) {
|
|
|
3c2ede |
+ Height = (*Blt)->Height - (UINT16)BltY;
|
|
|
3c2ede |
}
|
|
|
3c2ede |
|
|
|
3c2ede |
- BufferLen = Width * Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
|
|
|
3c2ede |
- BltBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocateZeroPool (BufferLen);
|
|
|
3c2ede |
+ //
|
|
|
3c2ede |
+ // Prepare the buffer for the temporary image.
|
|
|
3c2ede |
+ // Make sure the buffer size doesn't overflow UINTN.
|
|
|
3c2ede |
+ //
|
|
|
3c2ede |
+ BufferLen = Width * Height;
|
|
|
3c2ede |
+ if (BufferLen > MAX_UINTN / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) {
|
|
|
3c2ede |
+ return EFI_OUT_OF_RESOURCES;
|
|
|
3c2ede |
+ }
|
|
|
3c2ede |
+ BufferLen *= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
|
|
|
3c2ede |
+ BltBuffer = AllocateZeroPool (BufferLen);
|
|
|
3c2ede |
if (BltBuffer == NULL) {
|
|
|
3c2ede |
return EFI_OUT_OF_RESOURCES;
|
|
|
3c2ede |
}
|
|
|
3c2ede |
@@ -1346,11 +1411,26 @@ HiiDrawImage (
|
|
|
3c2ede |
//
|
|
|
3c2ede |
// Allocate a new bitmap to hold the incoming image.
|
|
|
3c2ede |
//
|
|
|
3c2ede |
- Width = Image->Width + BltX;
|
|
|
3c2ede |
- Height = Image->Height + BltY;
|
|
|
3c2ede |
|
|
|
3c2ede |
- BufferLen = Width * Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
|
|
|
3c2ede |
- BltBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocateZeroPool (BufferLen);
|
|
|
3c2ede |
+ //
|
|
|
3c2ede |
+ // Make sure the final width and height doesn't overflow UINT16.
|
|
|
3c2ede |
+ //
|
|
|
3c2ede |
+ if ((BltX > (UINTN)MAX_UINT16 - Image->Width) || (BltY > (UINTN)MAX_UINT16 - Image->Height)) {
|
|
|
3c2ede |
+ return EFI_INVALID_PARAMETER;
|
|
|
3c2ede |
+ }
|
|
|
3c2ede |
+
|
|
|
3c2ede |
+ Width = Image->Width + (UINT16)BltX;
|
|
|
3c2ede |
+ Height = Image->Height + (UINT16)BltY;
|
|
|
3c2ede |
+
|
|
|
3c2ede |
+ //
|
|
|
3c2ede |
+ // Make sure the output image size doesn't overflow UINTN.
|
|
|
3c2ede |
+ //
|
|
|
3c2ede |
+ BufferLen = Width * Height;
|
|
|
3c2ede |
+ if (BufferLen > MAX_UINTN / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) {
|
|
|
3c2ede |
+ return EFI_OUT_OF_RESOURCES;
|
|
|
3c2ede |
+ }
|
|
|
3c2ede |
+ BufferLen *= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
|
|
|
3c2ede |
+ BltBuffer = AllocateZeroPool (BufferLen);
|
|
|
3c2ede |
if (BltBuffer == NULL) {
|
|
|
3c2ede |
return EFI_OUT_OF_RESOURCES;
|
|
|
3c2ede |
}
|
|
|
3c2ede |
@@ -1360,8 +1440,8 @@ HiiDrawImage (
|
|
|
3c2ede |
FreePool (BltBuffer);
|
|
|
3c2ede |
return EFI_OUT_OF_RESOURCES;
|
|
|
3c2ede |
}
|
|
|
3c2ede |
- ImageOut->Width = (UINT16) Width;
|
|
|
3c2ede |
- ImageOut->Height = (UINT16) Height;
|
|
|
3c2ede |
+ ImageOut->Width = Width;
|
|
|
3c2ede |
+ ImageOut->Height = Height;
|
|
|
3c2ede |
ImageOut->Image.Bitmap = BltBuffer;
|
|
|
3c2ede |
|
|
|
3c2ede |
//
|
|
|
3c2ede |
@@ -1375,7 +1455,7 @@ HiiDrawImage (
|
|
|
3c2ede |
return Status;
|
|
|
3c2ede |
}
|
|
|
3c2ede |
ASSERT (FontInfo != NULL);
|
|
|
3c2ede |
- for (Index = 0; Index < Width * Height; Index++) {
|
|
|
3c2ede |
+ for (Index = 0; Index < (UINTN)Width * Height; Index++) {
|
|
|
3c2ede |
BltBuffer[Index] = FontInfo->BackgroundColor;
|
|
|
3c2ede |
}
|
|
|
3c2ede |
FreePool (FontInfo);
|
|
|
3c2ede |
--
|
|
|
3c2ede |
1.8.3.1
|
|
|
3c2ede |
|