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

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