Compare commits

...

1 Commits

Author SHA1 Message Date
Bernhard Miklautz
120b7641f7 Prepare 2.10.0+dfsg1-2 with patches for multiple CVEs
Add patches to debian/patches to fix the following CVEs:

  + CVE-2024-32039
  + CVE-2024-32041
  + CVE-2024-32040
  + CVE-2024-32458
  + CVE-2024-32459
  + CVE-2024-32460
  + CVE-2024-32658
  + CVE-2024-32659
  + CVE-2024-32660
2024-05-07 11:58:04 +00:00
10 changed files with 1502 additions and 0 deletions

23
debian/changelog vendored
View File

@ -1,3 +1,26 @@
freerdp2 (2.10.0+dfsg1-2) UNRELEASED; urgency=medium
* debian/patches:
+ Add 0001-CVE-2024-32039_and_CVE-2024-32041.patch. Fix Integer overflow
and OutOfBound Write in clear_decompress_residual_data and OutOfBound Read
in zgfx_decompress_segment. (CVE-2024-32039, CVE-2024-32041).
+ Add 0002-CVE-2024-32040.patch. Fix integer underflow in nsc_rle_decode.
(CVE-2024-32040).
+ Add 0003-CVE-2024-32458.patch. Fix OutOfBound Read in
planar_skip_plane_rle. (CVE-2024-32458).
+ Add 0004-CVE-2024-32459.patch. Fix OutOfBound Read in ncrush_decompress.
(CVE-2024-32459).
+ Add 0005-CVE-2024-32460.patch. Fix OutOfBound Read in
interleaved_decompress. (CVE-2024-32460).
+ Add 0006-CVE-2024-32658.patch. Fix ExtractRunLengthRegularFgBg out of
bound read. (CVE-2024-32658).
+ Add 0007-CVE-2024-32659.patch. Fix freerdp_image_copy out of bound read.
(CVE-2024-32659).
+ Add 0008-CVE-2024-32660.patch. Fix zgfx_decompress out of memory.
(CVE-2024-32660).
-- Bernhard Miklautz <bernhard.miklautz@shacknet.at> Mon, 29 Apr 2024 16:23:15 +0200
freerdp2 (2.10.0+dfsg1-1) unstable; urgency=medium
* New upstream release.

View File

