From 6acb319466e7907d6d12d7d20f945626a64d658f Mon Sep 17 00:00:00 2001 From: Gyorgy Sarvari Date: Sat, 11 Oct 2025 20:13:37 +0200 Subject: [PATCH] freerdp3: patch CVE-2024-32660 Details: https://nvd.nist.gov/vuln/detail/CVE-2024-32660 Pick the patch that is mentioned in the above CVE report. Signed-off-by: Gyorgy Sarvari Signed-off-by: Anuj Mittal --- .../freerdp/freerdp3/CVE-2024-32660.patch | 151 ++++++++++++++++++ .../recipes-support/freerdp/freerdp3_3.4.0.bb | 1 + 2 files changed, 152 insertions(+) create mode 100644 meta-oe/recipes-support/freerdp/freerdp3/CVE-2024-32660.patch diff --git a/meta-oe/recipes-support/freerdp/freerdp3/CVE-2024-32660.patch b/meta-oe/recipes-support/freerdp/freerdp3/CVE-2024-32660.patch new file mode 100644 index 0000000000..5e0d679467 --- /dev/null +++ b/meta-oe/recipes-support/freerdp/freerdp3/CVE-2024-32660.patch @@ -0,0 +1,151 @@ +From 466ffba85665107f23cbc25ee4563e5638dcc4cd Mon Sep 17 00:00:00 2001 +From: akallabeth +Date: Sat, 20 Apr 2024 19:59:48 +0200 +Subject: [PATCH] allocate in segment steps + +do not trust the uncompressedSize of a ZGFX_SEGMENTED_MULTIPART and +allocate the output buffer in steps after decoding a segment. + +CVE: CVE-2024-32660 +Upstream-Status: Backport [https://github.com/FreeRDP/FreeRDP/commit/5e5d27cf310e4c10b854be7667bfb7a5d774eb47] + +Signed-off-by: Gyorgy Sarvari +--- + libfreerdp/codec/zgfx.c | 75 +++++++++++++++++++++++++---------------- + 1 file changed, 46 insertions(+), 29 deletions(-) + +diff --git a/libfreerdp/codec/zgfx.c b/libfreerdp/codec/zgfx.c +index b7ee27511..3a9d2e526 100644 +--- a/libfreerdp/codec/zgfx.c ++++ b/libfreerdp/codec/zgfx.c +@@ -382,16 +382,46 @@ 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 = 0; + wStream sbuffer = { 0 }; ++ size_t used = 0; ++ BYTE* pConcatenated = NULL; + wStream* stream = Stream_StaticConstInit(&sbuffer, pSrcData, SrcSize); + + WINPR_ASSERT(zgfx); + WINPR_ASSERT(stream); ++ WINPR_ASSERT(ppDstData); ++ WINPR_ASSERT(pDstSize); ++ ++ *ppDstData = NULL; ++ *pDstSize = 0; + + if (!Stream_CheckAndLogRequiredLength(TAG, stream, 1)) + goto fail; +@@ -403,16 +433,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) + { +@@ -420,8 +449,6 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY + UINT16 segmentNumber = 0; + UINT16 segmentCount = 0; + UINT32 uncompressedSize = 0; +- BYTE* pConcatenated = NULL; +- size_t used = 0; + + if (!Stream_CheckAndLogRequiredLength(TAG, stream, 6)) + goto fail; +@@ -429,17 +456,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_CheckAndLogRequiredLengthOfSize(TAG, 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_CheckAndLogRequiredLength(TAG, stream, sizeof(UINT32))) +@@ -450,16 +466,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 + { +@@ -468,6 +483,8 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY + + status = 1; + fail: ++ if (status < 0) ++ free(pConcatenated); + return status; + } + diff --git a/meta-oe/recipes-support/freerdp/freerdp3_3.4.0.bb b/meta-oe/recipes-support/freerdp/freerdp3_3.4.0.bb index 8649e28ecb..80e8f5f93f 100644 --- a/meta-oe/recipes-support/freerdp/freerdp3_3.4.0.bb +++ b/meta-oe/recipes-support/freerdp/freerdp3_3.4.0.bb @@ -16,6 +16,7 @@ SRC_URI = "git://github.com/FreeRDP/FreeRDP.git;branch=master;protocol=https \ file://CVE-2024-32460.patch \ file://CVE-2024-32658.patch \ file://CVE-2024-32659.patch \ + file://CVE-2024-32660.patch \ " S = "${WORKDIR}/git"