Blame SOURCES/edk2-BaseTools-Add-more-checker-in-Decompress-algorithm-t.patch

cc9195
From 29c394f110b1f769e629e8775874261e33d4abd9 Mon Sep 17 00:00:00 2001
cc9195
From: Laszlo Ersek <lersek@redhat.com>
cc9195
Date: Wed, 24 Oct 2018 21:03:45 +0200
cc9195
Subject: [PATCH 4/4] BaseTools: Add more checker in Decompress algorithm to
cc9195
 access the valid buffer (CVE FIX)
cc9195
cc9195
Message-id: <20181024190345.15288-5-lersek@redhat.com>
cc9195
Patchwork-id: 82886
cc9195
O-Subject:  [RHEL8 edk2 PATCH 4/4] BaseTools: Add more checker in Decompress
cc9195
	algorithm to access the valid buffer (CVE FIX)
cc9195
Bugzilla: 1641445
cc9195
1641453
cc9195
1641464
cc9195
1641469
cc9195
Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
cc9195
Acked-by: Thomas Huth <thuth@redhat.com>
cc9195
cc9195
From: Liming Gao <liming.gao@intel.com>
cc9195
cc9195
--v-- RHEL8 note start --v--
cc9195
cc9195
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1641445
cc9195
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1641453
cc9195
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1641464
cc9195
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1641469
cc9195
cc9195
Unfortunately, the upstream patch series was not structured according to
cc9195
the CVE reports. This patch contributes to fixing:
cc9195
cc9195
- CVE-2017-5731
cc9195
- CVE-2017-5733
cc9195
- CVE-2017-5734
cc9195
- CVE-2017-5735
cc9195
cc9195
but not CVE-2017-5732 (contrarily to the upstream commit message). The
cc9195
best I could achieve up-stream was to get the "CVE FIX" expression into
cc9195
the subject, and a whole-sale dump of the CVEs into the body. I had not
cc9195
been invited to the original (off-list, embargoed) analysis and review.
cc9195
cc9195
The differences that "git-backport-diff" reports as "functional" for this
cc9195
backport aren't actually functional differences. They are due to
cc9195
downstream lacking two upstream commits:
cc9195
cc9195
- f7496d717357 ("BaseTools: Clean up source files", 2018-07-09), with the
cc9195
  "usual" diffstat "289 files changed, 10645 insertions(+), 10645
cc9195
  deletions(-)";