@ -0,0 +1,68 @@
From d88ad1acd142769650a6159906ac90f46a766265 Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Tue, 16 Apr 2024 08:35:05 +0200
Subject: [PATCH] [codec,clear] fix integer overflow
reorder check to prevent possible integer overflow
(cherry picked from commit 3a2a241b8fcfee853e35cc54bec00375096fedd9)
---
libfreerdp/codec/clear.c | 2 +-
libfreerdp/codec/zgfx.c | 14 +++++++++-----
2 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/libfreerdp/codec/clear.c b/libfreerdp/codec/clear.c
index 101260770..b8899746e 100644
--- a/libfreerdp/codec/clear.c
+++ b/libfreerdp/codec/clear.c
@@ -410,7 +410,7 @@ static BOOL clear_decompress_residual_data(CLEAR_CONTEXT* clear, wStream* s,
}
}
- if ((pixelIndex + runLengthFactor) > pixelCount)
+ if ((pixelIndex >= pixelCount) || (runLengthFactor > (pixelCount - pixelIndex)))
{
WLog_ERR(TAG,
"pixelIndex %" PRIu32 " + runLengthFactor %" PRIu32 " > pixelCount %" PRIu32
diff --git a/libfreerdp/codec/zgfx.c b/libfreerdp/codec/zgfx.c
index 841b50860..b7b96ade0 100644
--- a/libfreerdp/codec/zgfx.c
+++ b/libfreerdp/codec/zgfx.c
@@ -230,7 +230,10 @@ static BOOL zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, wStream* stream, size_t
BYTE* pbSegment;
size_t cbSegment;
- if (!zgfx || !stream || (segmentSize < 2))
+ WINPR_ASSERT(zgfx);
+ WINPR_ASSERT(stream);
+
+ if (segmentSize < 2)
return FALSE;
cbSegment = segmentSize - 1;
@@ -349,8 +352,9 @@ static BOOL zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, wStream* stream, size_t
if (count > sizeof(zgfx->OutputBuffer) - zgfx->OutputCount)
return FALSE;
-
- if (count > zgfx->cBitsRemaining / 8)
+ else if (count > zgfx->cBitsRemaining / 8)
+ return FALSE;
+ else if (zgfx->pbInputCurrent + count > zgfx->pbInputEnd)
return FALSE;
CopyMemory(&(zgfx->OutputBuffer[zgfx->OutputCount]), zgfx->pbInputCurrent,
@@ -388,8 +392,8 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY
BYTE descriptor;
wStream* stream = Stream_New((BYTE*)pSrcData, SrcSize);
- if (!stream)
- return -1;
+ WINPR_ASSERT(zgfx);
+ WINPR_ASSERT(stream);
if (Stream_GetRemainingLength(stream) < 1)
goto fail;
--
2.43.0

View File

@ -0,0 +1,29 @@
From 5893b5f277db38b0040c572b078de838b84cfc07 Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Tue, 16 Apr 2024 08:26:37 +0200
Subject: [PATCH] [codec,nsc] fix missing check
in nsc_rle_decode abort if there are more bytes to be read then there
are left.
(cherry picked from commit fb4f2d6e4db563077afcae4d270ba78ff905f6cf)
---
libfreerdp/codec/nsc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libfreerdp/codec/nsc.c b/libfreerdp/codec/nsc.c
index 645ca7512..d10fc6bca 100644
--- a/libfreerdp/codec/nsc.c
+++ b/libfreerdp/codec/nsc.c
@@ -169,7 +169,7 @@ static BOOL nsc_rle_decode(const BYTE* in, size_t inSize, BYTE* out, UINT32 outS
len |= ((UINT32)(*in++)) << 24U;
}
- if (outSize < len)
+ if ((outSize < len) || (left < len))
return FALSE;
outSize -= len;
--
2.43.0

117
debian/patches/0003-CVE-2024-32458.patch vendored Normal file
View File

@ -0,0 +1,117 @@
From 9bc624c721ecde8251cfabd1edf069bc713ccc97 Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Tue, 16 Apr 2024 08:42:52 +0200
Subject: [PATCH] [codec,planar] fix missing input length checks
(cherry picked from commit 52d75f6f4078143951e8a4976bc5af30a5556cb6)
---
libfreerdp/codec/planar.c | 53 +++++++++++++++++++++++++++++++--------
1 file changed, 43 insertions(+), 10 deletions(-)
diff --git a/libfreerdp/codec/planar.c b/libfreerdp/codec/planar.c
index 0a5ec581c..fe27011e1 100644
--- a/libfreerdp/codec/planar.c
+++ b/libfreerdp/codec/planar.c
@@ -689,6 +689,13 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData, UINT
rawHeights[3] = nSrcHeight;
}
+ const size_t diff = srcp - pSrcData;
+ if (SrcSize < diff)
+ {
+ WLog_ERR(TAG, "Size mismatch %" PRIu32 " < %" PRIuz, SrcSize, diff);
+ return FALSE;
+ }
+
if (!rle) /* RAW */
{
UINT32 base = planeSize * 3;
@@ -697,8 +704,12 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData, UINT
if (alpha)
{
- if ((SrcSize - (srcp - pSrcData)) < (planeSize + base))
+ if ((SrcSize - diff) < (planeSize + base))
+ {
+ WLog_ERR(TAG, "Alpha plane size mismatch %" PRIuz " < %" PRIu32, SrcSize - diff,
+ (planeSize + base));
return FALSE;
+ }
planes[3] = srcp; /* AlphaPlane */
planes[0] = planes[3] + rawSizes[3]; /* LumaOrRedPlane */
@@ -710,8 +721,11 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData, UINT
}
else
{
- if ((SrcSize - (srcp - pSrcData)) < base)
+ if ((SrcSize - diff) < base)
+ {
+ WLog_ERR(TAG, "plane size mismatch %" PRIu32 " < %" PRIu32, SrcSize - diff, base);
return FALSE;
+ }
planes[0] = srcp; /* LumaOrRedPlane */
planes[1] = planes[0] + rawSizes[0]; /* OrangeChromaOrGreenPlane */
@@ -726,8 +740,8 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData, UINT
if (alpha)
{
planes[3] = srcp;
- rleSizes[3] = planar_skip_plane_rle(planes[3], SrcSize - (planes[3] - pSrcData),
- rawWidths[3], rawHeights[3]); /* AlphaPlane */
+ rleSizes[3] = planar_skip_plane_rle(planes[3], SrcSize - diff, rawWidths[3],
+ rawHeights[3]); /* AlphaPlane */
if (rleSizes[3] < 0)
return FALSE;
@@ -737,22 +751,41 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData, UINT
else
planes[0] = srcp;
- rleSizes[0] = planar_skip_plane_rle(planes[0], SrcSize - (planes[0] - pSrcData),
- rawWidths[0], rawHeights[0]); /* RedPlane */
+ const size_t diff0 = (planes[0] - pSrcData);
+ if (SrcSize < diff0)
+ {
+ WLog_ERR(TAG, "Size mismatch %" PRIu32 " < %" PRIuz, SrcSize, diff0);
+ return FALSE;
+ }
+ rleSizes[0] = planar_skip_plane_rle(planes[0], SrcSize - diff0, rawWidths[0],
+ rawHeights[0]); /* RedPlane */
if (rleSizes[0] < 0)
return FALSE;
planes[1] = planes[0] + rleSizes[0];
- rleSizes[1] = planar_skip_plane_rle(planes[1], SrcSize - (planes[1] - pSrcData),
- rawWidths[1], rawHeights[1]); /* GreenPlane */
+
+ const size_t diff1 = (planes[1] - pSrcData);
+ if (SrcSize < diff1)
+ {
+ WLog_ERR(TAG, "Size mismatch %" PRIu32 " < %" PRIuz, SrcSize, diff1);
+ return FALSE;
+ }
+ rleSizes[1] = planar_skip_plane_rle(planes[1], SrcSize - diff1, rawWidths[1],
+ rawHeights[1]); /* GreenPlane */
if (rleSizes[1] < 1)
return FALSE;
planes[2] = planes[1] + rleSizes[1];
- rleSizes[2] = planar_skip_plane_rle(planes[2], SrcSize - (planes[2] - pSrcData),
- rawWidths[2], rawHeights[2]); /* BluePlane */
+ const size_t diff2 = (planes[2] - pSrcData);
+ if (SrcSize < diff2)
+ {
+ WLog_ERR(TAG, "Size mismatch %" PRIu32 " < %" PRIuz, SrcSize, diff);
+ return FALSE;
+ }
+ rleSizes[2] = planar_skip_plane_rle(planes[2], SrcSize - diff2, rawWidths[2],
+ rawHeights[2]); /* BluePlane */
if (rleSizes[2] < 1)
return FALSE;
--
2.43.0

View File

@ -0,0 +1,17 @@
diff --git a/libfreerdp/codec/ncrush.c b/libfreerdp/codec/ncrush.c
index 3d6a216..ce67c2a 100644
--- a/libfreerdp/codec/ncrush.c
+++ b/libfreerdp/codec/ncrush.c
@@ -2050,6 +2050,12 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY
return 1;
}
+ if (SrcSize < 4)
+ {
+ WLog_ERR(TAG, "Input size short: SrcSize %" PRIu32 " < 4", SrcSize);
+ return -1;
+ }
+
SrcEnd = &pSrcData[SrcSize];
nbits = 32;
bits = get_dword(pSrcData);

1030
debian/patches/0005-CVE-2024-32460.patch vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,35 @@
From 2b9f30a2fa4b13559a367f7cbe158e1bafe0f482 Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Sat, 20 Apr 2024 17:59:49 +0200
Subject: [PATCH] [codec,interleaved] fix offset error
(cherry picked from commit 1a755d898ddc028cc818d0dd9d49d5acff4c44bf)
---
libfreerdp/codec/interleaved.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libfreerdp/codec/interleaved.c b/libfreerdp/codec/interleaved.c
index d4d291699..e419876e6 100644
--- a/libfreerdp/codec/interleaved.c
+++ b/libfreerdp/codec/interleaved.c
@@ -214,7 +214,7 @@ static UINT ExtractRunLengthRegularFgBg(const BYTE* pbOrderHdr, const BYTE* pbEn
runLength = (*pbOrderHdr) & g_MaskRegularRunLength;
if (runLength == 0)
{
- if (!buffer_within_range(pbOrderHdr, 1, pbEnd))
+ if (!buffer_within_range(pbOrderHdr, 2, pbEnd))
{
*advance = 0;
return 0;
@@ -284,7 +284,7 @@ static UINT ExtractRunLengthMegaMega(const BYTE* pbOrderHdr, const BYTE* pbEnd,
WINPR_ASSERT(pbEnd);
WINPR_ASSERT(advance);
- if (!buffer_within_range(pbOrderHdr, 2, pbEnd))
+ if (!buffer_within_range(pbOrderHdr, 3, pbEnd))
{
*advance = 0;
return 0;
--
2.43.0

View File

@ -0,0 +1,27 @@
From 8b9ad6cf80a2233de22b3b5100d642d876ef9a6e Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Sun, 21 Apr 2024 10:18:43 +0200
Subject: [PATCH] [codec,color] fix out of bound read
(cherry picked from commit 6430945ce003a5e24d454d8566f54aae1b6b617b)
---
libfreerdp/codec/color.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/libfreerdp/codec/color.c b/libfreerdp/codec/color.c
index 00919983c..f8467c295 100644
--- a/libfreerdp/codec/color.c
+++ b/libfreerdp/codec/color.c
@@ -613,6 +613,9 @@ BOOL freerdp_image_copy(BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32
if (!pDstData || !pSrcData)
return FALSE;
+ if ((nWidth == 0) || (nHeight == 0))
+ return TRUE;
+
if (nDstStep == 0)
nDstStep = nWidth * GetBytesPerPixel(DstFormat);
--
2.43.0

148
debian/patches/0008-CVE-2024-32660.patch vendored Normal file
View File

@ -0,0 +1,148 @@
diff --git a/libfreerdp/codec/zgfx.c b/libfreerdp/codec/zgfx.c
index 97579b1..c632294 100644
--- a/libfreerdp/codec/zgfx.c
+++ b/libfreerdp/codec/zgfx.c
@@ -262,7 +262,11 @@ static BOOL zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, wStream* stream, size_t
zgfx->pbInputCurrent = pbSegment;
zgfx->pbInputEnd = &pbSegment[cbSegment - 1];
/* NumberOfBitsToDecode = ((NumberOfBytesToDecode - 1) * 8) - ValueOfLastByte */
- zgfx->cBitsRemaining = 8 * (cbSegment - 1) - *zgfx->pbInputEnd;
+ const UINT32 bits = 8u * (cbSegment - 1u);
+ if (bits < *zgfx->pbInputEnd)
+ return FALSE;
+
+ zgfx->cBitsRemaining = bits - *zgfx->pbInputEnd;
zgfx->cBitsCurrent = 0;
zgfx->BitsCurrent = 0;
@@ -381,15 +385,45 @@ static BYTE* aligned_zgfx_malloc(size_t size)
return malloc(size + 64);
}
+static BOOL zgfx_append(ZGFX_CONTEXT* zgfx, BYTE** ppConcatenated, size_t uncompressedSize,
+ size_t* pUsed)
+{
+ WINPR_ASSERT(zgfx);
+ WINPR_ASSERT(ppConcatenated);
+ WINPR_ASSERT(pUsed);
+
+ const size_t used = *pUsed;
+ if (zgfx->OutputCount > UINT32_MAX - used)
+ return FALSE;
+
+ if (used + zgfx->OutputCount > uncompressedSize)
+ return FALSE;
+
+ BYTE* tmp = realloc(*ppConcatenated, used + zgfx->OutputCount + 64ull);
+ if (!tmp)
+ return FALSE;
+ *ppConcatenated = tmp;
+ CopyMemory(&tmp[used], zgfx->OutputBuffer, zgfx->OutputCount);
+ *pUsed = used + zgfx->OutputCount;
+ return TRUE;
+}
+
int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData,
UINT32* pDstSize, UINT32 flags)
{
int status = -1;
- BYTE descriptor;
+ BYTE descriptor = 0;
+ size_t used = 0;
+ BYTE* pConcatenated = NULL;
wStream* stream = Stream_New((BYTE*)pSrcData, SrcSize);
WINPR_ASSERT(zgfx);
WINPR_ASSERT(stream);
+ WINPR_ASSERT(ppDstData);
+ WINPR_ASSERT(pDstSize);
+
+ *ppDstData = NULL;
+ *pDstSize = 0;
if (Stream_GetRemainingLength(stream) < 1)
goto fail;
@@ -401,16 +435,15 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY
if (!zgfx_decompress_segment(zgfx, stream, Stream_GetRemainingLength(stream)))
goto fail;
- *ppDstData = NULL;
-
if (zgfx->OutputCount > 0)
- *ppDstData = aligned_zgfx_malloc(zgfx->OutputCount);
-
- if (!*ppDstData)
- goto fail;
-
- *pDstSize = zgfx->OutputCount;
- CopyMemory(*ppDstData, zgfx->OutputBuffer, zgfx->OutputCount);
+ {
+ if (!zgfx_append(zgfx, &pConcatenated, zgfx->OutputCount, &used))
+ goto fail;
+ if (used != zgfx->OutputCount)
+ goto fail;
+ *ppDstData = pConcatenated;
+ *pDstSize = zgfx->OutputCount;
+ }
}
else if (descriptor == ZGFX_SEGMENTED_MULTIPART)
{
@@ -418,8 +451,6 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY
UINT16 segmentNumber;
UINT16 segmentCount;
UINT32 uncompressedSize;
- BYTE* pConcatenated;
- size_t used = 0;
if (Stream_GetRemainingLength(stream) < 6)
goto fail;
@@ -427,17 +458,6 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY
Stream_Read_UINT16(stream, segmentCount); /* segmentCount (2 bytes) */
Stream_Read_UINT32(stream, uncompressedSize); /* uncompressedSize (4 bytes) */
- if (Stream_GetRemainingLength(stream) < segmentCount * sizeof(UINT32))
- goto fail;
-
- pConcatenated = aligned_zgfx_malloc(uncompressedSize);
-
- if (!pConcatenated)
- goto fail;
-
- *ppDstData = pConcatenated;
- *pDstSize = uncompressedSize;
-
for (segmentNumber = 0; segmentNumber < segmentCount; segmentNumber++)
{
if (Stream_GetRemainingLength(stream) < sizeof(UINT32))
@@ -448,16 +468,15 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY
if (!zgfx_decompress_segment(zgfx, stream, segmentSize))
goto fail;
- if (zgfx->OutputCount > UINT32_MAX - used)
+ if (!zgfx_append(zgfx, &pConcatenated, uncompressedSize, &used))
goto fail;
+ }
- if (used + zgfx->OutputCount > uncompressedSize)
- goto fail;
+ if (used != uncompressedSize)
+ goto fail;
- CopyMemory(pConcatenated, zgfx->OutputBuffer, zgfx->OutputCount);
- pConcatenated += zgfx->OutputCount;
- used += zgfx->OutputCount;
- }
+ *ppDstData = pConcatenated;
+ *pDstSize = uncompressedSize;
}
else
{
@@ -466,6 +485,8 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY
status = 1;
fail:
+ if (status < 0)
+ free(pConcatenated);
Stream_Free(stream, FALSE);
return status;
}

8
debian/patches/series vendored Normal file
View File

@ -0,0 +1,8 @@
0001-CVE-2024-32039_and_CVE-2024-32041.patch
0002-CVE-2024-32040.patch
0003-CVE-2024-32458.patch
0004-CVE-2024-32459.patch
0005-CVE-2024-32460.patch
0006-CVE-2024-32658.patch
0007-CVE-2024-32659.patch
0008-CVE-2024-32660.patch