|
|
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 |
|