cc9195
cc9195
- more importantly, 472eb3b89682 ("BaseTools: Add --uefi option to enable
cc9195
  UefiCompress method", 2018-10-13).
cc9195
cc9195
(Side note: in upstream, commit 472eb3b89682 was incorrectly reverted as
cc9195
part of 1ccc4d895dd8 ("Revert BaseTools: PYTHON3 migration", 2018-10-15),
cc9195
but then it was re-applied in f1400101a732.)
cc9195
cc9195
In commit 472eb3b89682, the "UEFI" compression/decompression method was
cc9195
added to BaseTools, beyond the original "Tiano" method. This caused the
cc9195
Tiano method to be indented more deeply, in the main() function of
cc9195
"TianoCompress.c". (Also the original Decompress() function was renamed to
cc9195
TDecompress().) The CVE fix applies to the "Tiano" method, which RHEL8
cc9195
does have, but at a different nesting level. Therefore the changes have
cc9195
been backported manually, and the difference in indentation is also why
cc9195
"git-backport-diff" thinks the changes are functional.
cc9195
cc9195
This backport, once applied, can be diffed against the upstream tree more
cc9195
easily as follows:
cc9195
cc9195
  git diff -b HEAD..041d89bc0f01 -- \
cc9195
    BaseTools/Source/C/Common/Decompress.c \
cc9195
    BaseTools/Source/C/TianoCompress/TianoCompress.c
cc9195
cc9195
--^-- RHEL8 note end --^--
cc9195
cc9195
Fix CVE-2017-5731,CVE-2017-5732,CVE-2017-5733,CVE-2017-5734,CVE-2017-5735
cc9195
https://bugzilla.tianocore.org/show_bug.cgi?id=686
cc9195
cc9195
Contributed-under: TianoCore Contribution Agreement 1.1
cc9195
Signed-off-by: Holtsclaw Brent <brent.holtsclaw@intel.com>
cc9195
Signed-off-by: Liming Gao <liming.gao@intel.com>
cc9195
Reviewed-by: Star Zeng <star.zeng@intel.com>
cc9195
Acked-by: Laszlo Ersek <lersek@redhat.com>
cc9195
(cherry picked from commit 041d89bc0f0119df37a5fce1d0f16495ff905089)
cc9195
---
cc9195
 BaseTools/Source/C/Common/Decompress.c           | 23 +++++++++++++++++++--
cc9195
 BaseTools/Source/C/TianoCompress/TianoCompress.c | 26 +++++++++++++++++++++++-
cc9195
 2 files changed, 46 insertions(+), 3 deletions(-)
cc9195
cc9195
diff --git a/BaseTools/Source/C/Common/Decompress.c b/BaseTools/Source/C/Common/Decompress.c
cc9195
index 8f1afb4..bdc10f5 100644
cc9195
--- a/BaseTools/Source/C/Common/Decompress.c
cc9195
+++ b/BaseTools/Source/C/Common/Decompress.c
cc9195
@@ -194,12 +194,16 @@ Returns:
cc9195
   UINT16  Avail;
cc9195
   UINT16  NextCode;
cc9195
   UINT16  Mask;
cc9195
+  UINT16  MaxTableLength;
cc9195
 
cc9195
   for (Index = 1; Index <= 16; Index++) {
cc9195
     Count[Index] = 0;
cc9195
   }
cc9195
 
cc9195
   for (Index = 0; Index < NumOfChar; Index++) {
cc9195
+    if (BitLen[Index] > 16) {
cc9195
+      return (UINT16) BAD_TABLE;
cc9195
+    }
cc9195
     Count[BitLen[Index]]++;
cc9195
   }
cc9195
 
cc9195
@@ -237,6 +241,7 @@ Returns:
cc9195
 
cc9195
   Avail = NumOfChar;
cc9195
   Mask  = (UINT16) (1U << (15 - TableBits));
cc9195
+  MaxTableLength = (UINT16) (1U << TableBits);
cc9195
 
cc9195
   for (Char = 0; Char < NumOfChar; Char++) {
cc9195
 
cc9195
@@ -250,6 +255,9 @@ Returns:
cc9195
     if (Len <= TableBits) {
cc9195
 
cc9195
       for (Index = Start[Len]; Index < NextCode; Index++) {
cc9195
+        if (Index >= MaxTableLength) {
cc9195
+          return (UINT16) BAD_TABLE;
cc9195
+        }
cc9195
         Table[Index] = Char;
cc9195
       }
cc9195
 
cc9195
@@ -643,10 +651,14 @@ Returns: (VOID)
cc9195
 
cc9195
       BytesRemain--;
cc9195
       while ((INT16) (BytesRemain) >= 0) {
cc9195
-        Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++];
cc9195
         if (Sd->mOutBuf >= Sd->mOrigSize) {
cc9195
           return ;
cc9195
         }
cc9195
+        if (DataIdx >= Sd->mOrigSize) {
cc9195
+          Sd->mBadTableFlag = (UINT16) BAD_TABLE;
cc9195
+          return ;
cc9195
+        }
cc9195
+        Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++];
cc9195
 
cc9195
         BytesRemain--;
cc9195
       }
cc9195
@@ -684,6 +696,7 @@ Returns:
cc9195
 --*/
cc9195
 {
cc9195
   UINT8 *Src;
cc9195
+  UINT32 CompSize;
cc9195
 
cc9195
   *ScratchSize  = sizeof (SCRATCH_DATA);
cc9195
 
cc9195
@@ -692,7 +705,13 @@ Returns:
cc9195
     return EFI_INVALID_PARAMETER;
cc9195
   }
cc9195
 
cc9195
+  CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24);
cc9195
   *DstSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);
cc9195
+
cc9195
+  if (SrcSize < CompSize + 8 || (CompSize + 8) < 8) {
cc9195
+    return EFI_INVALID_PARAMETER;
cc9195
+  }
cc9195
+
cc9195
   return EFI_SUCCESS;
cc9195
 }
cc9195
 
cc9195
@@ -752,7 +771,7 @@ Returns:
cc9195
   CompSize  = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24);
cc9195
   OrigSize  = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);
cc9195
 
