From 05faff9cdbc3e8fa9be9cc4386a890fbe2dbb015 Mon Sep 17 00:00:00 2001 From: xinlongchen Date: Tue, 22 Sep 2026 15:22:20 +0800 Subject: [PATCH] Upgrade to upstream version 3.31.1 --- ...30-CVE-2026-23531-CVE-2026-23532-CVE.patch | 90 ------ 0001-fix-CVE-2026-23883.patch | 47 --- 0001-fix-CVE-2026-26955-CVE-2026-26965.patch | 58 ---- CVE-2024-32658.patch | 32 -- CVE-2024-32659.patch | 24 -- CVE-2024-32660.patch | 148 --------- ...clear-fix-clear_resize_buffer-checks.patch | 62 ---- ...-rdstls-Fix-version-validation-macro.patch | 32 ++ ...ccept-matching-autoreconnect-cookies.patch | 31 ++ ...ls-validate-cookie-session-ID-length.patch | 30 ++ freerdp-2.11.6-CVE-2026-24679.patch | 40 --- freerdp-2.11.6-CVE-2026-24683.patch | 103 ------ freerdp-2.11.6-CVE-2026-24684.patch | 75 ----- freerdp-2.11.6-CVE-2026-25942.patch | 102 ------ freerdp-2.11.6-CVE-2026-25959.patch | 160 ---------- freerdp-2.11.6-CVE-2026-29774.patch | 73 ----- freerdp-2.11.6-CVE-2026-29775.patch | 37 --- freerdp-2.11.6-CVE-2026-29776.patch | 26 -- freerdp-2.11.6-CVE-2026-31884.patch | 168 ---------- freerdp-2.11.6-CVE-2026-31885.patch | 219 ------------- freerdp-2.11.6-CVE-2026-31897.patch | 26 -- freerdp-2.11.6-CVE-2026-33952.patch | 27 -- freerdp-2.11.6-CVE-2026-33977.patch | 71 ----- freerdp-2.11.6-CVE-2026-33983.patch | 84 ----- freerdp-2.11.6-CVE-2026-33984.patch | 40 --- freerdp-2.11.6-CVE-2026-33985.patch | 58 ---- freerdp-2.11.6-CVE-2026-33986.patch | 45 --- freerdp-2.11.6-CVE-2026-44420.patch | 68 ---- freerdp-2.11.6-CVE-2026-44421.patch | 36 --- freerdp-2.11.6-CVE-2026-55827.patch | 297 ------------------ freerdp-2.11.6-CVE-2026-64624.patch | 57 ---- freerdp-2.11.6-nsc-limit-copy-area.patch | 19 -- freerdp.spec | 155 +++++---- freerdp_download_and_repack.sh | 18 ++ sources | 2 +- 35 files changed, 200 insertions(+), 2360 deletions(-) delete mode 100644 0001-fix-CVE-2026-23530-CVE-2026-23531-CVE-2026-23532-CVE.patch delete mode 100644 0001-fix-CVE-2026-23883.patch delete mode 100644 0001-fix-CVE-2026-26955-CVE-2026-26965.patch delete mode 100644 CVE-2024-32658.patch delete mode 100644 CVE-2024-32659.patch delete mode 100644 CVE-2024-32660.patch delete mode 100644 codec-clear-fix-clear_resize_buffer-checks.patch create mode 100644 core-rdstls-Fix-version-validation-macro.patch create mode 100644 core-rdstls-accept-matching-autoreconnect-cookies.patch create mode 100644 core-rdstls-validate-cookie-session-ID-length.patch delete mode 100644 freerdp-2.11.6-CVE-2026-24679.patch delete mode 100644 freerdp-2.11.6-CVE-2026-24683.patch delete mode 100644 freerdp-2.11.6-CVE-2026-24684.patch delete mode 100644 freerdp-2.11.6-CVE-2026-25942.patch delete mode 100644 freerdp-2.11.6-CVE-2026-25959.patch delete mode 100644 freerdp-2.11.6-CVE-2026-29774.patch delete mode 100644 freerdp-2.11.6-CVE-2026-29775.patch delete mode 100644 freerdp-2.11.6-CVE-2026-29776.patch delete mode 100644 freerdp-2.11.6-CVE-2026-31884.patch delete mode 100644 freerdp-2.11.6-CVE-2026-31885.patch delete mode 100644 freerdp-2.11.6-CVE-2026-31897.patch delete mode 100644 freerdp-2.11.6-CVE-2026-33952.patch delete mode 100644 freerdp-2.11.6-CVE-2026-33977.patch delete mode 100644 freerdp-2.11.6-CVE-2026-33983.patch delete mode 100644 freerdp-2.11.6-CVE-2026-33984.patch delete mode 100644 freerdp-2.11.6-CVE-2026-33985.patch delete mode 100644 freerdp-2.11.6-CVE-2026-33986.patch delete mode 100644 freerdp-2.11.6-CVE-2026-44420.patch delete mode 100644 freerdp-2.11.6-CVE-2026-44421.patch delete mode 100644 freerdp-2.11.6-CVE-2026-55827.patch delete mode 100644 freerdp-2.11.6-CVE-2026-64624.patch delete mode 100644 freerdp-2.11.6-nsc-limit-copy-area.patch create mode 100755 freerdp_download_and_repack.sh diff --git a/0001-fix-CVE-2026-23530-CVE-2026-23531-CVE-2026-23532-CVE.patch b/0001-fix-CVE-2026-23530-CVE-2026-23531-CVE-2026-23532-CVE.patch deleted file mode 100644 index d1ae232..0000000 --- a/0001-fix-CVE-2026-23530-CVE-2026-23531-CVE-2026-23532-CVE.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 64be7b936979a41ef8ad6969054d455ecf27c58c Mon Sep 17 00:00:00 2001 -From: xinlongchen -Date: Thu, 22 Jan 2026 19:17:13 +0800 -Subject: [PATCH] fix CVE-2026-23530 CVE-2026-23531 CVE-2026-23532 - CVE-2026-23534 - ---- - libfreerdp/codec/clear.c | 6 ++++-- - libfreerdp/codec/planar.c | 5 +++++ - libfreerdp/gdi/gfx.c | 9 +++++---- - 3 files changed, 14 insertions(+), 6 deletions(-) - -diff --git a/libfreerdp/codec/clear.c b/libfreerdp/codec/clear.c -index b889974..b2647b3 100644 ---- a/libfreerdp/codec/clear.c -+++ b/libfreerdp/codec/clear.c -@@ -873,7 +873,7 @@ static BOOL clear_decompress_bands_data(CLEAR_CONTEXT* clear, wStream* s, UINT32 - if (count > nHeight) - count = nHeight; - -- if (nXDstRel + i > nDstWidth) -+ if (nXDstRel + i >= nDstWidth) - return FALSE; - - for (UINT32 y = 0; y < count; y++) -@@ -1134,7 +1134,9 @@ INT32 clear_decompress(CLEAR_CONTEXT* clear, const BYTE* pSrcData, UINT32 SrcSiz - - if (glyphData) - { -- if (!freerdp_image_copy(glyphData, clear->format, 0, 0, 0, nWidth, nHeight, pDstData, -+ const uint32_t w = MIN(nWidth, nDstWidth); -+ const uint32_t h = MIN(nHeight, nDstHeight); -+ if (!freerdp_image_copy(glyphData, clear->format, 0, 0, 0, w, h, pDstData, - DstFormat, nDstStep, nXDst, nYDst, palette, FREERDP_FLIP_NONE)) - goto fail; - } -diff --git a/libfreerdp/codec/planar.c b/libfreerdp/codec/planar.c -index fe27011..1cb2e22 100644 ---- a/libfreerdp/codec/planar.c -+++ b/libfreerdp/codec/planar.c -@@ -616,6 +616,11 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData, UINT - WINPR_ASSERT(planar); - WINPR_ASSERT(prims); - -+ if (planar->maxWidth < nSrcWidth) -+ return FALSE; -+ if (planar->maxHeight < nSrcHeight) -+ return FALSE; -+ - if (nDstStep <= 0) - nDstStep = nDstWidth * GetBytesPerPixel(DstFormat); - -diff --git a/libfreerdp/gdi/gfx.c b/libfreerdp/gdi/gfx.c -index 3970715..968a5a1 100644 ---- a/libfreerdp/gdi/gfx.c -+++ b/libfreerdp/gdi/gfx.c -@@ -1175,7 +1175,6 @@ static UINT gdi_SurfaceToSurface(RdpgfxClientContext* context, - UINT status = ERROR_INTERNAL_ERROR; - UINT16 index; - BOOL sameSurface; -- UINT32 nWidth, nHeight; - const RECTANGLE_16* rectSrc; - RECTANGLE_16 invalidRect; - gdiGfxSurface* surfaceSrc; -@@ -1199,8 +1198,8 @@ static UINT gdi_SurfaceToSurface(RdpgfxClientContext* context, - if (!is_rect_valid(rectSrc, surfaceSrc->width, surfaceSrc->height)) - goto fail; - -- nWidth = rectSrc->right - rectSrc->left; -- nHeight = rectSrc->bottom - rectSrc->top; -+ const UINT32 nWidth = rectSrc->right - rectSrc->left; -+ const UINT32 nHeight = rectSrc->bottom - rectSrc->top; - - for (index = 0; index < surfaceToSurface->destPtsCount; index++) - { -@@ -1209,8 +1208,10 @@ static UINT gdi_SurfaceToSurface(RdpgfxClientContext* context, - if (!is_rect_valid(&rect, surfaceDst->width, surfaceDst->height)) - goto fail; - -+ const UINT32 rwidth = rect.right - rect.left; -+ const UINT32 rheight = rect.bottom - rect.top; - if (!freerdp_image_copy(surfaceDst->data, surfaceDst->format, surfaceDst->scanline, -- destPt->x, destPt->y, nWidth, nHeight, surfaceSrc->data, -+ destPt->x, destPt->y, rwidth, rheight, surfaceSrc->data, - surfaceSrc->format, surfaceSrc->scanline, rectSrc->left, - rectSrc->top, NULL, FREERDP_FLIP_NONE)) - goto fail; --- -2.41.1 - diff --git a/0001-fix-CVE-2026-23883.patch b/0001-fix-CVE-2026-23883.patch deleted file mode 100644 index 0e03ab9..0000000 --- a/0001-fix-CVE-2026-23883.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 2ec90f86ee2b3992df734fe97f62d9f67bf89055 Mon Sep 17 00:00:00 2001 -From: xinlongchen -Date: Thu, 22 Jan 2026 19:27:04 +0800 -Subject: [PATCH] fix CVE-2026-23883 - ---- - client/X11/xf_graphics.c | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) - -diff --git a/client/X11/xf_graphics.c b/client/X11/xf_graphics.c -index 5aa1fd4..48603c1 100644 ---- a/client/X11/xf_graphics.c -+++ b/client/X11/xf_graphics.c -@@ -406,7 +406,6 @@ static BOOL xf_Pointer_New(rdpContext* context, rdpPointer* pointer) - BOOL rc = FALSE; - #ifdef WITH_XCURSOR - UINT32 CursorFormat; -- size_t size; - xfContext* xfc = (xfContext*)context; - xfPointer* xpointer = (xfPointer*)pointer; - -@@ -421,9 +420,12 @@ static BOOL xf_Pointer_New(rdpContext* context, rdpPointer* pointer) - xpointer->nCursors = 0; - xpointer->mCursors = 0; - -- size = 1ull * pointer->height * pointer->width * GetBytesPerPixel(CursorFormat); -+ const size_t size = -+ 1ull * pointer->height * pointer->width * GetBytesPerPixel(CursorFormat); -+ - -- if (!(xpointer->cursorPixels = (XcursorPixel*)_aligned_malloc(size, 16))) -+ xpointer->cursorPixels = (XcursorPixel*)_aligned_malloc(size, 16); -+ if (!xpointer->cursorPixels) - goto fail; - - if (!freerdp_image_copy_from_pointer_data( -@@ -431,7 +433,6 @@ static BOOL xf_Pointer_New(rdpContext* context, rdpPointer* pointer) - pointer->xorMaskData, pointer->lengthXorMask, pointer->andMaskData, - pointer->lengthAndMask, pointer->xorBpp, &context->gdi->palette)) - { -- _aligned_free(xpointer->cursorPixels); - return FALSE; - } - rc = TRUE; --- -2.41.1 - diff --git a/0001-fix-CVE-2026-26955-CVE-2026-26965.patch b/0001-fix-CVE-2026-26955-CVE-2026-26965.patch deleted file mode 100644 index 70bf930..0000000 --- a/0001-fix-CVE-2026-26955-CVE-2026-26965.patch +++ /dev/null @@ -1,58 +0,0 @@ -From cf5c93544a0b4c1f734e14e3cde19312583cb33c Mon Sep 17 00:00:00 2001 -From: xinlongchen -Date: Tue, 3 Mar 2026 16:19:01 +0800 -Subject: [PATCH] fix CVE-2026-26955 CVE-2026-26965 - ---- - libfreerdp/codec/planar.c | 12 +++++++++++- - libfreerdp/gdi/gfx.c | 3 +++ - 2 files changed, 14 insertions(+), 1 deletion(-) - -diff --git a/libfreerdp/codec/planar.c b/libfreerdp/codec/planar.c -index 1cb2e22..ecc4128 100644 ---- a/libfreerdp/codec/planar.c -+++ b/libfreerdp/codec/planar.c -@@ -621,8 +621,9 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData, UINT - if (planar->maxHeight < nSrcHeight) - return FALSE; - -+ const UINT32 bpp = GetBytesPerPixel(DstFormat); - if (nDstStep <= 0) -- nDstStep = nDstWidth * GetBytesPerPixel(DstFormat); -+ nDstStep = nDstWidth * bpp; - - srcp = pSrcData; - -@@ -831,6 +832,15 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData, UINT - } - else /* RLE */ - { -+ if (nYDst + nSrcHeight > nTotalHeight) -+ { -+ return FALSE; -+ } -+ -+ if ((nXDst + nSrcWidth) * bpp > nDstStep) -+ { -+ return FALSE; -+ } - status = - planar_decompress_plane_rle(planes[0], rleSizes[0], pTempData, nTempStep, nXDst, - nYDst, nSrcWidth, nSrcHeight, 2, vFlip); /* RedPlane */ -diff --git a/libfreerdp/gdi/gfx.c b/libfreerdp/gdi/gfx.c -index 968a5a1..0d9e8ce 100644 ---- a/libfreerdp/gdi/gfx.c -+++ b/libfreerdp/gdi/gfx.c -@@ -384,6 +384,9 @@ static UINT gdi_SurfaceCommand_ClearCodec(rdpGdi* gdi, RdpgfxClientContext* cont - return ERROR_NOT_FOUND; - } - -+ if (!is_within_surface(surface, cmd)) -+ return ERROR_INVALID_DATA; -+ - rc = clear_decompress(surface->codecs->clear, cmd->data, cmd->length, cmd->width, cmd->height, - surface->data, surface->format, surface->scanline, cmd->left, cmd->top, - surface->width, surface->height, &gdi->palette); --- -2.41.1 - diff --git a/CVE-2024-32658.patch b/CVE-2024-32658.patch deleted file mode 100644 index e6978a2..0000000 --- a/CVE-2024-32658.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 2b9f30a2fa4b13559a367f7cbe158e1bafe0f482 Mon Sep 17 00:00:00 2001 -From: akallabeth -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 d4d291699e12..e419876e6628 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; diff --git a/CVE-2024-32659.patch b/CVE-2024-32659.patch deleted file mode 100644 index 5c37766..0000000 --- a/CVE-2024-32659.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 8b9ad6cf80a2233de22b3b5100d642d876ef9a6e Mon Sep 17 00:00:00 2001 -From: akallabeth -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 00919983c343..f8467c295eb7 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); - diff --git a/CVE-2024-32660.patch b/CVE-2024-32660.patch deleted file mode 100644 index e3b8a70..0000000 --- a/CVE-2024-32660.patch +++ /dev/null @@ -1,148 +0,0 @@ -From 0381b3bef6e09b17576445186d26a07ec3772b1a Mon Sep 17 00:00:00 2001 -From: akallabeth -Date: Sat, 20 Apr 2024 19:59:48 +0200 -Subject: [PATCH] [codec,zgfx] 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. - -(cherry picked from commit 5e5d27cf310e4c10b854be7667bfb7a5d774eb47) ---- - libfreerdp/codec/zgfx.c | 77 +++++++++++++++++++++++++---------------- - 1 file changed, 47 insertions(+), 30 deletions(-) - -diff --git a/libfreerdp/codec/zgfx.c b/libfreerdp/codec/zgfx.c -index b7b96ade0c58..c63229480499 100644 ---- a/libfreerdp/codec/zgfx.c -+++ b/libfreerdp/codec/zgfx.c -@@ -385,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; -@@ -405,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) - { -@@ -422,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; -@@ -431,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)) -@@ -452,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 - { -@@ -470,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; - } diff --git a/codec-clear-fix-clear_resize_buffer-checks.patch b/codec-clear-fix-clear_resize_buffer-checks.patch deleted file mode 100644 index 45e2d25..0000000 --- a/codec-clear-fix-clear_resize_buffer-checks.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 00a593f9eda67212539e4dcac68ea5a699eb3e93 Mon Sep 17 00:00:00 2001 -From: Ondrej Holy -Date: Thu, 22 Jan 2026 12:48:37 +0100 -Subject: [PATCH] [codec,clear] fix clear_resize_buffer checks - -Backport of commit c4391827d7facfc874ca7f61a92afb82232a5748. - -Co-Authored-By: Claude ---- - libfreerdp/codec/clear.c | 17 +++++++++-------- - 1 file changed, 9 insertions(+), 8 deletions(-) - -diff --git a/libfreerdp/codec/clear.c b/libfreerdp/codec/clear.c -index e38fa0dcf..299acef2e 100644 ---- a/libfreerdp/codec/clear.c -+++ b/libfreerdp/codec/clear.c -@@ -62,7 +62,7 @@ struct _CLEAR_CONTEXT - NSC_CONTEXT* nsc; - UINT32 seqNumber; - BYTE* TempBuffer; -- UINT32 TempSize; -+ size_t TempSize; - UINT32 nTempStep; - UINT32 TempFormat; - UINT32 format; -@@ -313,24 +313,25 @@ static BOOL clear_decompress_subcode_rlex(wStream* s, UINT32 bitmapDataByteCount - - static BOOL clear_resize_buffer(CLEAR_CONTEXT* clear, UINT32 width, UINT32 height) - { -- UINT32 size; -- - if (!clear) - return FALSE; - -- size = ((width + 16) * (height + 16) * GetBytesPerPixel(clear->format)); -+ const UINT64 size = 1ull * (width + 16ull) * (height + 16ull); -+ const size_t bpp = GetBytesPerPixel(clear->format); -+ if (size > UINT32_MAX / bpp) -+ return FALSE; - -- if (size > clear->TempSize) -+ if (size > clear->TempSize / bpp) - { -- BYTE* tmp = (BYTE*)realloc(clear->TempBuffer, size); -+ BYTE* tmp = (BYTE*)realloc(clear->TempBuffer, size * bpp); - - if (!tmp) - { -- WLog_ERR(TAG, "clear->TempBuffer realloc failed for %" PRIu32 " bytes", size); -+ WLog_ERR(TAG, "clear->TempBuffer realloc failed for %" PRIu64 " bytes", size); - return FALSE; - } - -- clear->TempSize = size; -+ clear->TempSize = size * bpp; - clear->TempBuffer = tmp; - } - --- -2.52.0 - - diff --git a/core-rdstls-Fix-version-validation-macro.patch b/core-rdstls-Fix-version-validation-macro.patch new file mode 100644 index 0000000..fcbcaa9 --- /dev/null +++ b/core-rdstls-Fix-version-validation-macro.patch @@ -0,0 +1,32 @@ +From 8cc061211378a621908ee7056977bc855e870c7c Mon Sep 17 00:00:00 2001 +From: Ondrej Holy +Date: Mon, 14 Sep 2026 13:32:45 +0200 +Subject: [PATCH] [core,rdstls] Fix version validation macro + +Currently, `rdstls_is_version_supported` ignores its second argument because +of the `versions` versus `version` typo. This can select a different local +variable or fail to compile. However, all calls pass local `version`, so this +works currently and does not cause a bug. Let us pass the supplied argument +instead. + +Co-Authored-By: GPT-5 +--- + libfreerdp/core/rdstls.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libfreerdp/core/rdstls.c b/libfreerdp/core/rdstls.c +index 1dd84de01e..fff802a81c 100644 +--- a/libfreerdp/core/rdstls.c ++++ b/libfreerdp/core/rdstls.c +@@ -612,7 +612,7 @@ static BOOL rdstls_are_some_versions_supported_(wLog* log, uint16_t version, BOO + return TRUE; + } + +-#define rdstls_is_version_supported(rdstls, versions) \ ++#define rdstls_is_version_supported(rdstls, version) \ + rdstls_is_version_supported_((rdstls), (version), __FILE__, __func__, __LINE__) + WINPR_ATTR_NODISCARD + static BOOL rdstls_is_version_supported_(rdpRdstls* rdstls, uint16_t version, const char* file, +-- +2.54.0 + diff --git a/core-rdstls-accept-matching-autoreconnect-cookies.patch b/core-rdstls-accept-matching-autoreconnect-cookies.patch new file mode 100644 index 0000000..f1ebadc --- /dev/null +++ b/core-rdstls-accept-matching-autoreconnect-cookies.patch @@ -0,0 +1,31 @@ +From bab8c7126257d762a6a24ae90578d9c6fa5cd91a Mon Sep 17 00:00:00 2001 +From: Ondrej Holy +Date: Tue, 15 Sep 2026 13:19:07 +0200 +Subject: [PATCH] [core,rdstls] accept matching autoreconnect cookies + +Currently, matching cookies leave `resultCode` at access denied and return +`FALSE`. This aborts authentication before a response is sent. Let's mark +matching cookies as successful and complete request handling. + +Co-Authored-By: GPT-5 +--- + libfreerdp/core/rdstls.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/libfreerdp/core/rdstls.c b/libfreerdp/core/rdstls.c +index fff802a81c..911e8cdf68 100644 +--- a/libfreerdp/core/rdstls.c ++++ b/libfreerdp/core/rdstls.c +@@ -875,7 +875,8 @@ static BOOL rdstls_process_authentication_request_with_cookie(rdpRdstls* rdstls, + } + + WLog_Print(rdstls->log, WLOG_DEBUG, "RDSTLS Cookie matches. Grant access."); +- return FALSE; ++ rdstls->resultCode = RDSTLS_RESULT_SUCCESS; ++ return TRUE; + } + + WINPR_ATTR_NODISCARD +-- +2.54.0 + diff --git a/core-rdstls-validate-cookie-session-ID-length.patch b/core-rdstls-validate-cookie-session-ID-length.patch new file mode 100644 index 0000000..898dfbd --- /dev/null +++ b/core-rdstls-validate-cookie-session-ID-length.patch @@ -0,0 +1,30 @@ +From 7bfd78bbd247e46771b8de36ece3ff76d22b114c Mon Sep 17 00:00:00 2001 +From: Ondrej Holy +Date: Tue, 15 Sep 2026 13:22:00 +0200 +Subject: [PATCH] [core,rdstls] validate cookie session ID length + +Currently, the cookie handler verifies two bytes before reading four bytes of +session ID. A truncated request can be read beyond its available input. Let's +require the complete session ID before reading it. + +Co-Authored-By: GPT-5 +--- + libfreerdp/core/rdstls.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libfreerdp/core/rdstls.c b/libfreerdp/core/rdstls.c +index 911e8cdf68..75b380b649 100644 +--- a/libfreerdp/core/rdstls.c ++++ b/libfreerdp/core/rdstls.c +@@ -841,7 +841,7 @@ static BOOL rdstls_process_authentication_request_with_cookie(rdpRdstls* rdstls, + if (!rdstls_check_state_requirements(rdstls, RDSTLS_STATE_AUTH_REQ)) + return FALSE; + +- if (!Stream_CheckAndLogRequiredLengthWLog(rdstls->log, s, 2)) ++ if (!Stream_CheckAndLogRequiredLengthWLog(rdstls->log, s, 4)) + return FALSE; + + const rdpSettings* settings = rdstls->context->settings; +-- +2.54.0 + diff --git a/freerdp-2.11.6-CVE-2026-24679.patch b/freerdp-2.11.6-CVE-2026-24679.patch deleted file mode 100644 index b5c69ab..0000000 --- a/freerdp-2.11.6-CVE-2026-24679.patch +++ /dev/null @@ -1,40 +0,0 @@ -From b2345d0142bc741cb35894db06dddca2e4c19439 Mon Sep 17 00:00:00 2001 -From: akallabeth -Date: Mon, 26 Jan 2026 10:59:39 +0100 -Subject: [PATCH] [channels,urbdrc] ensure InterfaceNumber is within range - -(cherry picked from commit 2d563a50be17c1b407ca448b1321378c0726dd31) ---- - channels/urbdrc/client/libusb/libusb_udevice.c | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/channels/urbdrc/client/libusb/libusb_udevice.c b/channels/urbdrc/client/libusb/libusb_udevice.c -index 38f76f5593dd..5cc6726c8736 100644 ---- a/channels/urbdrc/client/libusb/libusb_udevice.c -+++ b/channels/urbdrc/client/libusb/libusb_udevice.c -@@ -528,19 +528,19 @@ static int libusb_udev_select_interface(IUDEVICE* idev, BYTE InterfaceNumber, BY - { - int error = 0, diff = 0; - UDEVICE* pdev = (UDEVICE*)idev; -- URBDRC_PLUGIN* urbdrc; -- MSUSB_CONFIG_DESCRIPTOR* MsConfig; -- MSUSB_INTERFACE_DESCRIPTOR** MsInterfaces; - - if (!pdev || !pdev->urbdrc) - return -1; - -- urbdrc = pdev->urbdrc; -- MsConfig = pdev->MsConfig; -+ URBDRC_PLUGIN* urbdrc = pdev->urbdrc; -+ MSUSB_CONFIG_DESCRIPTOR* MsConfig = pdev->MsConfig; - - if (MsConfig) - { -- MsInterfaces = MsConfig->MsInterfaces; -+ if (InterfaceNumber >= MsConfig->NumInterfaces) -+ return -2; -+ -+ MSUSB_INTERFACE_DESCRIPTOR** MsInterfaces = MsConfig->MsInterfaces; - if (MsInterfaces) - { - WLog_Print(urbdrc->log, WLOG_INFO, diff --git a/freerdp-2.11.6-CVE-2026-24683.patch b/freerdp-2.11.6-CVE-2026-24683.patch deleted file mode 100644 index c32a321..0000000 --- a/freerdp-2.11.6-CVE-2026-24683.patch +++ /dev/null @@ -1,103 +0,0 @@ -From dea45312c1aa9f2797696ad5f56a8809de1f03c3 Mon Sep 17 00:00:00 2001 -From: vulgraph <216388001+vulgraph@users.noreply.github.com> -Date: Fri, 1 May 2026 20:53:56 +0800 -Subject: [PATCH] [channels,ainput] lock context when updating listener - -Backport of d9ca272dce7a776ab475e9b1a8e8c3d2968c8486 to stable-2.0. - -Adapted to stable-2.0 plugin layout (no GENERIC_DYNVC_PLUGIN base): -- Lock initialization moved to DVCPluginEntry where the plugin is - allocated; deletion added to ainput_plugin_terminated. -- Callback type adjusted: AINPUT_CHANNEL_CALLBACK (vs upstream's - GENERIC_CHANNEL_CALLBACK) accessed via ainput->listener_callback - rather than ainput->base.listener_callback. -- Variable declarations hoisted to start of function for stable-2.0 - C89-compatible style. - -(cherry picked from commit d9ca272dce7a776ab475e9b1a8e8c3d2968c8486) ---- - channels/ainput/client/ainput_main.c | 26 +++++++++++++++++++++----- - 1 file changed, 21 insertions(+), 5 deletions(-) - -diff --git a/channels/ainput/client/ainput_main.c b/channels/ainput/client/ainput_main.c -index d8eb8ec594b6..0f44b309213c 100644 ---- a/channels/ainput/client/ainput_main.c -+++ b/channels/ainput/client/ainput_main.c -@@ -69,6 +69,7 @@ struct AINPUT_PLUGIN_ - UINT32 MajorVersion; - UINT32 MinorVersion; - BOOL initialized; -+ CRITICAL_SECTION lock; - }; - - /** -@@ -113,6 +114,7 @@ static UINT ainput_send_input_event(AInputClientContext* context, UINT64 flags, - AINPUT_CHANNEL_CALLBACK* callback; - BYTE buffer[32] = { 0 }; - UINT64 time; -+ UINT rc; - wStream sbuffer = { 0 }; - wStream* s = &sbuffer; - -@@ -132,8 +134,6 @@ static UINT ainput_send_input_event(AInputClientContext* context, UINT64 flags, - ainput->MajorVersion, ainput->MinorVersion); - return CHANNEL_RC_UNSUPPORTED_VERSION; - } -- callback = ainput->listener_callback->channel_callback; -- WINPR_ASSERT(callback); - - { - char buffer[128] = { 0 }; -@@ -152,10 +152,15 @@ static UINT ainput_send_input_event(AInputClientContext* context, UINT64 flags, - Stream_SealLength(s); - - /* ainput back what we have received. AINPUT does not have any message IDs. */ -+ EnterCriticalSection(&ainput->lock); -+ callback = ainput->listener_callback->channel_callback; -+ WINPR_ASSERT(callback); - WINPR_ASSERT(callback->channel); - WINPR_ASSERT(callback->channel->Write); -- return callback->channel->Write(callback->channel, (ULONG)Stream_Length(s), Stream_Buffer(s), -- NULL); -+ rc = callback->channel->Write(callback->channel, (ULONG)Stream_Length(s), Stream_Buffer(s), -+ NULL); -+ LeaveCriticalSection(&ainput->lock); -+ return rc; - } - - /** -@@ -167,8 +172,16 @@ static UINT ainput_on_close(IWTSVirtualChannelCallback* pChannelCallback) - { - AINPUT_CHANNEL_CALLBACK* callback = (AINPUT_CHANNEL_CALLBACK*)pChannelCallback; - -- free(callback); -+ if (callback) -+ { -+ AINPUT_PLUGIN* ainput = (AINPUT_PLUGIN*)callback->plugin; -+ WINPR_ASSERT(ainput); - -+ /* Lock here to ensure that no ainput_send_input_event is in progress. */ -+ EnterCriticalSection(&ainput->lock); -+ free(callback); -+ LeaveCriticalSection(&ainput->lock); -+ } - return CHANNEL_RC_OK; - } - -@@ -263,6 +276,7 @@ static UINT ainput_plugin_terminated(IWTSPlugin* pPlugin) - } - if (ainput) - { -+ DeleteCriticalSection(&ainput->lock); - free(ainput->listener_callback); - free(ainput->iface.pInterface); - } -@@ -304,6 +318,8 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) - ainput->iface.Initialize = ainput_plugin_initialize; - ainput->iface.Terminated = ainput_plugin_terminated; - -+ InitializeCriticalSection(&ainput->lock); -+ - context->handle = (void*)ainput; - context->AInputSendInputEvent = ainput_send_input_event; - ainput->iface.pInterface = (void*)context; diff --git a/freerdp-2.11.6-CVE-2026-24684.patch b/freerdp-2.11.6-CVE-2026-24684.patch deleted file mode 100644 index 48c561d..0000000 --- a/freerdp-2.11.6-CVE-2026-24684.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 13dd4912e28b7a699afc2b7ad24797f9702b75fc Mon Sep 17 00:00:00 2001 -From: vulgraph -Date: Sun, 3 May 2026 20:44:15 +0800 -Subject: [PATCH] [channels,rdpsnd] terminate thread before free - -Backport of upstream commit 622bb7b4402491ca003f47472d0e478132673696 -to the stable-2.0 branch. Addresses CVE-2026-24684. - -The original cleanup_internals() did not terminate the rdpsnd helper -thread before releasing channel context memory, so any pending callback -on that thread could observe freed audio_formats / pool state. - -This change extracts the existing terminate-and-free logic into -rdpsnd_terminate_thread() and calls it at the start of -cleanup_internals(). rdpsnd_virtual_channel_event_terminated() now uses -the same helper, mirroring the upstream layout. - -Compiles cleanly on stable-2.0; no public API change. ---- - channels/rdpsnd/client/rdpsnd_main.c | 30 ++++++++++++++++++++-------- - 1 file changed, 22 insertions(+), 8 deletions(-) - -diff --git a/channels/rdpsnd/client/rdpsnd_main.c b/channels/rdpsnd/client/rdpsnd_main.c -index 3de4cbc66bb0..9af5ead32f2c 100644 ---- a/channels/rdpsnd/client/rdpsnd_main.c -+++ b/channels/rdpsnd/client/rdpsnd_main.c -@@ -1244,11 +1244,32 @@ static UINT rdpsnd_virtual_channel_event_connected(rdpsndPlugin* rdpsnd, LPVOID - return CHANNEL_RC_NO_MEMORY; - } - -+static void rdpsnd_terminate_thread(rdpsndPlugin* rdpsnd) -+{ -+ if (!rdpsnd) -+ return; -+ -+ if (rdpsnd->queue) -+ MessageQueue_PostQuit(rdpsnd->queue, 0); -+ -+ if (rdpsnd->thread) -+ { -+ WaitForSingleObject(rdpsnd->thread, INFINITE); -+ CloseHandle(rdpsnd->thread); -+ } -+ -+ MessageQueue_Free(rdpsnd->queue); -+ rdpsnd->thread = NULL; -+ rdpsnd->queue = NULL; -+} -+ - static void cleanup_internals(rdpsndPlugin* rdpsnd) - { - if (!rdpsnd) - return; - -+ rdpsnd_terminate_thread(rdpsnd); -+ - if (rdpsnd->pool) - StreamPool_Return(rdpsnd->pool, rdpsnd->data_in); - -@@ -1396,14 +1417,7 @@ void rdpsnd_virtual_channel_event_terminated(rdpsndPlugin* rdpsnd) - { - if (rdpsnd) - { -- if (rdpsnd->queue) -- MessageQueue_PostQuit(rdpsnd->queue, 0); -- if (rdpsnd->thread) -- { -- WaitForSingleObject(rdpsnd->thread, INFINITE); -- CloseHandle(rdpsnd->thread); -- } -- MessageQueue_Free(rdpsnd->queue); -+ rdpsnd_terminate_thread(rdpsnd); - - free_internals(rdpsnd); - audio_formats_free(rdpsnd->fixed_format, 1); diff --git a/freerdp-2.11.6-CVE-2026-25942.patch b/freerdp-2.11.6-CVE-2026-25942.patch deleted file mode 100644 index 1a71998..0000000 --- a/freerdp-2.11.6-CVE-2026-25942.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 75fb359eebf2c5248362c8259d932eeab5134e59 Mon Sep 17 00:00:00 2001 -From: Armin Novak -Date: Mon, 9 Feb 2026 13:39:28 +0100 -Subject: [PATCH] [client,x11] stringfiy functions for RAILS - ---- - client/X11/xf_rail.c | 68 ++++++++++++++++++++++++++++++++------------ - 1 file changed, 50 insertions(+), 18 deletions(-) - -diff --git a/client/X11/xf_rail.c b/client/X11/xf_rail.c -index fdc2244e9f90..c4f7173af502 100644 ---- a/client/X11/xf_rail.c -+++ b/client/X11/xf_rail.c -@@ -33,22 +33,51 @@ - - #define TAG CLIENT_TAG("x11") - --static const char* error_code_names[] = { "RAIL_EXEC_S_OK", -- "RAIL_EXEC_E_HOOK_NOT_LOADED", -- "RAIL_EXEC_E_DECODE_FAILED", -- "RAIL_EXEC_E_NOT_IN_ALLOWLIST", -- "RAIL_EXEC_E_FILE_NOT_FOUND", -- "RAIL_EXEC_E_FAIL", -- "RAIL_EXEC_E_SESSION_LOCKED" }; -- --#ifdef WITH_DEBUG_RAIL --static const char* movetype_names[] = { -- "(invalid)", "RAIL_WMSZ_LEFT", "RAIL_WMSZ_RIGHT", -- "RAIL_WMSZ_TOP", "RAIL_WMSZ_TOPLEFT", "RAIL_WMSZ_TOPRIGHT", -- "RAIL_WMSZ_BOTTOM", "RAIL_WMSZ_BOTTOMLEFT", "RAIL_WMSZ_BOTTOMRIGHT", -- "RAIL_WMSZ_MOVE", "RAIL_WMSZ_KEYMOVE", "RAIL_WMSZ_KEYSIZE" --}; --#endif -+static const char* error_code2str(UINT32 code) -+{ -+#define EVCASE(x) \ -+ case x: \ -+ return #x -+ switch (code) -+ { -+ EVCASE(RAIL_EXEC_S_OK); -+ EVCASE(RAIL_EXEC_E_HOOK_NOT_LOADED); -+ EVCASE(RAIL_EXEC_E_DECODE_FAILED); -+ EVCASE(RAIL_EXEC_E_NOT_IN_ALLOWLIST); -+ EVCASE(RAIL_EXEC_E_FILE_NOT_FOUND); -+ EVCASE(RAIL_EXEC_E_FAIL); -+ EVCASE(RAIL_EXEC_E_SESSION_LOCKED); -+ default: -+ return "RAIL_EXEC_E_UNKNOWN"; -+ } -+#undef EVCASE -+} -+ -+static const char* movetype2str(UINT32 code) -+{ -+#define EVCASE(x) \ -+ case x: \ -+ return #x -+ -+ switch (code) -+ { -+ -+ EVCASE(RAIL_WMSZ_LEFT); -+ EVCASE(RAIL_WMSZ_RIGHT); -+ EVCASE(RAIL_WMSZ_TOP); -+ EVCASE(RAIL_WMSZ_TOPLEFT); -+ EVCASE(RAIL_WMSZ_TOPRIGHT); -+ EVCASE(RAIL_WMSZ_BOTTOM); -+ EVCASE(RAIL_WMSZ_BOTTOMLEFT); -+ EVCASE(RAIL_WMSZ_BOTTOMRIGHT); -+ EVCASE(RAIL_WMSZ_MOVE); -+ EVCASE(RAIL_WMSZ_KEYMOVE); -+ EVCASE(RAIL_WMSZ_KEYSIZE); -+ default: -+ return "RAIL_WMSZ_INVALID"; -+ } -+#undef EVCASE -+} - - struct xf_rail_icon - { -@@ -804,8 +833,9 @@ static UINT xf_rail_server_execute_result(RailClientContext* context, - - if (execResult->execResult != RAIL_EXEC_S_OK) - { -- WLog_ERR(TAG, "RAIL exec error: execResult=%s NtError=0x%X\n", -- error_code_names[execResult->execResult], execResult->rawResult); -+ WLog_ERR(TAG, "RAIL exec error: execResult=%s [0x%08" PRIx32 "] NtError=0x%X\n", -+ error_code2str(execResult->execResult), execResult->execResult, -+ execResult->rawResult); - freerdp_abort_connect(xfc->context.instance); - } - else -@@ -936,6 +966,8 @@ static UINT xf_rail_server_local_move_size(RailClientContext* context, - if (!appWindow) - return ERROR_INTERNAL_ERROR; - -+ WLog_DBG(TAG, "%s [0x%08" PRIx32 "]", -+ movetype2str(localMoveSize->moveSizeType), localMoveSize->moveSizeType); - switch (localMoveSize->moveSizeType) - { - case RAIL_WMSZ_LEFT: diff --git a/freerdp-2.11.6-CVE-2026-25959.patch b/freerdp-2.11.6-CVE-2026-25959.patch deleted file mode 100644 index 7f5c690..0000000 --- a/freerdp-2.11.6-CVE-2026-25959.patch +++ /dev/null @@ -1,160 +0,0 @@ -From 62826906f848cc72cee07443e0f7f3f6b26c6c80 Mon Sep 17 00:00:00 2001 -From: Armin Novak -Date: Mon, 9 Feb 2026 17:52:37 +0100 -Subject: [PATCH] [client,x11] lock cache when providing data (CVE-2026-25959) - -Backport of upstream commit d3e8b3b9365be96a4f11dda149d71b3287227d0a -to stable-2.0. - -The stable-2.0 cliprdr cache is a pair of plain pointers -(clipboard->data and clipboard->data_raw), not the upstream wHashTable -introduced after the 2.x line. The same race exists, however: - - - xf_cliprdr_server_format_data_response runs on the cliprdr channel - thread. It calls xf_cliprdr_clear_cached_data (free + NULL) and - then re-populates clipboard->data / data_raw. - - xf_cliprdr_process_selection_request runs on the X11 event thread - and reads clipboard->data / data_raw, passing them to - xf_cliprdr_provide_data -> XChangeProperty. - -If the channel thread's free races with the X11 thread's read, the -X11 thread can hand a freed buffer to XChangeProperty (heap UAF). - -Mirror the upstream fix by introducing a CRITICAL_SECTION protecting -the cache, and lock around every site that reads, writes, or frees -clipboard->data / data_raw: - - * xf_cliprdr_process_selection_request - lock around the read + - provide_data + (else branch) clear+request_data block. - * xf_cliprdr_server_format_list - lock around the clear call. - * xf_cliprdr_server_format_data_response - lock from the initial - clear through provide_data, including the early-return on - SrcSize == 0. - -Lock is initialized in xf_clipboard_new (with a clean-up in the -error path) and destroyed in xf_clipboard_free. - -Source: https://github.com/FreeRDP/FreeRDP/commit/d3e8b3b9365be96a4f11dda149d71b3287227d0a ---- - client/X11/xf_cliprdr.c | 37 +++++++++++++++++++++++++++++++++++++ - 1 file changed, 37 insertions(+) - -diff --git a/client/X11/xf_cliprdr.c b/client/X11/xf_cliprdr.c -index 6c83fadaaf38..513c79c2462c 100644 ---- a/client/X11/xf_cliprdr.c -+++ b/client/X11/xf_cliprdr.c -@@ -34,6 +34,7 @@ - #include - #include - #include -+#include - #include - - #include -@@ -115,6 +116,14 @@ struct xf_clipboard - /* last sent data */ - CLIPRDR_FORMAT* lastSentFormats; - UINT32 lastSentNumFormats; -+ -+ /* Lock protecting clipboard->data / data_raw cache against races -+ * between the X11 event thread (reader in -+ * xf_cliprdr_process_selection_request) and the cliprdr channel -+ * thread (writer in xf_cliprdr_server_format_data_response and -+ * xf_cliprdr_clear_cached_data). Backport of upstream commit -+ * d3e8b3b9365be96a4f11dda149d71b3287227d0a (CVE-2026-25959). */ -+ CRITICAL_SECTION lock; - }; - - static UINT xf_cliprdr_send_client_format_list(xfClipboard* clipboard); -@@ -1002,6 +1011,13 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard, - matchingFormat = (formatId == clipboard->data_format_id) && - (formatName == clipboard->data_format_name); - -+ /* Lock the cached data while we read/free it. The cliprdr -+ * channel thread may concurrently free and re-populate -+ * clipboard->data / clipboard->data_raw via -+ * xf_cliprdr_server_format_data_response, leading to a heap -+ * use-after-free passed to XChangeProperty (CVE-2026-25959). */ -+ EnterCriticalSection(&clipboard->lock); -+ - if (matchingFormat && (clipboard->data != 0) && !rawTransfer) - { - /* Cached converted clipboard data available. Send it now */ -@@ -1035,6 +1051,8 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard, - delayRespond = TRUE; - xf_cliprdr_send_data_request(clipboard, formatId); - } -+ -+ LeaveCriticalSection(&clipboard->lock); - } - } - -@@ -1360,7 +1378,9 @@ static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context, - xfContext* xfc = clipboard->xfc; - UINT ret; - xf_clipboard_formats_free(clipboard); -+ EnterCriticalSection(&clipboard->lock); - xf_cliprdr_clear_cached_data(clipboard); -+ LeaveCriticalSection(&clipboard->lock); - clipboard->data_format_id = -1; - clipboard->data_format_name = NULL; - -@@ -1510,6 +1530,12 @@ xf_cliprdr_server_format_data_response(CliprdrClientContext* context, - if (!clipboard->respond) - return CHANNEL_RC_OK; - -+ /* Hold the cache lock from the moment we drop the previous cached -+ * data through producing and consuming the new cached data, so the -+ * X11 event thread can never observe a freed pointer. Backport of -+ * upstream commit d3e8b3b9365be96a4f11dda149d71b3287227d0a -+ * (CVE-2026-25959). */ -+ EnterCriticalSection(&clipboard->lock); - xf_cliprdr_clear_cached_data(clipboard); - pDstData = NULL; - DstSize = 0; -@@ -1579,6 +1605,7 @@ xf_cliprdr_server_format_data_response(CliprdrClientContext* context, - WLog_DBG(TAG, "skipping, empty data detected!"); - free(clipboard->respond); - clipboard->respond = NULL; -+ LeaveCriticalSection(&clipboard->lock); - return CHANNEL_RC_OK; - } - -@@ -1620,6 +1647,7 @@ xf_cliprdr_server_format_data_response(CliprdrClientContext* context, - } - - xf_cliprdr_provide_data(clipboard, clipboard->respond, pDstData, DstSize); -+ LeaveCriticalSection(&clipboard->lock); - { - union - { -@@ -1795,6 +1823,13 @@ xfClipboard* xf_clipboard_new(xfContext* xfc, BOOL relieveFilenameRestriction) - return NULL; - } - -+ if (!InitializeCriticalSectionAndSpinCount(&clipboard->lock, 4000)) -+ { -+ WLog_ERR(TAG, "failed to initialize clipboard cache lock"); -+ free(clipboard); -+ return NULL; -+ } -+ - xfc->clipboard = clipboard; - clipboard->xfc = xfc; - channels = ((rdpContext*)xfc)->channels; -@@ -1925,6 +1960,7 @@ xfClipboard* xf_clipboard_new(xfContext* xfc, BOOL relieveFilenameRestriction) - free(clipboard->clientFormats[i].formatName); - - ClipboardDestroy(clipboard->system); -+ DeleteCriticalSection(&clipboard->lock); - free(clipboard); - return NULL; - } -@@ -1957,6 +1993,7 @@ void xf_clipboard_free(xfClipboard* clipboard) - free(clipboard->data_raw); - free(clipboard->respond); - free(clipboard->incr_data); -+ DeleteCriticalSection(&clipboard->lock); - free(clipboard); - } - diff --git a/freerdp-2.11.6-CVE-2026-29774.patch b/freerdp-2.11.6-CVE-2026-29774.patch deleted file mode 100644 index 13212a2..0000000 --- a/freerdp-2.11.6-CVE-2026-29774.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 4da3d3c3338777ce1b4a01b81033b030ac304b7d Mon Sep 17 00:00:00 2001 -From: Armin Novak -Date: Sat, 28 Feb 2026 11:38:23 +0100 -Subject: [PATCH] [codec,h264] validate rectangles before use - -(cherry picked from commit 6482b7a92fff3959582cef052d1967ad6bde3738) ---- - libfreerdp/codec/h264.c | 38 ++++++++++++++++++++++++++++++++++++++ - 1 file changed, 38 insertions(+) - -diff --git a/libfreerdp/codec/h264.c b/libfreerdp/codec/h264.c -index 3f1ddb34090f..7bc4a147cc00 100644 ---- a/libfreerdp/codec/h264.c -+++ b/libfreerdp/codec/h264.c -@@ -165,6 +165,36 @@ static BOOL avc_yuv_to_rgb(H264_CONTEXT* h264, const RECTANGLE_16* regionRects, - return TRUE; - } - -+static BOOL isRectValid(UINT32 width, UINT32 height, const RECTANGLE_16* rect) -+{ -+ WINPR_ASSERT(rect); -+ if (rect->left > width) -+ return FALSE; -+ if (rect->right > width) -+ return FALSE; -+ if (rect->left >= rect->right) -+ return FALSE; -+ if (rect->top > height) -+ return FALSE; -+ if (rect->bottom > height) -+ return FALSE; -+ if (rect->top >= rect->bottom) -+ return FALSE; -+ return TRUE; -+} -+ -+static BOOL areRectsValid(UINT32 width, UINT32 height, const RECTANGLE_16* rects, UINT32 count) -+{ -+ WINPR_ASSERT(rects || (count == 0)); -+ for (size_t x = 0; x < count; x++) -+ { -+ const RECTANGLE_16* rect = &rects[x]; -+ if (!isRectValid(width, height, rect)) -+ return FALSE; -+ } -+ return TRUE; -+} -+ - INT32 avc420_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSize, BYTE* pDstData, - DWORD DstFormat, UINT32 nDstStep, UINT32 nDstWidth, UINT32 nDstHeight, - RECTANGLE_16* regionRects, UINT32 numRegionRects) -@@ -174,6 +204,9 @@ INT32 avc420_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSize - if (!h264) - return -1001; - -+ if (!areRectsValid(nDstWidth, nDstHeight, regionRects, numRegionRects)) -+ return -1013; -+ - status = h264->subsystem->Decompress(h264, pSrcData, SrcSize); - - if (status == 0) -@@ -414,6 +447,11 @@ INT32 avc444_decompress(H264_CONTEXT* h264, BYTE op, RECTANGLE_16* regionRects, - if (!h264 || !regionRects || !pSrcData || !pDstData) - return -1001; - -+ if (!areRectsValid(nDstWidth, nDstHeight, regionRects, numRegionRects)) -+ return -1013; -+ if (!areRectsValid(nDstWidth, nDstHeight, auxRegionRects, numAuxRegionRect)) -+ return -1014; -+ - switch (op) - { - case 0: /* YUV420 in stream 1 diff --git a/freerdp-2.11.6-CVE-2026-29775.patch b/freerdp-2.11.6-CVE-2026-29775.patch deleted file mode 100644 index 6a29986..0000000 --- a/freerdp-2.11.6-CVE-2026-29775.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 37dec34f8b2db84162f7834cb0c03ef9cdca4f1c Mon Sep 17 00:00:00 2001 -From: vulgraph -Date: Sun, 3 May 2026 20:48:47 +0800 -Subject: [PATCH] [cache,bitmap] overallocate bitmap cache - -Backport of upstream commit ffad58fd2b329efd81a3239e9d7e3c927b8e503f -to stable-2.0. Addresses CVE-2026-29775. - -Older RDP servers can send a cache index that is one past the -configured BitmapCacheV2NumCells, causing an out-of-bounds write into -bitmapCache->cells. Fix by overallocating one extra cell slot, matching -the upstream remediation. - -stable-2.0 reads BitmapCacheV2NumCells through the settings struct -directly rather than freerdp_settings_get_uint32(), so the cast and -field access differ slightly from upstream while the security change -(+1ull) is identical. ---- - libfreerdp/cache/bitmap.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/libfreerdp/cache/bitmap.c b/libfreerdp/cache/bitmap.c -index 0ce2599b3239..2fd324b6d5d6 100644 ---- a/libfreerdp/cache/bitmap.c -+++ b/libfreerdp/cache/bitmap.c -@@ -281,8 +281,9 @@ rdpBitmapCache* bitmap_cache_new(rdpSettings* settings) - bitmapCache->settings = settings; - bitmapCache->update = ((freerdp*)settings->instance)->update; - bitmapCache->context = bitmapCache->update->context; -- bitmapCache->cells = -- (BITMAP_V2_CELL*)calloc(settings->BitmapCacheV2NumCells, sizeof(BITMAP_V2_CELL)); -+ /* overallocate by 1. older RDP servers do send a off by 1 cache index. */ -+ bitmapCache->cells = (BITMAP_V2_CELL*)calloc( -+ (size_t)settings->BitmapCacheV2NumCells + 1ull, sizeof(BITMAP_V2_CELL)); - - if (!bitmapCache->cells) - goto fail; diff --git a/freerdp-2.11.6-CVE-2026-29776.patch b/freerdp-2.11.6-CVE-2026-29776.patch deleted file mode 100644 index 2453a7d..0000000 --- a/freerdp-2.11.6-CVE-2026-29776.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 363de214f9131ce0eb27fe495bd6f75583cbc10b Mon Sep 17 00:00:00 2001 -From: Armin Novak -Date: Tue, 3 Mar 2026 13:58:09 +0100 -Subject: [PATCH] [core,orders] improve input validation - -check length before subtracting. Might underflow and be cought by the -next check, but lets be strict. - -(cherry picked from commit a9e0abf2eac8c2e370fa155bf1abb9d044c0ca8a) ---- - libfreerdp/core/orders.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/libfreerdp/core/orders.c b/libfreerdp/core/orders.c -index d8bf58d92b9e..a616a22898f5 100644 ---- a/libfreerdp/core/orders.c -+++ b/libfreerdp/core/orders.c -@@ -2144,6 +2144,8 @@ static CACHE_BITMAP_ORDER* update_read_cache_bitmap_order(rdpUpdate* update, wSt - goto fail; - - Stream_Read(s, bitmapComprHdr, 8); /* bitmapComprHdr (8 bytes) */ -+ if (cache_bitmap->bitmapLength < 8) -+ goto fail; - cache_bitmap->bitmapLength -= 8; - } - } diff --git a/freerdp-2.11.6-CVE-2026-31884.patch b/freerdp-2.11.6-CVE-2026-31884.patch deleted file mode 100644 index dd12b99..0000000 --- a/freerdp-2.11.6-CVE-2026-31884.patch +++ /dev/null @@ -1,168 +0,0 @@ -From 3adb5f9e96f3922335b17c9ef916d050ad42e43c Mon Sep 17 00:00:00 2001 -From: Armin Novak -Date: Tue, 10 Mar 2026 09:57:16 +0100 -Subject: [PATCH] [codec,dsp] add format checks - -To avoid issues with invalid audio format settings always check before -use. - -(cherry picked from commit 03b48b3601d867afccac1cdc6081de7a275edce7) ---- - libfreerdp/codec/dsp.c | 83 ++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 83 insertions(+) - -diff --git a/libfreerdp/codec/dsp.c b/libfreerdp/codec/dsp.c -index 0de86027867b..ea7fc61a1f06 100644 ---- a/libfreerdp/codec/dsp.c -+++ b/libfreerdp/codec/dsp.c -@@ -337,6 +337,21 @@ static UINT16 dsp_decode_ima_adpcm_sample(ADPCM* adpcm, unsigned int channel, BY - return (UINT16)d; - } - -+static BOOL valid_ima_adpcm_format(const FREERDP_DSP_CONTEXT* context) -+{ -+ if (!context) -+ return FALSE; -+ if (context->format.wFormatTag != WAVE_FORMAT_DVI_ADPCM) -+ return FALSE; -+ if (context->format.nBlockAlign <= 4ULL) -+ return FALSE; -+ if (context->format.nChannels < 1) -+ return FALSE; -+ if (context->format.wBitsPerSample == 0) -+ return FALSE; -+ return TRUE; -+} -+ - static BOOL freerdp_dsp_decode_ima_adpcm(FREERDP_DSP_CONTEXT* context, const BYTE* src, size_t size, - wStream* out) - { -@@ -349,6 +364,9 @@ static BOOL freerdp_dsp_decode_ima_adpcm(FREERDP_DSP_CONTEXT* context, const BYT - const UINT32 channels = context->format.nChannels; - size_t i; - -+ if (!valid_ima_adpcm_format(context)) -+ return FALSE; -+ - if (!Stream_EnsureCapacity(out, out_size)) - return FALSE; - -@@ -477,6 +495,21 @@ static BOOL freerdp_dsp_encode_gsm610(FREERDP_DSP_CONTEXT* context, const BYTE* - #endif - - #if defined(WITH_LAME) -+static BOOL valid_mp3_format(const FREERDP_DSP_CONTEXT* context) -+{ -+ if (!context) -+ return FALSE; -+ if (context->format.wFormatTag != WAVE_FORMAT_MPEGLAYER3) -+ return FALSE; -+ if (context->format.nChannels < 1) -+ return FALSE; -+ if (context->format.wBitsPerSample == 0) -+ return FALSE; -+ if (context->format.nSamplesPerSec == 0) -+ return FALSE; -+ return TRUE; -+} -+ - static BOOL freerdp_dsp_decode_mp3(FREERDP_DSP_CONTEXT* context, const BYTE* src, size_t size, - wStream* out) - { -@@ -488,6 +521,9 @@ static BOOL freerdp_dsp_decode_mp3(FREERDP_DSP_CONTEXT* context, const BYTE* src - if (!context || !src || !out) - return FALSE; - -+ if (!valid_mp3_format(context)) -+ return FALSE; -+ - buffer_size = 2 * context->format.nChannels * context->format.nSamplesPerSec; - - if (!Stream_EnsureCapacity(context->buffer, 2 * buffer_size)) -@@ -522,6 +558,9 @@ static BOOL freerdp_dsp_encode_mp3(FREERDP_DSP_CONTEXT* context, const BYTE* src - if (!context || !src || !out) - return FALSE; - -+ if (!valid_mp3_format(context)) -+ return FALSE; -+ - samples_per_channel = size / context->format.nChannels / context->format.wBitsPerSample / 8; - - /* Ensure worst case buffer size for mp3 stream taken from LAME header */ -@@ -728,6 +767,8 @@ static BOOL freerdp_dsp_encode_ima_adpcm(FREERDP_DSP_CONTEXT* context, const BYT - size_t align; - out_size = size / 2; - -+ if (!valid_ima_adpcm_format(context)) -+ return FALSE; - if (!Stream_EnsureRemainingCapacity(out, size)) - return FALSE; - -@@ -823,11 +864,28 @@ static INLINE INT16 freerdp_dsp_decode_ms_adpcm_sample(ADPCM* adpcm, BYTE sample - return (INT16)presample; - } - -+static BOOL valid_ms_adpcm_format(const FREERDP_DSP_CONTEXT* context) -+{ -+ if (!context) -+ return FALSE; -+ if (context->format.wFormatTag != WAVE_FORMAT_ADPCM) -+ return FALSE; -+ if (context->format.nBlockAlign <= 4ULL) -+ return FALSE; -+ if (context->format.nChannels < 1) -+ return FALSE; -+ if (context->format.wBitsPerSample == 0) -+ return FALSE; -+ return TRUE; -+} -+ - static BOOL freerdp_dsp_decode_ms_adpcm(FREERDP_DSP_CONTEXT* context, const BYTE* src, size_t size, - wStream* out) - { - BYTE* dst; - BYTE sample; -+ if (!valid_ms_adpcm_format(context)) -+ return FALSE; - const size_t out_size = size * 4; - const UINT32 channels = context->format.nChannels; - const UINT32 block_size = context->format.nBlockAlign; -@@ -959,6 +1017,9 @@ static BOOL freerdp_dsp_encode_ms_adpcm(FREERDP_DSP_CONTEXT* context, const BYTE - const size_t step = 8 + ((context->format.nChannels > 1) ? 4 : 0); - out_size = size / 2; - -+ if (!valid_ms_adpcm_format(context)) -+ return FALSE; -+ - if (!Stream_EnsureRemainingCapacity(out, size)) - return FALSE; - -@@ -1318,6 +1379,28 @@ BOOL freerdp_dsp_context_reset(FREERDP_DSP_CONTEXT* context, const AUDIO_FORMAT* - return FALSE; - - context->format = *targetFormat; -+ -+ switch (context->format.wFormatTag) -+ { -+#if defined(WITH_LAME) -+ case WAVE_FORMAT_MPEGLAYER3: -+ if (!valid_mp3_format(context)) -+ return FALSE; -+ break; -+#endif -+ case WAVE_FORMAT_ADPCM: -+ if (!valid_ms_adpcm_format(context)) -+ return FALSE; -+ break; -+ case WAVE_FORMAT_DVI_ADPCM: -+ if (!valid_ima_adpcm_format(context)) -+ return FALSE; -+ break; -+ default: -+ break; -+ } -+ -+ - #if defined(WITH_FAAD2) - context->faadSetup = FALSE; - #endif diff --git a/freerdp-2.11.6-CVE-2026-31885.patch b/freerdp-2.11.6-CVE-2026-31885.patch deleted file mode 100644 index 3340fa8..0000000 --- a/freerdp-2.11.6-CVE-2026-31885.patch +++ /dev/null @@ -1,219 +0,0 @@ -From 46be2a60f65024d4419cbd80ca545d178ff18507 Mon Sep 17 00:00:00 2001 -From: Armin Novak -Date: Tue, 10 Mar 2026 10:21:40 +0100 -Subject: [PATCH] [codec,dsp] fix array bounds checks - -Adapted to FreeRDP 2.11.6. ---- -diff --color -ruN base/libfreerdp/codec/dsp.c work/libfreerdp/codec/dsp.c ---- a/libfreerdp/codec/dsp.c 2026-06-02 16:03:07.348504798 +0800 -+++ b/libfreerdp/codec/dsp.c 2026-06-02 16:03:07.419505504 +0800 -@@ -296,7 +296,16 @@ - { - INT32 ss; - INT32 d; -- ss = ima_step_size_table[adpcm->ima.last_step[channel]]; -+ INT16 offset; -+ -+ WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ima.last_step)); -+ WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ima.last_sample)); -+ -+ offset = adpcm->ima.last_step[channel]; -+ WINPR_ASSERT(offset >= 0); -+ WINPR_ASSERT(offset < ARRAYSIZE(ima_step_size_table)); -+ -+ ss = ima_step_size_table[offset]; - d = (ss >> 3); - - if (sample & 1) -@@ -319,6 +328,7 @@ - d = 32767; - - adpcm->ima.last_sample[channel] = (INT16)d; -+ WINPR_ASSERT(sample < ARRAYSIZE(ima_step_index_table)); - adpcm->ima.last_step[channel] += ima_step_index_table[sample]; - - if (adpcm->ima.last_step[channel] < 0) -@@ -368,6 +378,9 @@ - { - if (size % block_size == 0) - { -+ if (size < 4) -+ return FALSE; -+ - context->adpcm.ima.last_sample[0] = - (INT16)(((UINT16)(*src)) | (((UINT16)(*(src + 1))) << 8)); - context->adpcm.ima.last_step[0] = (INT16)(*(src + 2)); -@@ -377,6 +390,8 @@ - - if (channels > 1) - { -+ if (size < 4) -+ return FALSE; - context->adpcm.ima.last_sample[1] = - (INT16)(((UINT16)(*src)) | (((UINT16)(*(src + 1))) << 8)); - context->adpcm.ima.last_step[1] = (INT16)(*(src + 2)); -@@ -388,6 +403,8 @@ - - if (channels > 1) - { -+ if (size < 8) -+ return FALSE; - for (i = 0; i < 8; i++) - { - channel = (i < 4 ? 0 : 1); -@@ -407,6 +424,8 @@ - } - else - { -+ if (size < 1) -+ return FALSE; - sample = ((*src) & 0x0f); - decoded = dsp_decode_ima_adpcm_sample(&context->adpcm, 0, sample); - *dst++ = (decoded & 0xFF); -@@ -689,7 +708,16 @@ - INT32 ss; - BYTE enc; - INT32 diff; -- ss = ima_step_size_table[adpcm->ima.last_step[channel]]; -+ INT16 offset; -+ -+ WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ima.last_step)); -+ WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ima.last_sample)); -+ -+ offset = adpcm->ima.last_step[channel]; -+ WINPR_ASSERT(offset >= 0); -+ WINPR_ASSERT(offset < ARRAYSIZE(ima_step_size_table)); -+ -+ ss = ima_step_size_table[offset]; - d = e = sample - adpcm->ima.last_sample[channel]; - diff = ss >> 3; - enc = 0; -@@ -735,6 +763,7 @@ - diff = 32767; - - adpcm->ima.last_sample[channel] = (INT16)diff; -+ WINPR_ASSERT(enc < ARRAYSIZE(ima_step_index_table)); - adpcm->ima.last_step[channel] += ima_step_index_table[enc]; - - if (adpcm->ima.last_step[channel] < 0) -@@ -833,10 +862,29 @@ - { - INT8 nibble; - INT32 presample; -+ BYTE predictor; -+ INT32 coeff1; -+ INT32 coeff2; -+ INT32 tableval; -+ -+ WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ms.sample1)); -+ WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ms.sample2)); -+ WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ms.delta)); -+ WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ms.predictor)); -+ - nibble = (sample & 0x08 ? (INT8)sample - 16 : (INT8)sample); -- presample = ((adpcm->ms.sample1[channel] * ms_adpcm_coeffs1[adpcm->ms.predictor[channel]]) + -- (adpcm->ms.sample2[channel] * ms_adpcm_coeffs2[adpcm->ms.predictor[channel]])) / -- 256; -+ predictor = adpcm->ms.predictor[channel]; -+ -+ coeff1 = 0; -+ if (predictor < ARRAYSIZE(ms_adpcm_coeffs1)) -+ coeff1 = ms_adpcm_coeffs1[predictor]; -+ -+ coeff2 = 0; -+ if (predictor < ARRAYSIZE(ms_adpcm_coeffs2)) -+ coeff2 = ms_adpcm_coeffs2[predictor]; -+ -+ presample = -+ ((adpcm->ms.sample1[channel] * coeff1) + (adpcm->ms.sample2[channel] * coeff2)) / 256; - presample += nibble * adpcm->ms.delta[channel]; - - if (presample > 32767) -@@ -846,7 +894,12 @@ - - adpcm->ms.sample2[channel] = adpcm->ms.sample1[channel]; - adpcm->ms.sample1[channel] = presample; -- adpcm->ms.delta[channel] = adpcm->ms.delta[channel] * ms_adpcm_adaptation_table[sample] / 256; -+ -+ tableval = 0; -+ if (sample < ARRAYSIZE(ms_adpcm_adaptation_table)) -+ tableval = ms_adpcm_adaptation_table[sample]; -+ -+ adpcm->ms.delta[channel] = adpcm->ms.delta[channel] * tableval / 256; - - if (adpcm->ms.delta[channel] < 16) - adpcm->ms.delta[channel] = 16; -@@ -891,6 +944,9 @@ - { - if (channels > 1) - { -+ if (size < 14) -+ return FALSE; -+ - context->adpcm.ms.predictor[0] = *src++; - context->adpcm.ms.predictor[1] = *src++; - context->adpcm.ms.delta[0] = read_int16(src); -@@ -917,6 +973,9 @@ - } - else - { -+ if (size < 7) -+ return FALSE; -+ - context->adpcm.ms.predictor[0] = *src++; - context->adpcm.ms.delta[0] = read_int16(src); - src += 2; -@@ -934,12 +993,16 @@ - - if (channels > 1) - { -+ if (size < 1) -+ return FALSE; - sample = *src++; - size--; - write_int16(dst, freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample >> 4, 0)); - dst += 2; - write_int16(dst, freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample & 0x0F, 1)); - dst += 2; -+ if (size < 1) -+ return FALSE; - sample = *src++; - size--; - write_int16(dst, freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample >> 4, 0)); -@@ -949,6 +1012,8 @@ - } - else - { -+ if (size < 1) -+ return FALSE; - sample = *src++; - size--; - write_int16(dst, freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample >> 4, 0)); -@@ -966,6 +1031,14 @@ - { - INT32 presample; - INT32 errordelta; -+ size_t offset; -+ -+ WINPR_ASSERT(channel >= 0); -+ WINPR_ASSERT((size_t)channel < ARRAYSIZE(adpcm->ms.sample1)); -+ WINPR_ASSERT((size_t)channel < ARRAYSIZE(adpcm->ms.sample2)); -+ WINPR_ASSERT((size_t)channel < ARRAYSIZE(adpcm->ms.delta)); -+ WINPR_ASSERT((size_t)channel < ARRAYSIZE(adpcm->ms.predictor)); -+ - presample = ((adpcm->ms.sample1[channel] * ms_adpcm_coeffs1[adpcm->ms.predictor[channel]]) + - (adpcm->ms.sample2[channel] * ms_adpcm_coeffs2[adpcm->ms.predictor[channel]])) / - 256; -@@ -988,8 +1061,9 @@ - - adpcm->ms.sample2[channel] = adpcm->ms.sample1[channel]; - adpcm->ms.sample1[channel] = presample; -- adpcm->ms.delta[channel] = -- adpcm->ms.delta[channel] * ms_adpcm_adaptation_table[(((BYTE)errordelta) & 0x0F)] / 256; -+ offset = (((BYTE)errordelta) & 0x0F); -+ WINPR_ASSERT(offset < ARRAYSIZE(ms_adpcm_adaptation_table)); -+ adpcm->ms.delta[channel] = adpcm->ms.delta[channel] * ms_adpcm_adaptation_table[offset] / 256; - - if (adpcm->ms.delta[channel] < 16) - adpcm->ms.delta[channel] = 16; diff --git a/freerdp-2.11.6-CVE-2026-31897.patch b/freerdp-2.11.6-CVE-2026-31897.patch deleted file mode 100644 index e0284d2..0000000 --- a/freerdp-2.11.6-CVE-2026-31897.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 85541cace657819aaf064f4c2797d82d4c4f9d03 Mon Sep 17 00:00:00 2001 -From: Armin Novak -Date: Tue, 10 Mar 2026 09:17:23 +0100 -Subject: [PATCH] [codec,planar] add early length check to avoid oob read - -(cherry picked from commit cd27c8faca0eeb0d4309cc5837dfdf3c42eba4e7) ---- - libfreerdp/codec/planar.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/libfreerdp/codec/planar.c b/libfreerdp/codec/planar.c -index 5af3d82b26e7..c728dd8ea507 100644 ---- a/libfreerdp/codec/planar.c -+++ b/libfreerdp/codec/planar.c -@@ -626,9 +626,9 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData, UINT - - srcp = pSrcData; - -- if (!pSrcData) -+ if (!pSrcData || (SrcSize < 1)) - { -- WLog_ERR(TAG, "Invalid argument pSrcData=NULL"); -+ WLog_ERR(TAG, "Invalid argument pSrcData=%p [size=%" PRIu32 "]", pSrcData, SrcSize); - return FALSE; - } - diff --git a/freerdp-2.11.6-CVE-2026-33952.patch b/freerdp-2.11.6-CVE-2026-33952.patch deleted file mode 100644 index 1e0ebca..0000000 --- a/freerdp-2.11.6-CVE-2026-33952.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 062d6e1cd743a8b198e3ce7bdacec77ff8a568ea Mon Sep 17 00:00:00 2001 -From: Armin Novak -Date: Wed, 25 Mar 2026 09:04:43 +0100 -Subject: [PATCH] [core,gateway] Check rpcconn_common_hdr_t::auth_length is - valid - -Do sanity checks for rpcconn_common_hdr_t::auth_length read from -network, abort if the value is out of range. - -(cherry picked from commit 4ac0b6467d371a1ad47c1f751c5b305e4c068adb) ---- - libfreerdp/core/gateway/rts.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/libfreerdp/core/gateway/rts.c b/libfreerdp/core/gateway/rts.c -index ccbe0becaddf..85e65b0de3c6 100644 ---- a/libfreerdp/core/gateway/rts.c -+++ b/libfreerdp/core/gateway/rts.c -@@ -200,6 +200,8 @@ BOOL rts_read_common_pdu_header(wStream* s, rpcconn_common_hdr_t* header) - - if (header->frag_length < sizeof(rpcconn_common_hdr_t)) - return FALSE; -+ if (header->auth_length > header->frag_length - 8ull) -+ return FALSE; - - left = Stream_GetRemainingLength(s); - if (left < header->frag_length - sizeof(rpcconn_common_hdr_t)) diff --git a/freerdp-2.11.6-CVE-2026-33977.patch b/freerdp-2.11.6-CVE-2026-33977.patch deleted file mode 100644 index 545e55b..0000000 --- a/freerdp-2.11.6-CVE-2026-33977.patch +++ /dev/null @@ -1,71 +0,0 @@ -From d473cef5549e699709b511510f201d9ee4948230 Mon Sep 17 00:00:00 2001 -From: Armin Novak -Date: Wed, 25 Mar 2026 09:23:18 +0100 -Subject: [PATCH] [codec,dsp] fix IMA ADPCM sample clamping - -Adapted to FreeRDP 2.11.6 after CVE-2026-31885 backport. ---- -diff --color -ruN base/libfreerdp/codec/dsp.c work/libfreerdp/codec/dsp.c ---- a/libfreerdp/codec/dsp.c 2026-06-02 16:03:52.374946307 +0800 -+++ b/libfreerdp/codec/dsp.c 2026-06-02 16:03:52.467947206 +0800 -@@ -292,6 +292,17 @@ - 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 - }; - -+static inline void dsp_ima_clamp_step(ADPCM* adpcm, unsigned int channel) -+{ -+ WINPR_ASSERT(adpcm); -+ if (adpcm->ima.last_step[channel] < 0) -+ adpcm->ima.last_step[channel] = 0; -+ -+ const size_t size = ARRAYSIZE(ima_step_size_table); -+ if (adpcm->ima.last_step[channel] > size) -+ adpcm->ima.last_step[channel] = size; -+} -+ - static UINT16 dsp_decode_ima_adpcm_sample(ADPCM* adpcm, unsigned int channel, BYTE sample) - { - INT32 ss; -@@ -331,10 +342,7 @@ - WINPR_ASSERT(sample < ARRAYSIZE(ima_step_index_table)); - adpcm->ima.last_step[channel] += ima_step_index_table[sample]; - -- if (adpcm->ima.last_step[channel] < 0) -- adpcm->ima.last_step[channel] = 0; -- else if (adpcm->ima.last_step[channel] > 88) -- adpcm->ima.last_step[channel] = 88; -+ dsp_ima_clamp_step(adpcm, channel); - - return (UINT16)d; - } -@@ -384,6 +392,9 @@ - context->adpcm.ima.last_sample[0] = - (INT16)(((UINT16)(*src)) | (((UINT16)(*(src + 1))) << 8)); - context->adpcm.ima.last_step[0] = (INT16)(*(src + 2)); -+ -+ dsp_ima_clamp_step(&context->adpcm, 0); -+ - src += 4; - size -= 4; - out_size -= 16; -@@ -395,6 +406,8 @@ - context->adpcm.ima.last_sample[1] = - (INT16)(((UINT16)(*src)) | (((UINT16)(*(src + 1))) << 8)); - context->adpcm.ima.last_step[1] = (INT16)(*(src + 2)); -+ -+ dsp_ima_clamp_step(&context->adpcm, 1); - src += 4; - size -= 4; - out_size -= 16; -@@ -766,10 +779,7 @@ - WINPR_ASSERT(enc < ARRAYSIZE(ima_step_index_table)); - adpcm->ima.last_step[channel] += ima_step_index_table[enc]; - -- if (adpcm->ima.last_step[channel] < 0) -- adpcm->ima.last_step[channel] = 0; -- else if (adpcm->ima.last_step[channel] > 88) -- adpcm->ima.last_step[channel] = 88; -+ dsp_ima_clamp_step(adpcm, channel); - - return enc; - } diff --git a/freerdp-2.11.6-CVE-2026-33983.patch b/freerdp-2.11.6-CVE-2026-33983.patch deleted file mode 100644 index 1efd927..0000000 --- a/freerdp-2.11.6-CVE-2026-33983.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 9f6e61c006149ea49181c723fcbc70c0d021248f Mon Sep 17 00:00:00 2001 -From: Armin Novak -Date: Wed, 25 Mar 2026 10:03:56 +0100 -Subject: [PATCH] [codec,progressive] Fail progressive_rfx_quant_sub on invalid - values - -(cherry picked from commit 78188ab479c8e6eb9ba2475b3732c76b4bbe5425) ---- - libfreerdp/codec/progressive.c | 42 ++++++++++++++++++++++++++++++---- - 1 file changed, 38 insertions(+), 4 deletions(-) - -diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c -index 8894b35c8845..41e658c8fd66 100644 ---- a/libfreerdp/codec/progressive.c -+++ b/libfreerdp/codec/progressive.c -@@ -155,20 +155,51 @@ static INLINE void progressive_rfx_quant_lsub(RFX_COMPONENT_CODEC_QUANT* q, int - q->LL3 -= val; /* LL3 */ - } - --static INLINE void progressive_rfx_quant_sub(const RFX_COMPONENT_CODEC_QUANT* q1, -+static INLINE BOOL progressive_rfx_quant_sub(const RFX_COMPONENT_CODEC_QUANT* q1, - const RFX_COMPONENT_CODEC_QUANT* q2, - RFX_COMPONENT_CODEC_QUANT* dst) - { -+ if (q1->HH1 < q2->HL1) -+ return FALSE; - dst->HL1 = q1->HL1 - q2->HL1; /* HL1 */ -+ -+ if (q1->LH1 < q2->LH1) -+ return FALSE; - dst->LH1 = q1->LH1 - q2->LH1; /* LH1 */ -+ -+ if (q1->HH1 < q2->HH1) -+ return FALSE; - dst->HH1 = q1->HH1 - q2->HH1; /* HH1 */ -+ -+ if (q1->HL2 < q2->HL2) -+ return FALSE; - dst->HL2 = q1->HL2 - q2->HL2; /* HL2 */ -+ -+ if (q1->LH2 < q2->LH2) -+ return FALSE; - dst->LH2 = q1->LH2 - q2->LH2; /* LH2 */ -+ -+ if (q1->HH2 < q2->HH2) -+ return FALSE; - dst->HH2 = q1->HH2 - q2->HH2; /* HH2 */ -+ -+ if (q1->HL3 < q2->HL3) -+ return FALSE; - dst->HL3 = q1->HL3 - q2->HL3; /* HL3 */ -+ -+ if (q1->LH3 < q2->LH3) -+ return FALSE; - dst->LH3 = q1->LH3 - q2->LH3; /* LH3 */ -+ -+ if (q1->HH3 < q2->HH3) -+ return FALSE; - dst->HH3 = q1->HH3 - q2->HH3; /* HH3 */ -+ -+ if (q1->LL3 < q2->LL3) -+ return FALSE; - dst->LL3 = q1->LL3 - q2->LL3; /* LL3 */ -+ -+ return TRUE; - } - - static INLINE BOOL progressive_rfx_quant_lcmp_less_equal(const RFX_COMPONENT_CODEC_QUANT* q, -@@ -1433,9 +1464,12 @@ static INLINE int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progr - progressive_rfx_quant_add(quantY, quantProgY, &yBitPos); - progressive_rfx_quant_add(quantCb, quantProgCb, &cbBitPos); - progressive_rfx_quant_add(quantCr, quantProgCr, &crBitPos); -- progressive_rfx_quant_sub(&(tile->yBitPos), &yBitPos, &yNumBits); -- progressive_rfx_quant_sub(&(tile->cbBitPos), &cbBitPos, &cbNumBits); -- progressive_rfx_quant_sub(&(tile->crBitPos), &crBitPos, &crNumBits); -+ if (!progressive_rfx_quant_sub(&(tile->yBitPos), &yBitPos, &yNumBits)) -+ goto fail; -+ if (!progressive_rfx_quant_sub(&(tile->cbBitPos), &cbBitPos, &cbNumBits)) -+ goto fail; -+ if (!progressive_rfx_quant_sub(&(tile->crBitPos), &crBitPos, &crNumBits)) -+ goto fail; - progressive_rfx_quant_add(quantY, quantProgY, &shiftY); - progressive_rfx_quant_lsub(&shiftY, 1); /* -6 + 5 = -1 */ - progressive_rfx_quant_add(quantCb, quantProgCb, &shiftCb); diff --git a/freerdp-2.11.6-CVE-2026-33984.patch b/freerdp-2.11.6-CVE-2026-33984.patch deleted file mode 100644 index 2d52515..0000000 --- a/freerdp-2.11.6-CVE-2026-33984.patch +++ /dev/null @@ -1,40 +0,0 @@ -From dc7fdb165095139be779a4000199bc1706b06ad5 Mon Sep 17 00:00:00 2001 -From: Armin Novak -Date: Wed, 25 Mar 2026 09:48:54 +0100 -Subject: [PATCH] [codec,clear] update CLEAR_VBAR_ENTRY::size after alloc - -CVE-2026-33984 (GHSA-8469-2xcx-frf6): in resize_vbar_entry() in -libfreerdp/codec/clear.c, vBarEntry->size is updated to vBarEntry->count -before the (re)allocation call. If realloc fails, size is inflated while -pixels still points to the old, smaller buffer. On a subsequent call where -count <= size (the inflated value), the realloc is skipped and the caller -writes count * bpp bytes of attacker-controlled pixel data into the -undersized buffer, causing a heap buffer overflow. - -Only update vBarEntry->size after the buffer was successfully reallocated. - -Backported from upstream commit dc7fdb165095139be779a4000199bc1706b06ad5 -and adapted to the 2.11.6 clear.c codec code (realloc instead of -winpr_aligned_recalloc). ---- - libfreerdp/codec/clear.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/libfreerdp/codec/clear.c -+++ b/libfreerdp/codec/clear.c -@@ -565,7 +565,6 @@ static BOOL resize_vbar_entry(CLEAR_CONTEXT* clear, CLEAR_VBAR_ENTRY* vBarEntry) - const UINT32 oldPos = vBarEntry->size * bpp; - const UINT32 diffSize = (vBarEntry->count - vBarEntry->size) * bpp; - BYTE* tmp; -- vBarEntry->size = vBarEntry->count; - tmp = (BYTE*)realloc(vBarEntry->pixels, 1ull * vBarEntry->count * bpp); - - if (!tmp) -@@ -574,6 +573,7 @@ static BOOL resize_vbar_entry(CLEAR_CONTEXT* clear, CLEAR_VBAR_ENTRY* vBarEntry) - - memset(&tmp[oldPos], 0, diffSize); - vBarEntry->pixels = tmp; -+ vBarEntry->size = vBarEntry->count; - } - - if (!vBarEntry->pixels && vBarEntry->size) diff --git a/freerdp-2.11.6-CVE-2026-33985.patch b/freerdp-2.11.6-CVE-2026-33985.patch deleted file mode 100644 index 72595ea..0000000 --- a/freerdp-2.11.6-CVE-2026-33985.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 713a243a6088237c659682a18406db54e731fefd Mon Sep 17 00:00:00 2001 -From: Armin Novak -Date: Thu, 23 Apr 2026 19:36:17 +0800 -Subject: [PATCH] [codec,clear] Update CLEAR_GLYPH_ENTRY::count after alloc - -Ensure the value is always properly related to an existing buffer. - -(cherry picked from commit c49d1ad43b8c7b32794d0250f2623c2dccd7ef25) ---- - libfreerdp/codec/clear.c | 24 ++++++++++++++++++------ - 1 file changed, 18 insertions(+), 6 deletions(-) - -diff --git a/libfreerdp/codec/clear.c b/libfreerdp/codec/clear.c -index e38fa0dcfbef..a4b7e9baf3d1 100644 ---- a/libfreerdp/codec/clear.c -+++ b/libfreerdp/codec/clear.c -@@ -979,23 +979,35 @@ static BOOL clear_decompress_glyph_data(CLEAR_CONTEXT* clear, wStream* s, UINT32 - { - const UINT32 bpp = GetBytesPerPixel(clear->format); - CLEAR_GLYPH_ENTRY* glyphEntry = &(clear->GlyphCache[glyphIndex]); -- glyphEntry->count = nWidth * nHeight; -+ const size_t count = 1ull * nWidth * nHeight; -+ const size_t hlimit = SIZE_MAX / ((nWidth > 0) ? nWidth : 1); -+ if ((nWidth == 0) || (nHeight == 0) || (hlimit < nHeight)) -+ { -+ WLog_ERR(TAG, -+ "CLEARCODEC_FLAG_GLYPH_INDEX: invalid dimensions nWidth=%" PRIu32 -+ " nHeight=%" PRIu32, -+ nWidth, nHeight); -+ return FALSE; -+ } - -- if (glyphEntry->count > glyphEntry->size) -+ if (count > glyphEntry->size) - { -- BYTE* tmp; -- tmp = realloc(glyphEntry->pixels, 1ull * glyphEntry->count * bpp); -+ BYTE* tmp = realloc(glyphEntry->pixels, count * bpp); - - if (!tmp) - { -- WLog_ERR(TAG, "glyphEntry->pixels realloc %" PRIu32 " failed!", -- glyphEntry->count * bpp); -+ WLog_ERR(TAG, "glyphEntry->pixels realloc %zu failed!", count * bpp); - return FALSE; - } - -+ glyphEntry->count = (UINT32)count; - glyphEntry->size = glyphEntry->count; - glyphEntry->pixels = (UINT32*)tmp; - } -+ else -+ { -+ glyphEntry->count = (UINT32)count; -+ } - - if (!glyphEntry->pixels) - { diff --git a/freerdp-2.11.6-CVE-2026-33986.patch b/freerdp-2.11.6-CVE-2026-33986.patch deleted file mode 100644 index b5f9f41..0000000 --- a/freerdp-2.11.6-CVE-2026-33986.patch +++ /dev/null @@ -1,45 +0,0 @@ -From f6e43e208958140074ae9bb93cd0c9045a371c77 Mon Sep 17 00:00:00 2001 -From: Armin Novak -Date: Wed, 25 Mar 2026 09:45:56 +0100 -Subject: [PATCH] [codec,h264] update H264_CONTEXT::width,height after alloc - -CVE-2026-33986 (GHSA-h6qw-wxvm-hf97): in avc420_ensure_buffer() in -libfreerdp/codec/h264.c, h264->width and h264->height are updated before -the YUV buffers are (re)allocated. If any allocation fails the function -returns FALSE, but the dimensions are already inflated. On the next call -with the same dimensions the (width != h264->width || height != -h264->height) check evaluates to FALSE, the reallocation is skipped, and -the decoder writes decoded YUV data into the old, undersized buffers, -causing a heap buffer overflow. - -Ensure the width/height values are only updated after the buffers were -successfully allocated. - -Backported from upstream commit f6e43e208958140074ae9bb93cd0c9045a371c77 -and adapted to the 2.11.6 avc420_ensure_buffer() code (_aligned_malloc -instead of the later yuv_ensure_buffer/winpr_aligned_recalloc refactor). ---- - libfreerdp/codec/h264.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - ---- a/libfreerdp/codec/h264.c -+++ b/libfreerdp/codec/h264.c -@@ -58,8 +58,6 @@ BOOL avc420_ensure_buffer(H264_CONTEXT* h264, UINT32 stride, UINT32 width, UINT3 - h264->iStride[0] = stride; - h264->iStride[1] = (stride + 1) / 2; - h264->iStride[2] = (stride + 1) / 2; -- h264->width = width; -- h264->height = height; - _aligned_free(h264->pYUVData[0]); - _aligned_free(h264->pYUVData[1]); - _aligned_free(h264->pYUVData[2]); -@@ -69,6 +67,9 @@ BOOL avc420_ensure_buffer(H264_CONTEXT* h264, UINT32 stride, UINT32 width, UINT3 - - if (!h264->pYUVData[0] || !h264->pYUVData[1] || !h264->pYUVData[2]) - return FALSE; -+ -+ h264->width = width; -+ h264->height = height; - } - - return TRUE; diff --git a/freerdp-2.11.6-CVE-2026-44420.patch b/freerdp-2.11.6-CVE-2026-44420.patch deleted file mode 100644 index 802e6a4..0000000 --- a/freerdp-2.11.6-CVE-2026-44420.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0fba1f4dbff7585c9c99873d7c07d7dac46510c3 Mon Sep 17 00:00:00 2001 -From: Kevin Valerio -Date: Wed, 29 Apr 2026 22:39:54 +0200 -Subject: [PATCH] fix(cliprdr): validate capabilitySetLength in server caps - ---- - channels/cliprdr/server/cliprdr_main.c | 38 +++++++++++++++++++++++--- - 1 file changed, 34 insertions(+), 4 deletions(-) -diff --git a/channels/cliprdr/server/cliprdr_main.c b/channels/cliprdr/server/cliprdr_main.c -index 7e0b681..7df3c75 100644 ---- a/channels/cliprdr/server/cliprdr_main.c -+++ b/channels/cliprdr/server/cliprdr_main.c -@@ -489,15 +489,44 @@ static UINT cliprdr_server_receive_capabilities(CliprdrServerContext* context, w - for (index = 0; index < capabilities.cCapabilitiesSets; index++) - { - void* tmp = NULL; -+ const size_t cap_set_offset = cap_sets_size; - if (Stream_GetRemainingLength(s) < 4) - goto out; - Stream_Read_UINT16(s, capabilitySetType); /* capabilitySetType (2 bytes) */ - Stream_Read_UINT16(s, capabilitySetLength); /* capabilitySetLength (2 bytes) */ - -+ if (capabilitySetLength < sizeof(CLIPRDR_CAPABILITY_SET)) -+ { -+ WLog_ERR(TAG, -+ "invalid capabilitySetLength %" PRIu16 " < %" PRIuz -+ " (capabilitySetType=%" PRIu16 ")", -+ capabilitySetLength, sizeof(CLIPRDR_CAPABILITY_SET), capabilitySetType); -+ goto out; -+ } -+ -+ if (Stream_GetRemainingLength(s) < (size_t)capabilitySetLength - sizeof(CLIPRDR_CAPABILITY_SET)) -+ goto out; -+ -+ switch (capabilitySetType) -+ { -+ case CB_CAPSTYPE_GENERAL: -+ if (capabilitySetLength != sizeof(CLIPRDR_GENERAL_CAPABILITY_SET)) -+ { -+ WLog_ERR(TAG, -+ "invalid capabilitySetLength %" PRIu16 " != %" PRIuz -+ " (capabilitySetType=CB_CAPSTYPE_GENERAL)", -+ capabilitySetLength, sizeof(CLIPRDR_GENERAL_CAPABILITY_SET)); -+ goto out; -+ } -+ break; -+ default: -+ WLog_ERR(TAG, "unknown cliprdr capability set: %" PRIu16 "", capabilitySetType); -+ goto out; -+ } -+ - cap_sets_size += capabilitySetLength; - -- if (cap_sets_size > 0) -- tmp = realloc(capabilities.capabilitySets, cap_sets_size); -+ tmp = realloc(capabilities.capabilitySets, cap_sets_size); - if (tmp == NULL) - { - WLog_ERR(TAG, "capabilities.capabilitySets realloc failed!"); -@@ -507,7 +536,7 @@ static UINT cliprdr_server_receive_capabilities(CliprdrServerContext* context, w - - capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET*)tmp; - -- capSet = &(capabilities.capabilitySets[index]); -+ capSet = (CLIPRDR_CAPABILITY_SET*)(((BYTE*)capabilities.capabilitySets) + cap_set_offset); - - capSet->capabilitySetType = capabilitySetType; - capSet->capabilitySetLength = capabilitySetLength; diff --git a/freerdp-2.11.6-CVE-2026-44421.patch b/freerdp-2.11.6-CVE-2026-44421.patch deleted file mode 100644 index ad4d0f7..0000000 --- a/freerdp-2.11.6-CVE-2026-44421.patch +++ /dev/null @@ -1,36 +0,0 @@ -From f951d8677ce6d34d9778b951f73b3072b01853cb Mon Sep 17 00:00:00 2001 -From: Armin Novak -Date: Thu, 30 Apr 2026 10:04:24 +0200 -Subject: [PATCH] [gdi,gfx] fix bounds checks - -In gdi_CacheToSurface, the destination rectangle is validated by -is_rect_valid which clamps to surface dimensions. However, the -freerdp_image_copy call used the original cacheEntry->width/height, -potentially causing a heap-buffer-overflow write. Use the clamped -rectangle dimensions (w = rect.right - rect.left, h = rect.bottom - rect.top) -for the image copy. - -Adapted-by: PkgAgent/deepseek-v4 (modified to adapt to opencloudos-stream freerdp 2.11.6, using freerdp_image_copy instead of freerdp_image_copy_no_overlap) ---- - - libfreerdp/gdi/gfx.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/libfreerdp/gdi/gfx.c b/libfreerdp/gdi/gfx.c -diff --git a/libfreerdp/gdi/gfx.c b/libfreerdp/gdi/gfx.c -index 3970715..f9a9bcc 100644 ---- a/libfreerdp/gdi/gfx.c -+++ b/libfreerdp/gdi/gfx.c -@@ -1325,8 +1325,11 @@ static UINT gdi_CacheToSurface(RdpgfxClientContext* context, - if (!is_rect_valid(&rect, surface->width, surface->height)) - goto fail; - -+ const UINT32 w = rect.right - rect.left; -+ const UINT32 h = rect.bottom - rect.top; -+ - if (!freerdp_image_copy(surface->data, surface->format, surface->scanline, destPt->x, -- destPt->y, cacheEntry->width, cacheEntry->height, cacheEntry->data, -+ destPt->y, w, h, cacheEntry->data, - cacheEntry->format, cacheEntry->scanline, 0, 0, NULL, - FREERDP_FLIP_NONE)) - goto fail; diff --git a/freerdp-2.11.6-CVE-2026-55827.patch b/freerdp-2.11.6-CVE-2026-55827.patch deleted file mode 100644 index 01b31eb..0000000 --- a/freerdp-2.11.6-CVE-2026-55827.patch +++ /dev/null @@ -1,297 +0,0 @@ -From e58adf922ea4c0d5495e59a1fe488d70092e0e3e Mon Sep 17 00:00:00 2001 -From: Armin Novak -Date: Tue, 16 Jun 2026 10:16:21 +0000 -Subject: [PATCH] Backport bitmap decode fixes for CVE-2026-55827 - -CVE-2026-55827 (GHSA-c495-h83v-3prp): Cache Bitmap V3 RemoteFX data -was decoded into a per-bitmap allocation while using the desktop surface -stride and height as output bounds. A malicious RDP server could therefore -write attacker-influenced pixels beyond the heap allocation. - -Use the cached bitmap's own stride and height for all decode paths and -validate Cache Bitmap V3 codec and cache identifiers against negotiated -settings. - -Backported from upstream commit e58adf922ea4c0d5495e59a1fe488d70092e0e3e -and adapted to FreeRDP 2.11.6 APIs (legacy allocation, pixel-format, -decompression, stream-length and logging interfaces). - -Assisted-by: Cursor(GPT-5.6 Sol) ---- - libfreerdp/core/orders.c | 84 ++++++++++++++++++++++++++++++++++++++++++++---- - libfreerdp/gdi/graphics.c | 98 +++++++++++++++++++++++++++++++++++++++++++++------------ - 2 files changed, 156 insertions(+), 26 deletions(-) - ---- a/libfreerdp/core/orders.c -+++ b/libfreerdp/core/orders.c -@@ -2226,7 +2226,7 @@ - if (!cache_bitmap_v2) - goto fail; - -- cache_bitmap_v2->cacheId = flags & 0x0003; -+ cache_bitmap_v2->cacheId = flags & 0x0007; - cache_bitmap_v2->flags = (flags & 0xFF80) >> 7; - bitsPerPixelId = (flags & 0x0078) >> 3; - cache_bitmap_v2->bitmapBpp = get_cbr2_bpp(bitsPerPixelId, &rc); -@@ -2387,21 +2387,40 @@ - UINT32 new_len; - BYTE* new_data; - CACHE_BITMAP_V3_ORDER* cache_bitmap_v3; -+ const rdpSettings* settings; -+ UINT32 NumCellCaches; - - if (!update || !s) - return NULL; - -+ WINPR_ASSERT(update->context); -+ settings = update->context->settings; -+ WINPR_ASSERT(settings); -+ -+ if (!freerdp_settings_get_bool(settings, FreeRDP_BitmapCacheV3Enabled)) -+ { -+ WLog_Print(update->log, WLOG_ERROR, -+ "BitmapCacheV3 not enabled for this connection, aborting"); -+ return NULL; -+ } -+ - cache_bitmap_v3 = calloc(1, sizeof(CACHE_BITMAP_V3_ORDER)); - - if (!cache_bitmap_v3) - goto fail; - -- cache_bitmap_v3->cacheId = flags & 0x00000003; -- cache_bitmap_v3->flags = (flags & 0x0000FF80) >> 7; -- bitsPerPixelId = (flags & 0x00000078) >> 3; -- cache_bitmap_v3->bpp = get_cbr2_bpp(bitsPerPixelId, &rc); -- if (!rc) -+ cache_bitmap_v3->cacheId = flags & 0x00000007; -+ NumCellCaches = freerdp_settings_get_uint32(settings, FreeRDP_BitmapCacheV2NumCells); -+ if (cache_bitmap_v3->cacheId >= NumCellCaches) -+ { -+ WLog_Print(update->log, WLOG_ERROR, -+ "BitmapCacheV3::cacheId %" PRIu32 " > NumCellCaches %" PRIu32, -+ cache_bitmap_v3->cacheId, NumCellCaches); - goto fail; -+ } -+ cache_bitmap_v3->flags = (flags >> 7) & 0x000001FF; -+ bitsPerPixelId = (flags >> 3) & 0x0000000F; -+ cache_bitmap_v3->bpp = get_cbr2_bpp(bitsPerPixelId, &rc); - - if (Stream_GetRemainingLength(s) < 21) - goto fail; -@@ -2409,6 +2428,18 @@ - Stream_Read_UINT16(s, cache_bitmap_v3->cacheIndex); /* cacheIndex (2 bytes) */ - Stream_Read_UINT32(s, cache_bitmap_v3->key1); /* key1 (4 bytes) */ - Stream_Read_UINT32(s, cache_bitmap_v3->key2); /* key2 (4 bytes) */ -+ -+ if ((cache_bitmap_v3->flags & CBR3_DO_NOT_CACHE) != 0) -+ { -+ rdpCache* cache = update->context->cache; -+ WINPR_ASSERT(cache); -+ -+ if (cache_bitmap_v3->cacheId >= cache->bitmap->maxCells) -+ goto fail; -+ -+ cache_bitmap_v3->cacheIndex = cache->bitmap->cells[cache_bitmap_v3->cacheId].number; -+ } -+ - bitmapData = &cache_bitmap_v3->bitmapData; - Stream_Read_UINT8(s, bitmapData->bpp); - -@@ -2418,6 +2449,11 @@ - goto fail; - } - -+ /* [MS-RDPEGDI] 2.2.2.2.1.2.8 requires a nonzero color depth, but some -+ * Windows versions send zero. Fall back to the bitmap data color depth. */ -+ if (!rc) -+ cache_bitmap_v3->bpp = bitmapData->bpp; -+ - Stream_Seek_UINT8(s); /* reserved1 (1 byte) */ - Stream_Seek_UINT8(s); /* reserved2 (1 byte) */ - Stream_Read_UINT8(s, bitmapData->codecID); /* codecID (1 byte) */ -@@ -2425,6 +2461,40 @@ - Stream_Read_UINT16(s, bitmapData->height); /* height (2 bytes) */ - Stream_Read_UINT32(s, new_len); /* length (4 bytes) */ - -+ switch (bitmapData->codecID) -+ { -+ case RDP_CODEC_ID_IMAGE_REMOTEFX: -+ if (!freerdp_settings_get_bool(settings, FreeRDP_RemoteFxImageCodec)) -+ { -+ WLog_Print(update->log, WLOG_ERROR, -+ "codecID RDP_CODEC_ID_IMAGE_REMOTEFX not enabled for this " -+ "connection, aborting"); -+ goto fail; -+ } -+ break; -+ case RDP_CODEC_ID_REMOTEFX: -+ if (!freerdp_settings_get_bool(settings, FreeRDP_RemoteFxCodec)) -+ { -+ WLog_ERR(TAG, -+ "codecID RDP_CODEC_ID_REMOTEFX not enabled for this connection, aborting"); -+ goto fail; -+ } -+ break; -+ case RDP_CODEC_ID_NSCODEC: -+ if (!freerdp_settings_get_bool(settings, FreeRDP_NSCodec)) -+ { -+ WLog_ERR(TAG, -+ "codecID RDP_CODEC_ID_NSCODEC not enabled for this connection, aborting"); -+ goto fail; -+ } -+ break; -+ case RDP_CODEC_ID_NONE: -+ break; -+ default: -+ WLog_ERR(TAG, "Unsupported codecID 0x%08" PRIx32, bitmapData->codecID); -+ goto fail; -+ } -+ - if ((new_len == 0) || (Stream_GetRemainingLength(s) < new_len)) - goto fail; - -@@ -2461,7 +2531,7 @@ - bitsPerPixelId = get_bpp_bmf(cache_bitmap_v3->bpp, &rc); - if (!rc) - return FALSE; -- *flags = (cache_bitmap_v3->cacheId & 0x00000003) | -+ *flags = (cache_bitmap_v3->cacheId & 0x00000007) | - ((cache_bitmap_v3->flags << 7) & 0x0000FF80) | ((bitsPerPixelId << 3) & 0x00000078); - Stream_Write_UINT16(s, cache_bitmap_v3->cacheIndex); /* cacheIndex (2 bytes) */ - Stream_Write_UINT32(s, cache_bitmap_v3->key1); /* key1 (4 bytes) */ ---- a/libfreerdp/gdi/graphics.c -+++ b/libfreerdp/gdi/graphics.c -@@ -129,23 +129,54 @@ - gdi_bitmap->hdc, 0, 0, GDI_SRCCOPY, &context->gdi->palette); - } - -+static BOOL gdi_Bitmap_Rfx(rdpContext* context, rdpBitmap* bitmap, const BYTE* pSrcData, -+ UINT32 SrcSize) -+{ -+ BOOL rc; -+ UINT32 stride; -+ REGION16 invalidRegion; -+ -+ WINPR_ASSERT(context); -+ WINPR_ASSERT(bitmap); -+ WINPR_ASSERT(pSrcData || (SrcSize == 0)); -+ -+ region16_init(&invalidRegion); -+ stride = bitmap->width * GetBytesPerPixel(bitmap->format); -+ rc = rfx_process_message(context->codecs->rfx, pSrcData, SrcSize, bitmap->left, bitmap->top, -+ bitmap->data, bitmap->format, stride, bitmap->height, &invalidRegion); -+ region16_uninit(&invalidRegion); -+ -+ if (!rc) -+ { -+ WLog_ERR(TAG, "rfx_process_message failed"); -+ return FALSE; -+ } -+ -+ return TRUE; -+} -+ - static BOOL gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap, const BYTE* pSrcData, - UINT32 DstWidth, UINT32 DstHeight, UINT32 bpp, UINT32 length, - BOOL compressed, UINT32 codecId) - { - UINT32 SrcSize = length; - rdpGdi* gdi = context->gdi; -- UINT32 size = DstWidth * DstHeight; -+ UINT32 stride; -+ -+ WINPR_ASSERT(context); -+ WINPR_ASSERT(bitmap); -+ WINPR_ASSERT(gdi); -+ - bitmap->compressed = FALSE; - bitmap->format = gdi->dstFormat; - - if ((GetBytesPerPixel(bitmap->format) == 0) || (DstWidth == 0) || (DstHeight == 0) || - (DstWidth > UINT32_MAX / DstHeight) || -- (size > (UINT32_MAX / GetBytesPerPixel(bitmap->format)))) -+ ((DstWidth * DstHeight) > (UINT32_MAX / GetBytesPerPixel(bitmap->format)))) - return FALSE; - -- size *= GetBytesPerPixel(bitmap->format); -- bitmap->length = size; -+ stride = DstWidth * GetBytesPerPixel(bitmap->format); -+ bitmap->length = stride * DstHeight; - bitmap->data = (BYTE*)_aligned_malloc(bitmap->length, 16); - - if (!bitmap->data) -@@ -153,21 +184,50 @@ - - if (compressed) - { -- if (bpp < 32) -- { -- if (!interleaved_decompress(context->codecs->interleaved, pSrcData, SrcSize, DstWidth, -- DstHeight, bpp, bitmap->data, bitmap->format, 0, 0, 0, -- DstWidth, DstHeight, &gdi->palette)) -- return FALSE; -- } -- else -+ WINPR_ASSERT(context->codecs); -+ -+ switch (codecId) - { -- freerdp_planar_switch_bgr(context->codecs->planar, -- context->settings->DrawAllowDynamicColorFidelity); -- if (!planar_decompress(context->codecs->planar, pSrcData, SrcSize, DstWidth, DstHeight, -- bitmap->data, bitmap->format, 0, 0, 0, DstWidth, DstHeight, -- TRUE)) -- return FALSE; -+ case RDP_CODEC_ID_REMOTEFX: -+ case RDP_CODEC_ID_IMAGE_REMOTEFX: -+ if (!gdi_Bitmap_Rfx(context, bitmap, pSrcData, SrcSize)) -+ return FALSE; -+ break; -+ -+ case RDP_CODEC_ID_NSCODEC: -+ { -+ const int status = nsc_process_message( -+ context->codecs->nsc, 32, DstWidth, DstHeight, pSrcData, SrcSize, bitmap->data, -+ bitmap->format, stride, 0, 0, DstWidth, DstHeight, FREERDP_FLIP_VERTICAL); -+ -+ if (status < 1) -+ { -+ WLog_ERR(TAG, "nsc_process_message failed"); -+ return FALSE; -+ } -+ break; -+ } -+ -+ default: -+ if (bpp < 32) -+ { -+ if (!interleaved_decompress(context->codecs->interleaved, pSrcData, SrcSize, -+ DstWidth, DstHeight, bpp, bitmap->data, -+ bitmap->format, stride, 0, 0, DstWidth, DstHeight, -+ &gdi->palette)) -+ return FALSE; -+ } -+ else -+ { -+ freerdp_planar_switch_bgr( -+ context->codecs->planar, -+ context->settings->DrawAllowDynamicColorFidelity); -+ if (!planar_decompress(context->codecs->planar, pSrcData, SrcSize, DstWidth, -+ DstHeight, bitmap->data, bitmap->format, stride, 0, 0, -+ DstWidth, DstHeight, TRUE)) -+ return FALSE; -+ } -+ break; - } - } - else -@@ -186,7 +246,7 @@ - return FALSE; - } - -- if (!freerdp_image_copy(bitmap->data, bitmap->format, 0, 0, 0, DstWidth, DstHeight, -+ if (!freerdp_image_copy(bitmap->data, bitmap->format, stride, 0, 0, DstWidth, DstHeight, - pSrcData, SrcFormat, 0, 0, 0, &gdi->palette, FREERDP_FLIP_VERTICAL)) - return FALSE; - } diff --git a/freerdp-2.11.6-CVE-2026-64624.patch b/freerdp-2.11.6-CVE-2026-64624.patch deleted file mode 100644 index b02aa90..0000000 --- a/freerdp-2.11.6-CVE-2026-64624.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 22c5deea52404f51a13276b3abda44e1e60704cf Mon Sep 17 00:00:00 2001 -From: Armin Novak -Date: Thu, 2 Jul 2026 10:21:54 +0200 -Subject: [PATCH] [client,common] deactivate cli parsing in RDP files - -This undocumented feature may have unintended side effects. Disable it -by default while retaining a compile-time option to enable the legacy -behavior. - -Backported from upstream commit 22c5deea52404f51a13276b3abda44e1e60704cf -for CVE-2026-64624. FreeRDP 2.11.6 performs RDP file parsing in -freerdp_client_parse_rdp_file_buffer_ex() and supports CMake 2.8, so use -the corresponding 2.x parser location and add_definitions() interface. -The FreeRDP 3.x deprecation warning API is intentionally not backported. ---- - client/common/CMakeLists.txt | 5 +++++ - client/common/file.c | 2 ++ - 2 files changed, 7 insertions(+) - -diff --git a/client/common/CMakeLists.txt b/client/common/CMakeLists.txt -index b465a63..330950b 100644 ---- a/client/common/CMakeLists.txt -+++ b/client/common/CMakeLists.txt -@@ -43,6 +43,11 @@ foreach(FREERDP_CHANNELS_CLIENT_SRC ${FREERDP_CHANNELS_CLIENT_SRCS}) - set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} "${FREERDP_CHANNELS_CLIENT_SRC}") - endforeach() - -+option(WITH_EMBEDDED_CLI_IN_RDP_FILES -+ "Allow embedded command-line arguments in RDP files (dangerous)" OFF) -+if(WITH_EMBEDDED_CLI_IN_RDP_FILES) -+ add_definitions(-DWITH_EMBEDDED_CLI_IN_RDP_FILES) -+endif() - - # On windows create dll version information. - # Vendor, product and year are already set in top level CMakeLists.txt -diff --git a/client/common/file.c b/client/common/file.c -index b56fe6f..a116145 100644 ---- a/client/common/file.c -+++ b/client/common/file.c -@@ -721,6 +721,7 @@ BOOL freerdp_client_parse_rdp_file_buffer_ex(rdpFile* file, const BYTE* buffer, - if (freerdp_client_parse_rdp_file_add_line(file, line, index) == -1) - goto fail; - -+#if defined(WITH_EMBEDDED_CLI_IN_RDP_FILES) - if (beg[0] == '/') - { - if (!freerdp_client_parse_rdp_file_option(file, line, index)) -@@ -728,6 +729,7 @@ BOOL freerdp_client_parse_rdp_file_buffer_ex(rdpFile* file, const BYTE* buffer, - - goto next_line; /* FreeRDP option */ - } -+#endif - - d1 = strchr(line, ':'); - --- -2.43.5 diff --git a/freerdp-2.11.6-nsc-limit-copy-area.patch b/freerdp-2.11.6-nsc-limit-copy-area.patch deleted file mode 100644 index 56d9e16..0000000 --- a/freerdp-2.11.6-nsc-limit-copy-area.patch +++ /dev/null @@ -1,19 +0,0 @@ ---- a/libfreerdp/codec/nsc.c -+++ b/libfreerdp/codec/nsc.c -@@ -508,7 +508,15 @@ - return FALSE; - } - -- if (!freerdp_image_copy(pDstData, DstFormat, nDstStride, nXDst, nYDst, width, height, -+ UINT32 cwidth = width; -+ if (1ull * nXDst + width > nWidth) -+ cwidth = nWidth - nXDst; -+ -+ UINT32 cheight = height; -+ if (1ull * nYDst + height > nHeight) -+ cheight = nHeight - nYDst; -+ -+ if (!freerdp_image_copy(pDstData, DstFormat, nDstStride, nXDst, nYDst, cwidth, cheight, - context->BitmapData, PIXEL_FORMAT_BGRA32, 0, 0, 0, NULL, flip)) - return FALSE; - diff --git a/freerdp.spec b/freerdp.spec index dba4c60..edf1c83 100644 --- a/freerdp.spec +++ b/freerdp.spec @@ -16,46 +16,26 @@ Summary: Free implementation of the Remote Desktop Protocol (RDP) Name: freerdp -Version: 2.11.6 -Release: 17%{?dist} -License: ASL 2.0 +Version: 3.31.1 +Release: 1%{?dist} +License: Apache-2.0 AND HPND AND LGPL-2.1-or-later AND LicenseRef-Fedora-Public-Domain AND OFL-1.1 URL: http://www.freerdp.com/ -Source0: https://github.com/FreeRDP/FreeRDP/archive/%{version}/%{name}-%{version}.tar.gz -Patch0001: CVE-2024-32660.patch -Patch0002: CVE-2024-32658.patch -Patch0003: CVE-2024-32659.patch -Patch0004: 0001-fix-CVE-2026-23530-CVE-2026-23531-CVE-2026-23532-CVE.patch -Patch0005: 0001-fix-CVE-2026-23883.patch -Patch0006: 0001-fix-CVE-2026-26955-CVE-2026-26965.patch -Patch0007: freerdp-2.11.6-nsc-limit-copy-area.patch -Patch0008: codec-clear-fix-clear_resize_buffer-checks.patch -Patch0009: freerdp-2.11.6-CVE-2026-44421.patch -Patch0010: freerdp-2.11.6-CVE-2026-24684.patch -Patch0011: freerdp-2.11.6-CVE-2026-29775.patch -Patch0012: freerdp-2.11.6-CVE-2026-25959.patch -Patch0013: freerdp-2.11.6-CVE-2026-24683.patch -Patch0014: freerdp-2.11.6-CVE-2026-25942.patch -Patch0015: freerdp-2.11.6-CVE-2026-31884.patch -Patch0016: freerdp-2.11.6-CVE-2026-31885.patch -Patch0017: freerdp-2.11.6-CVE-2026-31897.patch -Patch0018: freerdp-2.11.6-CVE-2026-33952.patch -Patch0019: freerdp-2.11.6-CVE-2026-33983.patch -Patch0020: freerdp-2.11.6-CVE-2026-33977.patch -Patch0021: freerdp-2.11.6-CVE-2026-33985.patch -Patch0022: freerdp-2.11.6-CVE-2026-24679.patch -Patch0023: freerdp-2.11.6-CVE-2026-29774.patch -Patch0024: freerdp-2.11.6-CVE-2026-29776.patch -Patch0025: freerdp-2.11.6-CVE-2026-44420.patch -Patch0026: freerdp-2.11.6-CVE-2026-33984.patch -Patch0027: freerdp-2.11.6-CVE-2026-33986.patch -Patch0028: freerdp-2.11.6-CVE-2026-55827.patch -Patch0029: freerdp-2.11.6-CVE-2026-64624.patch - -BuildRequires: gcc gcc-c++ alsa-lib-devel cmake cups-devel gsm-devel lame-devel libicu-devel libjpeg-turbo-devel + +# The license of winpr/libwinpr/crt/unicode_builtin.c is not allowed. +# Repack the upstream archive with Source1 to remove that file. +# https://gitlab.com/fedora/legal/fedora-license-data/-/issues/498 +Source0: FreeRDP-%{version}-repack.tar.gz +Source1: freerdp_download_and_repack.sh +Patch0001: core-rdstls-Fix-version-validation-macro.patch +Patch0002: core-rdstls-accept-matching-autoreconnect-cookies.patch +Patch0003: core-rdstls-validate-cookie-session-ID-length.patch + +BuildRequires: gcc gcc-c++ alsa-lib-devel cmake cups-devel gsm-devel lame-devel libicu-devel libjpeg-turbo-devel turbojpeg-devel BuildRequires: libX11-devel libXcursor-devel libXdamage-devel libXext-devel libXi-devel libXinerama-devel BuildRequires: libxkbfile-devel libXrandr-devel libXtst-devel libXv-devel pam-devel xmlto zlib-devel BuildRequires: pkgconfig(cairo) pkgconfig(libpcsclite) pkgconfig(libpulse) pkgconfig(libsystemd) pkgconfig(libusb-1.0) BuildRequires: pkgconfig(openssl) pkgconfig(wayland-client) pkgconfig(wayland-scanner) pkgconfig(xkbcommon) pkgconfig(krb5) +BuildRequires: cmake(json-c) pkgconfig(fdk-aac) pkgconfig(fuse3) pkgconfig(libwebp) pkgconfig(opus) %if %{with tsmf} BuildRequires: pkgconfig(dbus-1) pkgconfig(dbus-glib-1) pkgconfig(glib-2.0) BuildRequires: pkgconfig(gstreamer-1.0) pkgconfig(gstreamer-base-1.0) pkgconfig(gstreamer-app-1.0) @@ -125,23 +105,31 @@ The %{name}-libwinpr-devel package contains libraries and header files for devel that use %{name}-libwinpr. %prep -%autosetup -p1 -n %{name}-%{version} +%autosetup -p1 -n FreeRDP-%{version} find . -name "*.h" -exec chmod 664 {} \; find . -name "*.c" -exec chmod 664 {} \; %build %cmake %{?_cmake_skip_rpath} \ + -DCHANNEL_RDP2TCP=ON \ + -DCHANNEL_RDP2TCP_CLIENT=ON \ + -DCHANNEL_RDPEWA=OFF \ + -DCHANNEL_RDPEWA_CLIENT=OFF \ -DCMAKE_INSTALL_LIBDIR:PATH=%{_lib} \ + -DWITH_AAD=ON \ -DWITH_ALSA=ON \ -DWITH_CAIRO=ON \ -DWITH_CUPS=ON \ -DWITH_CHANNELS=ON -DBUILTIN_CHANNELS=OFF \ -DWITH_CLIENT=ON \ + -DWITH_CLIENT_SDL=OFF \ -DWITH_DIRECTFB=OFF \ + -DWITH_DSP_FFMPEG=%{?cfg_with_ffmpeg} \ + -DWITH_FDK_AAC=ON \ -DWITH_FFMPEG=%{?cfg_with_ffmpeg} \ + -DWITH_FUSE=ON \ -DWITH_GSM=ON \ - -DWITH_GSSAPI=ON \ %if %{with %tsmf} -DWITH_GSTREAMER_1_0=ON -DWITH_GSTREAMER_0_10=OFF \ -DCHANNEL_TSMF=ON \ @@ -149,20 +137,33 @@ find . -name "*.c" -exec chmod 664 {} \; -DWITH_ICU=ON \ -DWITH_IPP=OFF \ -DWITH_JPEG=ON \ + -DWITH_JSONC_REQUIRED=ON \ + -DWITH_KEYBOARD_LAYOUT_FROM_FILE=ON \ + -DWITH_KRB5=ON \ -DWITH_LAME=ON \ -DWITH_MANPAGES=ON \ -DWITH_OPENH264=OFF \ -DWITH_OPENSSL=ON \ + -DWITH_OPUS=ON \ -DWITH_PCSC=ON \ + -DWITH_PKCS11=ON \ -DWITH_PULSE=ON \ + -DWITH_RDTK=ON \ + -DWITH_SAMPLE=OFF \ -DWITH_SERVER=ON \ -DWITH_SERVER_INTERFACE=ON \ -DWITH_SHADOW_X11=ON \ - -DWITH_SHADOW_MAC=ON \ + -DWITH_SHADOW_MAC=OFF \ -DWITH_SOXR=%{?cfg_with_soxr} \ + -DWITH_SWSCALE=%{?cfg_with_ffmpeg} \ + -DWITH_TIMEZONE_COMPILED=OFF \ + -DWITH_TIMEZONE_FROM_FILE=ON \ + -DWITH_URIPARSER=OFF \ + -DWITH_VIDEO_FFMPEG=%{?cfg_with_ffmpeg} \ -DWITH_WAYLAND=ON \ + -DWITH_WEBVIEW=OFF \ -DWITH_X11=ON \ - -DWITH_X264=%OFF \ + -DWITH_X264=OFF \ -DWITH_XCURSOR=ON \ -DWITH_XEXT=ON \ -DWITH_XKBFILE=ON \ @@ -172,6 +173,9 @@ find . -name "*.c" -exec chmod 664 {} \; -DWITH_XTEST=ON \ -DWITH_XV=ON \ -DWITH_ZLIB=ON \ + -DWINPR_UTILS_IMAGE_JPEG=ON \ + -DWINPR_UTILS_IMAGE_PNG=ON \ + -DWINPR_UTILS_IMAGE_WEBP=ON \ %ifarch x86_64 -DWITH_SSE2=ON \ -DWITH_VAAPI=%{?cfg_with_ffmpeg} \ @@ -200,55 +204,72 @@ find %{buildroot} -name "*.a" -delete %files libs %license LICENSE %doc README.md ChangeLog -%{_libdir}/freerdp2/ -%{_libdir}/libfreerdp-client2.so.* -%{_libdir}/libfreerdp-server2.so.* -%{_libdir}/libfreerdp-shadow2.so.* -%{_libdir}/libfreerdp-shadow-subsystem2.so.* -%{_libdir}/libfreerdp2.so.* +%{_datadir}/FreeRDP/ +%{_libdir}/freerdp3/ +%{_libdir}/libfreerdp-client3.so.* +%{_libdir}/libfreerdp-server3.so.* +%{_libdir}/libfreerdp-server-proxy3.so.* +%{_libdir}/libfreerdp-shadow3.so.* +%{_libdir}/libfreerdp-shadow-subsystem3.so.* +%{_libdir}/libfreerdp3.so.* %{_libdir}/libuwac0.so.* +%{_libdir}/librdtk0.so.* %{_mandir}/man7/wlog.* %files devel -%{_includedir}/freerdp2 +%{_includedir}/freerdp3 %{_includedir}/uwac0 -%{_libdir}/cmake/FreeRDP2 -%{_libdir}/cmake/FreeRDP-Client2 -%{_libdir}/cmake/FreeRDP-Server2 -%{_libdir}/cmake/FreeRDP-Shadow2 +%{_includedir}/rdtk0 +%{_libdir}/cmake/FreeRDP3 +%{_libdir}/cmake/FreeRDP-Client3 +%{_libdir}/cmake/FreeRDP-Proxy3 +%{_libdir}/cmake/FreeRDP-Server3 +%{_libdir}/cmake/FreeRDP-Shadow3 %{_libdir}/cmake/uwac0 -%{_libdir}/libfreerdp-client2.so -%{_libdir}/libfreerdp-server2.so -%{_libdir}/libfreerdp-shadow2.so -%{_libdir}/libfreerdp-shadow-subsystem2.so -%{_libdir}/libfreerdp2.so +%{_libdir}/cmake/rdtk0 +%{_libdir}/libfreerdp-client3.so +%{_libdir}/libfreerdp-server3.so +%{_libdir}/libfreerdp-server-proxy3.so +%{_libdir}/libfreerdp-shadow3.so +%{_libdir}/libfreerdp-shadow-subsystem3.so +%{_libdir}/libfreerdp3.so %{_libdir}/libuwac0.so -%{_libdir}/pkgconfig/freerdp2.pc -%{_libdir}/pkgconfig/freerdp-client2.pc -%{_libdir}/pkgconfig/freerdp-server2.pc -%{_libdir}/pkgconfig/freerdp-shadow2.pc +%{_libdir}/librdtk0.so +%{_libdir}/pkgconfig/freerdp3.pc +%{_libdir}/pkgconfig/freerdp-client3.pc +%{_libdir}/pkgconfig/freerdp-server3.pc +%{_libdir}/pkgconfig/freerdp-server-proxy3.pc +%{_libdir}/pkgconfig/freerdp-shadow3.pc %{_libdir}/pkgconfig/uwac0.pc +%{_libdir}/pkgconfig/rdtk0.pc %files server %{_bindir}/freerdp-proxy %{_bindir}/freerdp-shadow-cli +%{_mandir}/man1/freerdp-proxy.1* %{_mandir}/man1/freerdp-shadow-cli.1* %files -n libwinpr %license LICENSE %doc README.md ChangeLog -%{_libdir}/libwinpr2.so.* -%{_libdir}/libwinpr-tools2.so.* +%{_datadir}/WinPR/ +%{_libdir}/libwinpr3.so.* +%{_libdir}/libwinpr-tools3.so.* %files -n libwinpr-devel -%{_includedir}/winpr2 -%{_libdir}/cmake/WinPR2 -%{_libdir}/libwinpr2.so -%{_libdir}/libwinpr-tools2.so -%{_libdir}/pkgconfig/winpr2.pc -%{_libdir}/pkgconfig/winpr-tools2.pc +%{_includedir}/winpr3 +%{_libdir}/cmake/WinPR3 +%{_libdir}/cmake/WinPR-tools3 +%{_libdir}/libwinpr3.so +%{_libdir}/libwinpr-tools3.so +%{_libdir}/pkgconfig/winpr3.pc +%{_libdir}/pkgconfig/winpr-tools3.pc %changelog +* Tue Sep 22 2026 Xinlong Chen - 3.31.1-1 +- [Type] sync +- [DESC] Upgrade to upstream version 3.31.1 + * Mon Jul 27 2026 Xinlong Chen - 2.11.6-17 - [Type] security - [DESC] Fix CVE-2026-64624: disable embedded CLI parsing in RDP files by default diff --git a/freerdp_download_and_repack.sh b/freerdp_download_and_repack.sh new file mode 100755 index 0000000..b1a14ae --- /dev/null +++ b/freerdp_download_and_repack.sh @@ -0,0 +1,18 @@ +#!/bin/sh +set -eu + +version=$(rpmspec -q --srpm --queryformat '%{VERSION}\n' freerdp.spec) +archive="FreeRDP-${version}.tar.gz" +repacked="FreeRDP-${version}-repack.tar.gz" + +curl --fail --location \ + "https://github.com/FreeRDP/FreeRDP/archive/${version}/${archive}" \ + --output "${archive}" + +gzip --decompress "${archive}" +tar --file "FreeRDP-${version}.tar" \ + --delete "*/winpr/libwinpr/crt/unicode_builtin.c" +gzip --best --no-name --stdout "FreeRDP-${version}.tar" > "${repacked}" +rm -f "FreeRDP-${version}.tar" + +echo "${repacked} is prepared" diff --git a/sources b/sources index 414de71..3a92818 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (freerdp-2.11.6.tar.gz) = 4facaff07bc26434474776e2463c9ebf0111190cb6bcf7d3dc7a6b3d8e2de991925a92b7889b2c5dec50ee4cf28f94bb1016c36da207a00ead09005ea0ace36d +SHA512 (FreeRDP-3.31.1-repack.tar.gz) = be669db38cecfc8d774c6165a069c50249fdcb2f8877e767a10e7dc009131ed35363db50b484536f888b7ec9214cbeb1acfc3e129c9cd2694cd498b42718245e -- Gitee