Blame SOURCES/ovmf-MdeModulePkg-HiiDatabase-Fix-potential-integer-overf.patch

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