cc9195
-  if (SrcSize < CompSize + 8) {
cc9195
+  if (SrcSize < CompSize + 8 || (CompSize + 8) < 8) {
cc9195
     return EFI_INVALID_PARAMETER;
cc9195
   }
cc9195
 
cc9195
diff --git a/BaseTools/Source/C/TianoCompress/TianoCompress.c b/BaseTools/Source/C/TianoCompress/TianoCompress.c
cc9195
index 046fb36..d07fd9e 100644
cc9195
--- a/BaseTools/Source/C/TianoCompress/TianoCompress.c
cc9195
+++ b/BaseTools/Source/C/TianoCompress/TianoCompress.c
cc9195
@@ -1753,6 +1753,7 @@ Returns:
cc9195
   SCRATCH_DATA      *Scratch;
cc9195
   UINT8      *Src;
cc9195
   UINT32     OrigSize;
cc9195
+  UINT32     CompSize;
cc9195
 
cc9195
   SetUtilityName(UTILITY_NAME);
cc9195
   
cc9195
@@ -1761,6 +1762,7 @@ Returns:
cc9195
   OutBuffer = NULL;
cc9195
   Scratch   = NULL;
cc9195
   OrigSize = 0;
cc9195
+  CompSize = 0;
cc9195
   InputLength = 0;
cc9195
   InputFileName = NULL;
cc9195
   OutputFileName = NULL;
cc9195
@@ -1979,15 +1981,24 @@ Returns:
cc9195
   if (DebugMode) {
cc9195
     DebugMsg(UTILITY_NAME, 0, DebugLevel, "Decoding\n", NULL);
cc9195
   }
cc9195
+  if (InputLength < 8){
cc9195
+    Error (NULL, 0, 3000, "Invalid", "The input file %s is too small.", InputFileName);
cc9195
+    goto ERROR;
cc9195
+  }
cc9195
   //
cc9195
   // Get Compressed file original size
cc9195
   // 
cc9195
   Src     = (UINT8 *)FileBuffer;                     
cc9195
   OrigSize  = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);  
cc9195
+  CompSize  = Src[0] + (Src[1] << 8) + (Src[2] <<16) + (Src[3] <<24);
cc9195
   
cc9195
   //
cc9195
   // Allocate OutputBuffer
cc9195
   //
cc9195
+  if (InputLength < CompSize + 8 || (CompSize + 8) < 8) {
cc9195
+    Error (NULL, 0, 3000, "Invalid", "The input file %s data is invalid.", InputFileName);
cc9195
+    goto ERROR;
cc9195
+  }
cc9195
   OutBuffer = (UINT8 *)malloc(OrigSize);
cc9195
   if (OutBuffer == NULL) {
cc9195
     Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!");
cc9195
@@ -2171,12 +2182,16 @@ Returns:
cc9195
   UINT16  Mask;
cc9195
   UINT16  WordOfStart;
cc9195
   UINT16  WordOfCount;
cc9195
+  UINT16  MaxTableLength;
cc9195
 
cc9195
   for (Index = 0; Index <= 16; Index++) {
cc9195
     Count[Index] = 0;
cc9195
   }
cc9195
 
cc9195
   for (Index = 0; Index < NumOfChar; Index++) {
cc9195
+    if (BitLen[Index] > 16) {
cc9195
+      return (UINT16) BAD_TABLE;
cc9195
+    }
cc9195
     Count[BitLen[Index]]++;
cc9195
   }
cc9195
 
cc9195
@@ -2220,6 +2235,7 @@ Returns:
cc9195
 
cc9195
   Avail = NumOfChar;
cc9195
   Mask  = (UINT16) (1U << (15 - TableBits));
cc9195
+  MaxTableLength = (UINT16) (1U << TableBits);
cc9195
 
cc9195
   for (Char = 0; Char < NumOfChar; Char++) {
cc9195
 
cc9195
@@ -2233,6 +2249,9 @@ Returns:
cc9195
     if (Len <= TableBits) {
cc9195
 
cc9195
       for (Index = Start[Len]; Index < NextCode; Index++) {
cc9195
+        if (Index >= MaxTableLength) {
cc9195
+          return (UINT16) BAD_TABLE;
cc9195
+        }
cc9195
         Table[Index] = Char;
cc9195
       }
cc9195
 
cc9195
@@ -2617,11 +2636,16 @@ Returns: (VOID)
cc9195
       DataIdx     = Sd->mOutBuf - DecodeP (Sd) - 1;
cc9195
 
cc9195
       BytesRemain--;
cc9195
+
cc9195
       while ((INT16) (BytesRemain) >= 0) {
cc9195
-        Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++];
cc9195
         if (Sd->mOutBuf >= Sd->mOrigSize) {
cc9195
           goto Done ;
cc9195
         }
cc9195
+        if (DataIdx >= Sd->mOrigSize) {
cc9195
+          Sd->mBadTableFlag = (UINT16) BAD_TABLE;
cc9195
+          goto Done ;
cc9195
+        }
cc9195
+        Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++];
cc9195
 
cc9195
         BytesRemain--;
cc9195
       }
cc9195
-- 
cc9195
1.8.3.1
cc9195