[Buildroot] [PATCH 4/4] package/freerdp: patch various vulnerabilities

Thomas Perale thomas.perale at mind.be
Fri Mar 6 19:53:22 UTC 2026


In reply of:
> Patches mostly backported with the basis of the work of Ubuntu Security
> team. See [1].
> 
> Fix the following vulnerabilities:
> 
> - CVE-2024-32661:
>     FreeRDP is a free implementation of the Remote Desktop Protocol.
>     FreeRDP based clients prior to version 3.5.1 are vulnerable to a
>     possible `NULL` access and crash. Version 3.5.1 contains a patch for
>     the issue. No known workarounds are available.
> 
> For more information, see:
>   - https://www.cve.org/CVERecord?id=CVE-2024-32661
> 
> - CVE-2026-23530:
>     FreeRDP is a free implementation of the Remote Desktop Protocol. Prior
>     to version 3.21.0,`freerdp_bitmap_decompress_planar` does not validate
>     `nSrcWidth`/`nSrcHeight` against `planar->maxWidth`/`maxHeight` before
>     RLE decode. A malicious server can trigger a client‑side heap buffer
>     overflow, causing a crash (DoS) and potential heap corruption with
>     code‑execution risk depending on allocator behavior and surrounding
>     heap layout. Version 3.21.0 contains a patch for the issue.
> 
> For more information, see:
>   - https://www.cve.org/CVERecord?id=CVE-2026-23530
> 
> - CVE-2026-23531:
>     FreeRDP is a free implementation of the Remote Desktop Protocol. Prior
>     to version 3.21.0, in ClearCodec, when `glyphData` is present,
>     `clear_decompress` calls `freerdp_image_copy_no_overlap` without
>     validating the destination rectangle, allowing an out-of-bounds
>     read/write via crafted RDPGFX surface updates. A malicious server can
>     trigger a client‑side heap buffer overflow, causing a crash (DoS) and
>     potential heap corruption with code‑execution risk depending on
>     allocator behavior and surrounding heap layout. Version 3.21.0
>     contains a patch for the issue.
> 
> For more information, see:
>   - https://www.cve.org/CVERecord?id=CVE-2026-23531
> 
> - CVE-2026-23532:
>     FreeRDP is a free implementation of the Remote Desktop Protocol. Prior
>     to version 3.21.0, a client-side heap buffer overflow occurs in the
>     FreeRDP client’s `gdi_SurfaceToSurface` path due to a mismatch between
>     destination rectangle clamping and the actual copy size. A malicious
>     server can trigger a client‑side heap buffer overflow, causing a crash
>     (DoS) and potential heap corruption with code‑execution risk depending
>     on allocator behavior and surrounding heap layout. Version 3.21.0
>     contains a patch for the issue.
> 
> For more information, see:
>   - https://www.cve.org/CVERecord?id=CVE-2026-23532
> 
> - CVE-2026-23533:
>     FreeRDP is a free implementation of the Remote Desktop Protocol. Prior
>     to version 3.21.0, a client-side heap buffer overflow occurs in the
>     RDPGFX ClearCodec decode path when maliciously crafted residual data
>     causes out-of-bounds writes during color output. A malicious server
>     can trigger a client‑side heap buffer overflow, causing a crash (DoS)
>     and potential heap corruption with code‑execution risk depending on
>     allocator behavior and surrounding heap layout. Version 3.21.0
>     contains a patch for the issue.
> 
> For more information, see:
>   - https://www.cve.org/CVERecord?id=CVE-2026-23533
> 
> - CVE-2026-23534:
>     FreeRDP is a free implementation of the Remote Desktop Protocol. Prior
>     to version 3.21.0, a client-side heap buffer overflow occurs in the
>     ClearCodec bands decode path when crafted band coordinates allow
>     writes past the end of the destination surface buffer. A malicious
>     server can trigger a client‑side heap buffer overflow, causing a crash
>     (DoS) and potential heap corruption with code‑execution risk depending
>     on allocator behavior and surrounding heap layout. Version 3.21.0
>     contains a patch for the issue.
> 
> For more information, see:
>   - https://www.cve.org/CVERecord?id=CVE-2026-23534
> 
> - CVE-2026-23948:
>     FreeRDP is a free implementation of the Remote Desktop Protocol. Prior
>     to 3.22.0, a NULL pointer dereference vulnerability in
>     rdp_write_logon_info_v2() allows a malicious RDP server to crash
>     FreeRDP proxy by sending a specially crafted LogonInfoV2 PDU with
>     cbDomain=0 or cbUserName=0. This vulnerability is fixed in 3.22.0.
> 
> For more information, see:
>   - https://www.cve.org/CVERecord?id=CVE-2026-23948
> 
> - CVE-2026-24675:
>     FreeRDP is a free implementation of the Remote Desktop Protocol. Prior
>     to 3.22.0, urb_select_interface can free the device's MS config on
>     error but later code still dereferences it, leading to a use after
>     free in libusb_udev_select_interface. This vulnerability is fixed in
>     3.22.0.
> 
> For more information, see:
>   - https://www.cve.org/CVERecord?id=CVE-2026-24675
> 
> - CVE-2026-24676:
>     FreeRDP is a free implementation of the Remote Desktop Protocol. Prior
>     to 3.22.0, AUDIN format renegotiation frees the active format list
>     while the capture thread continues using audin->format, leading to a
>     use after free in audio_format_compatible. This vulnerability is fixed
>     in 3.22.0.
> 
> For more information, see:
>   - https://www.cve.org/CVERecord?id=CVE-2026-24676
> 
> - CVE-2026-24679:
>     FreeRDP is a free implementation of the Remote Desktop Protocol. Prior
>     to 3.22.0, The URBDRC client uses server-supplied interface numbers as
>     array indices without bounds checks, causing an out-of-bounds read in
>     libusb_udev_select_interface. This vulnerability is fixed in 3.22.0.
> 
> For more information, see:
>   - https://www.cve.org/CVERecord?id=CVE-2026-24679
> 
> - CVE-2026-24681:
>     FreeRDP is a free implementation of the Remote Desktop Protocol. Prior
>     to 3.22.0, aAsynchronous bulk transfer completions can use a freed
>     channel callback after URBDRC channel close, leading to a use after
>     free in urb_write_completion. This vulnerability is fixed in 3.22.0.
> 
> For more information, see:
>   - https://www.cve.org/CVERecord?id=CVE-2026-24681
> 
> - CVE-2026-24682:
>     FreeRDP is a free implementation of the Remote Desktop Protocol. Prior
>     to 3.22.0, audin_server_recv_formats frees an incorrect number of
>     audio formats on parse failure (i + i), leading to out-of-bounds
>     access in audio_formats_free. This vulnerability is fixed in 3.22.0.
> 
> For more information, see:
>   - https://www.cve.org/CVERecord?id=CVE-2026-24682
> 
> - CVE-2026-24683:
>     FreeRDP is a free implementation of the Remote Desktop Protocol.
>     ainput_send_input_event caches channel_callback in a local variable
>     and later uses it without synchronization; a concurrent channel close
>     can free or reinitialize the callback, leading to a use after free.
>     Prior to 3.22.0, This vulnerability is fixed in 3.22.0.
> 
> For more information, see:
>   - https://www.cve.org/CVERecord?id=CVE-2026-24683
> 
> [1] https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/freerdp2/2.6.1+dfsg1-3ubuntu2.10/freerdp2_2.6.1+dfsg1-3ubuntu2.10.debian.tar.xz
> 
> Signed-off-by: Thomas Perale <thomas.perale at mind.be>

Applied to 2025.02.x & 2025.11.x. Thanks

> ---
>  ...ing-check-in-rdp-write-logon-info-v1.patch |  29 +++++
>  .../0010-fix-decoder-length-checks.patch      |  29 +++++
>  .../0011-fix-missing-length-checks.patch      |  31 +++++
>  ...0012-check-clear-decomress-glyphData.patch |  79 ++++++++++++
>  ...0013-properly-clamp-SurfaceToSurface.patch |  48 ++++++++
>  .../0014-fix-clear-resize-buffer-checks.patch |  58 +++++++++
>  .../0015-fix-off-by-one-length-check.patch    |  33 +++++
>  .../freerdp/0016-fix-missing-NULL-check.patch |  55 +++++++++
>  ...0017-do-not-free-MsConfig-on-failure.patch |  31 +++++
>  package/freerdp/0018-reset-audin-format.patch |  35 ++++++
>  ...sure-InterfaceNumber-is-within-range.patch |  43 +++++++
>  ...l-all-usb-transfers-on-channel-close.patch |  24 ++++
>  ...ix-audin-server-recv-formats-cleanup.patch |  26 ++++
>  ...-lock-context-when-updating-listener.patch | 109 ++++++++++++++++
>  .../0023-terminate-thread-before-free.patch   |  64 ++++++++++
>  ...024-only-clean-up-thread-before-free.patch | 116 ++++++++++++++++++
>  package/freerdp/freerdp.mk                    |  44 +++++++
>  17 files changed, 854 insertions(+)
>  create mode 100644 package/freerdp/0009-fix-missing-check-in-rdp-write-logon-info-v1.patch
>  create mode 100644 package/freerdp/0010-fix-decoder-length-checks.patch
>  create mode 100644 package/freerdp/0011-fix-missing-length-checks.patch
>  create mode 100644 package/freerdp/0012-check-clear-decomress-glyphData.patch
>  create mode 100644 package/freerdp/0013-properly-clamp-SurfaceToSurface.patch
>  create mode 100644 package/freerdp/0014-fix-clear-resize-buffer-checks.patch
>  create mode 100644 package/freerdp/0015-fix-off-by-one-length-check.patch
>  create mode 100644 package/freerdp/0016-fix-missing-NULL-check.patch
>  create mode 100644 package/freerdp/0017-do-not-free-MsConfig-on-failure.patch
>  create mode 100644 package/freerdp/0018-reset-audin-format.patch
>  create mode 100644 package/freerdp/0019-ensure-InterfaceNumber-is-within-range.patch
>  create mode 100644 package/freerdp/0020-cancel-all-usb-transfers-on-channel-close.patch
>  create mode 100644 package/freerdp/0021-fix-audin-server-recv-formats-cleanup.patch
>  create mode 100644 package/freerdp/0022-lock-context-when-updating-listener.patch
>  create mode 100644 package/freerdp/0023-terminate-thread-before-free.patch
>  create mode 100644 package/freerdp/0024-only-clean-up-thread-before-free.patch
> 
> diff --git a/package/freerdp/0009-fix-missing-check-in-rdp-write-logon-info-v1.patch b/package/freerdp/0009-fix-missing-check-in-rdp-write-logon-info-v1.patch
> new file mode 100644
> index 0000000000..dfb4bd84c1
> --- /dev/null
> +++ b/package/freerdp/0009-fix-missing-check-in-rdp-write-logon-info-v1.patch
> @@ -0,0 +1,29 @@
> +From 71e463e31b4d69f4022d36bfc814592f56600793 Mon Sep 17 00:00:00 2001
> +From: akallabeth <akallabeth at posteo.net>
> +Date: Sun, 21 Apr 2024 13:56:13 +0200
> +Subject: [PATCH] [core,info] fix missing check in rdp_write_logon_info_v1
> +
> +CVE: CVE-2024-32661
> +Upstream: https://github.com/FreeRDP/FreeRDP/commit/71e463e31b4d69f4022d36bfc814592f56600793
> +[thomas: backport https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/freerdp2/2.6.1+dfsg1-3ubuntu2.10/freerdp2_2.6.1+dfsg1-3ubuntu2.10.debian.tar.xz]
> +Signed-off-by: Thomas Perale <thomas.perale at mind.be>
> +---
> + libfreerdp/core/info.c | 4 ++++
> + 1 file changed, 4 insertions(+)
> +
> +diff --git a/libfreerdp/core/info.c b/libfreerdp/core/info.c
> +index 7d6eec13782d..3395e4d2e04c 100644
> +--- a/libfreerdp/core/info.c
> ++++ b/libfreerdp/core/info.c
> +@@ -1327,6 +1327,10 @@ static BOOL rdp_write_logon_info_v1(wStream* s, logon_info* info)
> + 		return FALSE;
> + 
> + 	/* domain */
> ++	WINPR_ASSERT(info);
> ++	if (!info->domain || !info->username)
> ++		return FALSE;
> ++
> + 	ilen = ConvertToUnicode(CP_UTF8, 0, info->domain, -1, &wString, 0);
> +
> + 	if (ilen < 0)
> +
> diff --git a/package/freerdp/0010-fix-decoder-length-checks.patch b/package/freerdp/0010-fix-decoder-length-checks.patch
> new file mode 100644
> index 0000000000..5f16675ad0
> --- /dev/null
> +++ b/package/freerdp/0010-fix-decoder-length-checks.patch
> @@ -0,0 +1,29 @@
> +From 1bab198a2edd0d0e6e1627d21a433151ea190500 Mon Sep 17 00:00:00 2001
> +From: akallabeth <akallabeth at posteo.net>
> +Date: Thu, 15 Jan 2026 12:02:02 +0100
> +Subject: [PATCH] [codec,planar] fix decoder length checks
> +
> +CVE: CVE-2026-23530
> +Upstream: https://github.com/FreeRDP/FreeRDP/commit/1bab198a2edd0d0e6e1627d21a433151ea190500
> +[thomas: backport https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/freerdp2/2.6.1+dfsg1-3ubuntu2.10/freerdp2_2.6.1+dfsg1-3ubuntu2.10.debian.tar.xz]
> +Signed-off-by: Thomas Perale <thomas.perale at mind.be>
> +---
> + libfreerdp/codec/planar.c | 5 +++++
> + 1 file changed, 5 insertions(+)
> +
> +diff --git a/libfreerdp/codec/planar.c b/libfreerdp/codec/planar.c
> +index 1a06e36edb0c..94a640a551d1 100644
> +--- a/libfreerdp/codec/planar.c
> ++++ b/libfreerdp/codec/planar.c
> +@@ -616,6 +616,11 @@ BOOL freerdp_bitmap_decompress_planar(BITMAP_PLANAR_CONTEXT* WINPR_RESTRICT plan
> + 	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/package/freerdp/0011-fix-missing-length-checks.patch b/package/freerdp/0011-fix-missing-length-checks.patch
> new file mode 100644
> index 0000000000..1c96864318
> --- /dev/null
> +++ b/package/freerdp/0011-fix-missing-length-checks.patch
> @@ -0,0 +1,31 @@
> +From 25102b432fb37916a1a553d7ef8fd940c6e52c3f Mon Sep 17 00:00:00 2001
> +From: akallabeth <akallabeth at posteo.net>
> +Date: Thu, 15 Jan 2026 12:17:33 +0100
> +Subject: [PATCH] [codec,clear] fix missing length checks
> +
> +Upstream: https://github.com/FreeRDP/FreeRDP/commit/25102b432fb37916a1a553d7ef8fd940c6e52c3f.patch
> +CVE: CVE-2026-23531
> +[thomas: backport https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/freerdp2/2.6.1+dfsg1-3ubuntu2.10/freerdp2_2.6.1+dfsg1-3ubuntu2.10.debian.tar.xz]
> +Signed-off-by: Thomas Perale <thomas.perale at mind.be>
> +---
> + libfreerdp/codec/clear.c | 6 ++++--
> + 1 file changed, 4 insertions(+), 2 deletions(-)
> +
> +diff --git a/libfreerdp/codec/clear.c b/libfreerdp/codec/clear.c
> +index aa36baa9b305..4a67a8ed692b 100644
> +--- a/libfreerdp/codec/clear.c
> ++++ b/libfreerdp/codec/clear.c
> +@@ -1141,8 +1141,11 @@ INT32 clear_decompress(CLEAR_CONTEXT* cl
> + 
> + 	if (glyphData)
> + 	{
> +-		if (!freerdp_image_copy(glyphData, clear->format, 0, 0, 0, nWidth, nHeight, pDstData,
> +-		                        DstFormat, nDstStep, nXDst, nYDst, palette, FREERDP_FLIP_NONE))
> ++		const uint32_t w = MIN(nWidth, nDstWidth);
> ++		const uint32_t h = MIN(nHeight, nDstHeight);
> ++		if (!freerdp_image_copy_no_overlap(glyphData, clear->format, 0, 0, 0, w, h, pDstData,
> ++		                                   DstFormat, nDstStep, nXDst, nYDst, palette,
> ++		                                   FREERDP_FLIP_NONE))
> + 			goto fail;
> + 	}
> + 
> diff --git a/package/freerdp/0012-check-clear-decomress-glyphData.patch b/package/freerdp/0012-check-clear-decomress-glyphData.patch
> new file mode 100644
> index 0000000000..7db56cf6c1
> --- /dev/null
> +++ b/package/freerdp/0012-check-clear-decomress-glyphData.patch
> @@ -0,0 +1,79 @@
> +From 243ecf804bb122e8e643a5c142ad5a49d7aa19ee Mon Sep 17 00:00:00 2001
> +From: akallabeth <akallabeth at posteo.net>
> +Date: Fri, 16 Jan 2026 12:22:46 +0100
> +Subject: [PATCH] [codec,clear] check clear_decomress glyphData
> +
> +Check destination coordinates and lengths against the actual sizes. Log
> +every truncation accordingly
> +
> +CVE: CVE-2026-23531
> +Upstream: https://github.com/FreeRDP/FreeRDP/commit/243ecf804bb122e8e643a5c142ad5a49d7aa19ee
> +[thomas: backport https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/freerdp2/2.6.1+dfsg1-3ubuntu2.10/freerdp2_2.6.1+dfsg1-3ubuntu2.10.debian.tar.xz]
> +Signed-off-by: Thomas Perale <thomas.perale at mind.be>
> +---
> + libfreerdp/codec/clear.c | 50 ++++++++++++++++++++++++++++++++++++++--
> + 1 file changed, 48 insertions(+), 2 deletions(-)
> +
> +diff --git a/libfreerdp/codec/clear.c b/libfreerdp/codec/clear.c
> +index 0efa89f8d06c..f9aa4f0000c1 100644
> +--- a/libfreerdp/codec/clear.c
> ++++ b/libfreerdp/codec/clear.c
> +@@ -1141,9 +1141,55 @@ INT32 clear_decompress(CLEAR_CONTEXT* cl
> + 
> + 	if (glyphData)
> + 	{
> +-		const uint32_t w = MIN(nWidth, nDstWidth);
> +-		const uint32_t h = MIN(nHeight, nDstHeight);
> +-		if (!freerdp_image_copy_no_overlap(glyphData, clear->format, 0, 0, 0, w, h, pDstData,
> ++		uint32_t w = MIN(nWidth, nDstWidth);
> ++		if (nXDst > nDstWidth)
> ++		{
> ++			WLog_WARN(TAG, "glyphData copy area x exceeds destination: x=%" PRIu32 " > %" PRIu32,
> ++			          nXDst, nDstWidth);
> ++			w = 0;
> ++		}
> ++		else if (nXDst + w > nDstWidth)
> ++		{
> ++			WLog_WARN(TAG,
> ++			          "glyphData copy area x + width exceeds destination: x=%" PRIu32 " + %" PRIu32
> ++			          " > %" PRIu32,
> ++			          nXDst, w, nDstWidth);
> ++			w = nDstWidth - nXDst;
> ++		}
> ++
> ++		if (w != nWidth)
> ++		{
> ++			WLog_WARN(TAG,
> ++			          "glyphData copy area width truncated: requested=%" PRIu32
> ++			          ", truncated to %" PRIu32,
> ++			          nWidth, w);
> ++		}
> ++
> ++		uint32_t h = MIN(nHeight, nDstHeight);
> ++		if (nYDst > nDstHeight)
> ++		{
> ++			WLog_WARN(TAG, "glyphData copy area y exceeds destination: y=%" PRIu32 " > %" PRIu32,
> ++			          nYDst, nDstHeight);
> ++			h = 0;
> ++		}
> ++		else if (nYDst + h > nDstHeight)
> ++		{
> ++			WLog_WARN(TAG,
> ++			          "glyphData copy area y + height exceeds destination: x=%" PRIu32 " + %" PRIu32
> ++			          " > %" PRIu32,
> ++			          nYDst, h, nDstHeight);
> ++			h = nDstHeight - nYDst;
> ++		}
> ++
> ++		if (h != nHeight)
> ++		{
> ++			WLog_WARN(TAG,
> ++			          "glyphData copy area height truncated: requested=%" PRIu32
> ++			          ", truncated to %" PRIu32,
> ++			          nHeight, h);
> ++		}
> ++
> ++		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/package/freerdp/0013-properly-clamp-SurfaceToSurface.patch b/package/freerdp/0013-properly-clamp-SurfaceToSurface.patch
> new file mode 100644
> index 0000000000..541da75367
> --- /dev/null
> +++ b/package/freerdp/0013-properly-clamp-SurfaceToSurface.patch
> @@ -0,0 +1,48 @@
> +From c4a7c371342edf0d307cea728f56d3302f0ab38c Mon Sep 17 00:00:00 2001
> +From: akallabeth <akallabeth at posteo.net>
> +Date: Thu, 15 Jan 2026 12:04:36 +0100
> +Subject: [PATCH] [gdi,gfx] properly clamp SurfaceToSurface
> +
> +CVE: CVE-2026-23532
> +Upstream: https://github.com/FreeRDP/FreeRDP/commit/c4a7c371342edf0d307cea728f56d3302f0ab38c
> +[thomas: backport https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/freerdp2/2.6.1+dfsg1-3ubuntu2.10/freerdp2_2.6.1+dfsg1-3ubuntu2.10.debian.tar.xz]
> +Signed-off-by: Thomas Perale <thomas.perale at mind.be>
> +---
> + libfreerdp/gdi/gfx.c | 10 +++++-----
> + 1 file changed, 5 insertions(+), 5 deletions(-)
> +
> +diff --git a/libfreerdp/gdi/gfx.c b/libfreerdp/gdi/gfx.c
> +index 56e6ff9ed50b..96ce1007025c 100644
> +--- a/libfreerdp/gdi/gfx.c
> ++++ b/libfreerdp/gdi/gfx.c
> +@@ -1175,7 +1175,6 @@ static UINT gdi_SurfaceToSurface(RdpgfxC
> + 	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(RdpgfxC
> + 	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(RdpgfxC
> + 		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;
> diff --git a/package/freerdp/0014-fix-clear-resize-buffer-checks.patch b/package/freerdp/0014-fix-clear-resize-buffer-checks.patch
> new file mode 100644
> index 0000000000..9913da8d72
> --- /dev/null
> +++ b/package/freerdp/0014-fix-clear-resize-buffer-checks.patch
> @@ -0,0 +1,58 @@
> +From c4391827d7facfc874ca7f61a92afb82232a5748 Mon Sep 17 00:00:00 2001
> +From: akallabeth <akallabeth at posteo.net>
> +Date: Thu, 15 Jan 2026 12:11:57 +0100
> +Subject: [PATCH] [codec,clear] fix clear_resize_buffer checks
> +
> +CVE: CVE-2026-23533
> +Upstream: https://github.com/FreeRDP/FreeRDP/commit/c4391827d7facfc874ca7f61a92afb82232a5748
> +[thomas: backport https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/freerdp2/2.6.1+dfsg1-3ubuntu2.10/freerdp2_2.6.1+dfsg1-3ubuntu2.10.debian.tar.xz]
> +Signed-off-by: Thomas Perale <thomas.perale at mind.be>
> +---
> + libfreerdp/codec/clear.c | 15 ++++++++-------
> + 1 file changed, 8 insertions(+), 7 deletions(-)
> +
> +diff --git a/libfreerdp/codec/clear.c b/libfreerdp/codec/clear.c
> +index ad57529093e3..aa36baa9b305 100644
> +--- a/libfreerdp/codec/clear.c
> ++++ b/libfreerdp/codec/clear.c
> +@@ -62,7 +62,7 @@ struct S_CLEAR_CONTEXT
> + 	NSC_CONTEXT* nsc;
> + 	UINT32 seqNumber;
> + 	BYTE* TempBuffer;
> +-	UINT32 TempSize;
> ++	size_t TempSize;
> + 	UINT32 nTempStep;
> + 	UINT32 TempFormat;
> + 	UINT32 format;
> +@@ -313,16 +313,17 @@ static BOOL clear_decompress_subcode_rlex(wStream* WINPR_RESTRICT s, UINT32 bitm
> + 
> + 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)
> + 		{
> +@@ -330,7 +331,7 @@ static BOOL clear_resize_buffer(CLEAR_CONTEXT* WINPR_RESTRICT clear, UINT32 widt
> + 			return FALSE;
> + 		}
> + 
> +-		clear->TempSize = size;
> ++		clear->TempSize = size * bpp;
> + 		clear->TempBuffer = tmp;
> + 	}
> + 
> diff --git a/package/freerdp/0015-fix-off-by-one-length-check.patch b/package/freerdp/0015-fix-off-by-one-length-check.patch
> new file mode 100644
> index 0000000000..898603fdcd
> --- /dev/null
> +++ b/package/freerdp/0015-fix-off-by-one-length-check.patch
> @@ -0,0 +1,33 @@
> +From f8688b57f6cfad9a0b05475a6afbde355ffab720 Mon Sep 17 00:00:00 2001
> +From: akallabeth <akallabeth at posteo.net>
> +Date: Thu, 15 Jan 2026 12:19:53 +0100
> +Subject: [PATCH] [codec,clear] fix off by one length check
> +
> +CVE: CVE-2026-23534
> +Upstream: https://github.com/FreeRDP/FreeRDP/commit/f8688b57f6cfad9a0b05475a6afbde355ffab720
> +[thomas: backport https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/freerdp2/2.6.1+dfsg1-3ubuntu2.10/freerdp2_2.6.1+dfsg1-3ubuntu2.10.debian.tar.xz]
> +Signed-off-by: Thomas Perale <thomas.perale at mind.be>
> +---
> + libfreerdp/codec/clear.c | 4 ++--
> + 1 file changed, 2 insertions(+), 2 deletions(-)
> +
> +diff --git a/libfreerdp/codec/clear.c b/libfreerdp/codec/clear.c
> +index 4a67a8ed692b..0efa89f8d06c 100644
> +--- a/libfreerdp/codec/clear.c
> ++++ b/libfreerdp/codec/clear.c
> +@@ -881,11 +881,14 @@ static BOOL clear_decompress_bands_data(
> + 				if (count > nHeight)
> + 					count = nHeight;
> + 
> +-				if (nXDstRel + i > nDstWidth)
> ++				if (nXDstRel + i >= nDstWidth)
> + 					return FALSE;
> + 
> + 				for (UINT32 y = 0; y < count; y++)
> + 				{
> ++					if (nYDstRel + y >= nDstHeight)
> ++						return FALSE;
> ++
> + 					BYTE* pDstPixel8 = &pDstData[((nYDstRel + y) * nDstStep) +
> + 					                             ((nXDstRel + i) * GetBytesPerPixel(DstFormat))];
> + 					UINT32 color = ReadColor(cpSrcPixel, clear->format);
> diff --git a/package/freerdp/0016-fix-missing-NULL-check.patch b/package/freerdp/0016-fix-missing-NULL-check.patch
> new file mode 100644
> index 0000000000..245c05d9d5
> --- /dev/null
> +++ b/package/freerdp/0016-fix-missing-NULL-check.patch
> @@ -0,0 +1,55 @@
> +From 4d44e3c097656a8b9ec696353647b0888ca45860 Mon Sep 17 00:00:00 2001
> +From: akallabeth <akallabeth at posteo.net>
> +Date: Mon, 19 Jan 2026 20:11:24 +0100
> +Subject: [PATCH] [core,info] fix missing NULL check
> +
> +Upstream: https://github.com/FreeRDP/FreeRDP/commit/4d44e3c097656a8b9ec696353647b0888ca45860
> +CVE: CVE-2026-23948
> +[thomas: backport https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/freerdp2/2.6.1+dfsg1-3ubuntu2.10/freerdp2_2.6.1+dfsg1-3ubuntu2.10.debian.tar.xz]
> +Signed-off-by: Thomas Perale <thomas.perale at mind.be>
> +---
> + libfreerdp/core/info.c | 14 +++++++++-----
> + 1 file changed, 9 insertions(+), 5 deletions(-)
> +
> +diff --git a/libfreerdp/core/info.c b/libfreerdp/core/info.c
> +index 0b17b75d9f64..cc54aee7baef 100644
> +--- a/libfreerdp/core/info.c
> ++++ b/libfreerdp/core/info.c
> +@@ -1372,7 +1372,7 @@ static BOOL rdp_write_logon_info_v1(wStr
> + 	return TRUE;
> + }
> + 
> +-static BOOL rdp_write_logon_info_v2(wStream* s, logon_info* info)
> ++static BOOL rdp_write_logon_info_v2(wStream* s, const logon_info* info)
> + {
> + 	UINT32 Size = 2 + 4 + 4 + 4 + 4 + 558;
> + 	size_t domainLen, usernameLen;
> +@@ -1385,11 +1385,13 @@ static BOOL rdp_write_logon_info_v2(wStr
> + 	Stream_Write_UINT16(s, SAVE_SESSION_PDU_VERSION_ONE);
> + 	Stream_Write_UINT32(s, Size);
> + 	Stream_Write_UINT32(s, info->sessionId);
> +-	domainLen = strlen(info->domain);
> ++	if (info->domain)
> ++		domainLen = strlen(info->domain);
> + 	if (domainLen > UINT32_MAX)
> + 		return FALSE;
> + 	Stream_Write_UINT32(s, (UINT32)(domainLen + 1) * 2);
> +-	usernameLen = strlen(info->username);
> ++	if (info->username)
> ++		usernameLen = strlen(info->username);
> + 	if (usernameLen > UINT32_MAX)
> + 		return FALSE;
> + 	Stream_Write_UINT32(s, (UINT32)(usernameLen + 1) * 2);
> +@@ -1466,10 +1468,10 @@ static BOOL rdp_write_logon_info_ex(wStr
> + 
> + BOOL rdp_send_save_session_info(rdpContext* context, UINT32 type, void* data)
> + {
> +-	wStream* s;
> + 	BOOL status;
> ++	WINPR_ASSERT(context);
> + 	rdpRdp* rdp = context->rdp;
> +-	s = rdp_data_pdu_init(rdp);
> ++	wStream* s = rdp_data_pdu_init(rdp);
> + 
> + 	if (!s)
> + 		return FALSE;
> diff --git a/package/freerdp/0017-do-not-free-MsConfig-on-failure.patch b/package/freerdp/0017-do-not-free-MsConfig-on-failure.patch
> new file mode 100644
> index 0000000000..ceb9b8a898
> --- /dev/null
> +++ b/package/freerdp/0017-do-not-free-MsConfig-on-failure.patch
> @@ -0,0 +1,31 @@
> +From d676518809c319eec15911c705c13536036af2ae Mon Sep 17 00:00:00 2001
> +From: akallabeth <akallabeth at posteo.net>
> +Date: Mon, 26 Jan 2026 11:54:56 +0100
> +Subject: [PATCH] [channels,urbdrc] do not free MsConfig on failure
> +
> +let the channel handle it later.
> +
> +CVE: CVE-2026-24675
> +Upstream: https://github.com/FreeRDP/FreeRDP/commit/d676518809c319eec15911c705c13536036af2ae
> +[thomas: backport https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/freerdp2/2.6.1+dfsg1-3ubuntu2.10/freerdp2_2.6.1+dfsg1-3ubuntu2.10.debian.tar.xz]
> +Signed-off-by: Thomas Perale <thomas.perale at mind.be>
> +---
> + channels/urbdrc/client/data_transfer.c | 4 +---
> + 1 file changed, 1 insertion(+), 3 deletions(-)
> +
> +diff --git a/channels/urbdrc/client/data_transfer.c b/channels/urbdrc/client/data_transfer.c
> +index af4b9fb5f641..c4042107d4ee 100644
> +--- a/channels/urbdrc/client/data_transfer.c
> ++++ b/channels/urbdrc/client/data_transfer.c
> +@@ -570,10 +570,8 @@ static UINT urb_select_interface(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callb
> + 	MsConfig = pdev->get_MsConfig(pdev);
> + 	InterfaceNumber = MsInterface->InterfaceNumber;
> + 	if (!msusb_msinterface_replace(MsConfig, InterfaceNumber, MsInterface))
> +-	{
> +-		msusb_msconfig_free(MsConfig);
> + 		return ERROR_BAD_CONFIGURATION;
> +-	}
> ++
> + 	/* complete configuration setup */
> + 	if (!pdev->complete_msconfig_setup(pdev, MsConfig))
> + 	{
> diff --git a/package/freerdp/0018-reset-audin-format.patch b/package/freerdp/0018-reset-audin-format.patch
> new file mode 100644
> index 0000000000..c15ec93b7c
> --- /dev/null
> +++ b/package/freerdp/0018-reset-audin-format.patch
> @@ -0,0 +1,35 @@
> +From 026b81ae5831ac1598d8f7371e0d0996fac7db00 Mon Sep 17 00:00:00 2001
> +From: akallabeth <akallabeth at posteo.net>
> +Date: Mon, 26 Jan 2026 10:20:23 +0100
> +Subject: [PATCH] [channels,audin] reset audin->format
> +
> +Whenever the underlying structure changes reset the pointer to NULL
> +
> +CVE: CVE-2026-24676
> +Upstream: https://github.com/FreeRDP/FreeRDP/commit/026b81ae5831ac1598d8f7371e0d0996fac7db00
> +[thomas: backport https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/freerdp2/2.6.1+dfsg1-3ubuntu2.10/freerdp2_2.6.1+dfsg1-3ubuntu2.10.debian.tar.xz]
> +Signed-off-by: Thomas Perale <thomas.perale at mind.be>
> +---
> + channels/audin/client/audin_main.c | 2 ++
> + 1 file changed, 2 insertions(+)
> +
> +diff --git a/channels/audin/client/audin_main.c b/channels/audin/client/audin_main.c
> +index c57c65a62d4e..76d87bb9c1ed 100644
> +--- a/channels/audin/client/audin_main.c
> ++++ b/channels/audin/client/audin_main.c
> +@@ -219,6 +219,7 @@ static UINT audin_process_formats(AUDIN_
> + 	}
> + 
> + 	Stream_Seek_UINT32(s); /* cbSizeFormatsPacket */
> ++	audin->format = NULL;
> + 	callback->formats = audio_formats_new(NumFormats);
> + 
> + 	if (!callback->formats)
> +@@ -293,6 +294,7 @@ out:
> + 
> + 	if (error != CHANNEL_RC_OK)
> + 	{
> ++		audin->format = NULL;
> + 		audio_formats_free(callback->formats, NumFormats);
> + 		callback->formats = NULL;
> + 	}
> diff --git a/package/freerdp/0019-ensure-InterfaceNumber-is-within-range.patch b/package/freerdp/0019-ensure-InterfaceNumber-is-within-range.patch
> new file mode 100644
> index 0000000000..0e5e213703
> --- /dev/null
> +++ b/package/freerdp/0019-ensure-InterfaceNumber-is-within-range.patch
> @@ -0,0 +1,43 @@
> +From 2d563a50be17c1b407ca448b1321378c0726dd31 Mon Sep 17 00:00:00 2001
> +From: akallabeth <akallabeth at posteo.net>
> +Date: Mon, 26 Jan 2026 10:59:39 +0100
> +Subject: [PATCH] [channels,urbdrc] ensure InterfaceNumber is within range
> +
> +CVE: CVE-2026-24679
> +Upstream: https://github.com/FreeRDP/FreeRDP/commit/2d563a50be17c1b407ca448b1321378c0726dd31
> +[thomas: backport https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/freerdp2/2.6.1+dfsg1-3ubuntu2.10/freerdp2_2.6.1+dfsg1-3ubuntu2.10.debian.tar.xz]
> +Signed-off-by: Thomas Perale <thomas.perale at mind.be>
> +---
> + 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 6c2376f74fd6..5341248ec64f 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(
> + {
> + 	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/package/freerdp/0020-cancel-all-usb-transfers-on-channel-close.patch b/package/freerdp/0020-cancel-all-usb-transfers-on-channel-close.patch
> new file mode 100644
> index 0000000000..130f86ecbc
> --- /dev/null
> +++ b/package/freerdp/0020-cancel-all-usb-transfers-on-channel-close.patch
> @@ -0,0 +1,24 @@
> +From 414f701464929c217f2509bcbd6d2c1f00f7ed73 Mon Sep 17 00:00:00 2001
> +From: akallabeth <akallabeth at posteo.net>
> +Date: Mon, 26 Jan 2026 11:07:25 +0100
> +Subject: [PATCH] [channels,urbdrc] cancel all usb transfers on channel close
> +
> +CVE: CVE-2026-24681
> +Upstream: https://github.com/FreeRDP/FreeRDP/commit/414f701464929c217f2509bcbd6d2c1f00f7ed73
> +Signed-off-by: Thomas Perale <thomas.perale at mind.be>
> +---
> + channels/urbdrc/client/libusb/libusb_udevice.c | 1 +
> + 1 file changed, 1 insertion(+)
> +
> +diff --git a/channels/urbdrc/client/libusb/libusb_udevice.c b/channels/urbdrc/client/libusb/libusb_udevice.c
> +index 5341248ec64f..9e2d3ec5a193 100644
> +--- a/channels/urbdrc/client/libusb/libusb_udevice.c
> ++++ b/channels/urbdrc/client/libusb/libusb_udevice.c
> +@@ -1116,6 +1116,7 @@ static void libusb_udev_mark_channel_closed(IUDEVICE* idev)
> + 		const uint8_t devNr = idev->get_dev_number(idev);
> + 
> + 		pdev->status |= URBDRC_DEVICE_CHANNEL_CLOSED;
> ++		pdev->iface.cancel_all_transfer_request(&pdev->iface);
> + 		urbdrc->udevman->unregister_udevice(urbdrc->udevman, busNr, devNr);
> + 	}
> + }
> diff --git a/package/freerdp/0021-fix-audin-server-recv-formats-cleanup.patch b/package/freerdp/0021-fix-audin-server-recv-formats-cleanup.patch
> new file mode 100644
> index 0000000000..5db318b4fd
> --- /dev/null
> +++ b/package/freerdp/0021-fix-audin-server-recv-formats-cleanup.patch
> @@ -0,0 +1,26 @@
> +From 1c5c74223179d425a1ce6dbbb6a3dd2a958b7aee Mon Sep 17 00:00:00 2001
> +From: akallabeth <akallabeth at posteo.net>
> +Date: Mon, 26 Jan 2026 10:14:08 +0100
> +Subject: [PATCH] [channels,audin] fix audin_server_recv_formats cleanup
> +
> +CVE: CVE-2026-24682
> +Upstream: https://github.com/FreeRDP/FreeRDP/commit/1c5c74223179d425a1ce6dbbb6a3dd2a958b7aee
> +[thomas: backport https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/freerdp2/2.6.1+dfsg1-3ubuntu2.10/freerdp2_2.6.1+dfsg1-3ubuntu2.10.debian.tar.xz]
> +Signed-off-by: Thomas Perale <thomas.perale at mind.be>
> +---
> + channels/audin/server/audin.c | 6 +-----
> + 1 file changed, 1 insertion(+), 5 deletions(-)
> +
> +diff --git a/channels/audin/server/audin.c b/channels/audin/server/audin.c
> +index 5046a7d6f27c..17077efa6652 100644
> +--- a/channels/audin/server/audin.c
> ++++ b/channels/audin/server/audin.c
> +@@ -215,7 +215,7 @@ static UINT audin_server_recv_formats(au
> + 
> + 		if (!audio_format_read(s, format))
> + 		{
> +-			audio_formats_free(audin->context.client_formats, i);
> ++			audio_formats_free(audin->context.client_formats, audin->context.num_client_formats);
> + 			audin->context.client_formats = NULL;
> + 			WLog_ERR(TAG, "expected length at least 18, but got %" PRIu32 "", length);
> + 			return ERROR_INVALID_DATA;
> diff --git a/package/freerdp/0022-lock-context-when-updating-listener.patch b/package/freerdp/0022-lock-context-when-updating-listener.patch
> new file mode 100644
> index 0000000000..903e6af7f8
> --- /dev/null
> +++ b/package/freerdp/0022-lock-context-when-updating-listener.patch
> @@ -0,0 +1,109 @@
> +From d9ca272dce7a776ab475e9b1a8e8c3d2968c8486 Mon Sep 17 00:00:00 2001
> +From: akallabeth <akallabeth at posteo.net>
> +Date: Mon, 26 Jan 2026 12:08:48 +0100
> +Subject: [PATCH] [channels,ainput] lock context when updating listener
> +
> +CVE: CVE-2026-24683
> +Upstream: https://github.com/FreeRDP/FreeRDP/commit/d9ca272dce7a776ab475e9b1a8e8c3d2968c8486
> +[thomas: backport https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/freerdp2/2.6.1+dfsg1-3ubuntu2.10/freerdp2_2.6.1+dfsg1-3ubuntu2.10.debian.tar.xz]
> +Signed-off-by: Thomas Perale <thomas.perale at mind.be>
> +---
> + channels/ainput/client/ainput_main.c | 36 ++++++++++++++++++++--------
> + 1 file changed, 26 insertions(+), 10 deletions(-)
> +
> +diff --git a/channels/ainput/client/ainput_main.c b/channels/ainput/client/ainput_main.c
> +index c291bd727285..5545753600a1 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;
> + };
> + 
> + /**
> +@@ -109,10 +110,7 @@ static UINT ainput_on_data_received(IWTS
> + 
> + static UINT ainput_send_input_event(AInputClientContext* context, UINT64 flags, INT32 x, INT32 y)
> + {
> +-	AINPUT_PLUGIN* ainput;
> +-	AINPUT_CHANNEL_CALLBACK* callback;
> + 	BYTE buffer[32] = { 0 };
> +-	UINT64 time;
> + 	wStream sbuffer = { 0 };
> + 	wStream* s = &sbuffer;
> + 
> +@@ -121,8 +119,8 @@ static UINT ainput_send_input_event(AInp
> + 	WINPR_ASSERT(s);
> + 	WINPR_ASSERT(context);
> + 
> +-	time = GetTickCount64();
> +-	ainput = (AINPUT_PLUGIN*)context->handle;
> ++	const UINT64 time = GetTickCount64();
> ++	AINPUT_PLUGIN* ainput = (AINPUT_PLUGIN*)context->handle;
> + 	WINPR_ASSERT(ainput);
> + 	WINPR_ASSERT(ainput->listener_callback);
> + 
> +@@ -132,8 +130,6 @@ static UINT ainput_send_input_event(AInp
> + 		          ainput->MajorVersion, ainput->MinorVersion);
> + 		return CHANNEL_RC_UNSUPPORTED_VERSION;
> + 	}
> +-	callback = ainput->listener_callback->channel_callback;
> +-	WINPR_ASSERT(callback);
> + 
> + 	{
> + 		char buffer[128] = { 0 };
> +@@ -152,10 +148,15 @@ static UINT ainput_send_input_event(AInp
> + 	Stream_SealLength(s);
> + 
> + 	/* ainput back what we have received. AINPUT does not have any message IDs. */
> ++	EnterCriticalSection(&ainput->lock);
> ++	AINPUT_CHANNEL_CALLBACK* 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),
> ++	const UINT rc = callback->channel->Write(callback->channel, (ULONG)Stream_Length(s), Stream_Buffer(s),
> + 	                                NULL);
> ++	LeaveCriticalSection(&ainput->lock);
> ++	return rc;
> + }
> + 
> + /**
> +@@ -167,7 +168,14 @@ static UINT ainput_on_close(IWTSVirtualC
> + {
> + 	AINPUT_CHANNEL_CALLBACK* callback = (AINPUT_CHANNEL_CALLBACK*)pChannelCallback;
> + 
> +-	free(callback);
> ++	if (callback)
> ++	{
> ++		AINPUT_PLUGIN* ainput = (AINPUT_PLUGIN*)callback->plugin;
> ++		WINPR_ASSERT(ainput);
> ++		EnterCriticalSection(&ainput->lock);
> ++		free(callback);
> ++		LeaveCriticalSection(&ainput->lock);
> ++	}
> + 
> + 	return CHANNEL_RC_OK;
> + }
> +@@ -242,7 +250,10 @@ static UINT ainput_plugin_initialize(IWT
> + 	status = pChannelMgr->CreateListener(pChannelMgr, AINPUT_DVC_CHANNEL_NAME, 0,
> + 	                                     &ainput->listener_callback->iface, &ainput->listener);
> + 
> ++	InitializeCriticalSection(&ainput->lock);
> ++	EnterCriticalSection(&ainput->lock);
> + 	ainput->listener->pInterface = ainput->iface.pInterface;
> ++	LeaveCriticalSection(&ainput->lock);
> + 	ainput->initialized = status == CHANNEL_RC_OK;
> + 	return status;
> + }
> +@@ -255,6 +266,8 @@ static UINT ainput_plugin_initialize(IWT
> + static UINT ainput_plugin_terminated(IWTSPlugin* pPlugin)
> + {
> + 	AINPUT_PLUGIN* ainput = (AINPUT_PLUGIN*)pPlugin;
> ++	WINPR_ASSERT(ainput);
> ++	DeleteCriticalSection(&ainput->lock);
> + 	if (ainput && ainput->listener_callback)
> + 	{
> + 		IWTSVirtualChannelManager* mgr = ainput->listener_callback->channel_mgr;
> diff --git a/package/freerdp/0023-terminate-thread-before-free.patch b/package/freerdp/0023-terminate-thread-before-free.patch
> new file mode 100644
> index 0000000000..d0eb600e8d
> --- /dev/null
> +++ b/package/freerdp/0023-terminate-thread-before-free.patch
> @@ -0,0 +1,64 @@
> +From 622bb7b4402491ca003f47472d0e478132673696 Mon Sep 17 00:00:00 2001
> +From: akallabeth <akallabeth at posteo.net>
> +Date: Mon, 26 Jan 2026 10:48:14 +0100
> +Subject: [PATCH] [channels,rdpsnd] terminate thread before free
> +
> +Ensure that the optional rdpsnd thread is terminated and the message
> +queue freed up before releasing the channel context memory
> +
> +CVE: CVE-2026-24684
> +Upstream: https://github.com/FreeRDP/FreeRDP/commit/622bb7b4402491ca003f47472d0e478132673696
> +[thomas: backport https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/freerdp2/2.6.1+dfsg1-3ubuntu2.10/freerdp2_2.6.1+dfsg1-3ubuntu2.10.debian.tar.xz]
> +Signed-off-by: Thomas Perale <thomas.perale at mind.be>
> +---
> + channels/rdpsnd/client/rdpsnd_main.c | 28 +++++++++++++++++++---------
> + 1 file changed, 19 insertions(+), 9 deletions(-)
> +
> +diff --git a/channels/rdpsnd/client/rdpsnd_main.c b/channels/rdpsnd/client/rdpsnd_main.c
> +index 49c763a87e9b..61a29ec40aa8 100644
> +--- a/channels/rdpsnd/client/rdpsnd_main.c
> ++++ b/channels/rdpsnd/client/rdpsnd_main.c
> +@@ -1244,11 +1244,27 @@ fail:
> + 	return CHANNEL_RC_NO_MEMORY;
> + }
> + 
> ++static void rdpsnd_terminate_thread(rdpsndPlugin* rdpsnd)
> ++{
> ++	WINPR_ASSERT(rdpsnd);
> ++	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 +1412,7 @@ void rdpsnd_virtual_channel_event_termin
> + {
> + 	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/package/freerdp/0024-only-clean-up-thread-before-free.patch b/package/freerdp/0024-only-clean-up-thread-before-free.patch
> new file mode 100644
> index 0000000000..163ad9b8cd
> --- /dev/null
> +++ b/package/freerdp/0024-only-clean-up-thread-before-free.patch
> @@ -0,0 +1,116 @@
> +From afa6851dc80835d3101e40fcef51b6c5c0f43ea5 Mon Sep 17 00:00:00 2001
> +From: akallabeth <akallabeth at posteo.net>
> +Date: Wed, 28 Jan 2026 09:31:06 +0100
> +Subject: [PATCH] [channel,rdpsnd] only clean up thread before free
> +
> +rdpsnd channel usually has multiple instances (static, dynamic, ...) so
> +ensure only to terminate the handler thread when the channel is actually
> +closed for good.
> +
> +CVE: CVE-2026-24684
> +Upstream: https://github.com/FreeRDP/FreeRDP/commit/afa6851dc80835d3101e40fcef51b6c5c0f43ea5
> +[thomas: backport https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/freerdp2/2.6.1+dfsg1-3ubuntu2.10/freerdp2_2.6.1+dfsg1-3ubuntu2.10.debian.tar.xz]
> +Signed-off-by: Thomas Perale <thomas.perale at mind.be>
> +---
> + channels/rdpsnd/client/rdpsnd_main.c | 43 ++++++++++++++++------------
> + 1 file changed, 25 insertions(+), 18 deletions(-)
> +
> +diff --git a/channels/rdpsnd/client/rdpsnd_main.c b/channels/rdpsnd/client/rdpsnd_main.c
> +index 61a29ec40aa8..5a1edaea62c6 100644
> +--- a/channels/rdpsnd/client/rdpsnd_main.c
> ++++ b/channels/rdpsnd/client/rdpsnd_main.c
> +@@ -132,6 +132,8 @@ struct rdpsnd_plugin
> + 	BOOL applyVolume;
> + };
> + 
> ++static DWORD WINAPI play_thread(LPVOID arg);
> ++
> + static const char* rdpsnd_is_dyn_str(BOOL dynamic)
> + {
> + 	if (dynamic)
> +@@ -1264,7 +1266,6 @@ static void cleanup_internals(rdpsndPlug
> + 	if (!rdpsnd)
> + 		return;
> + 
> +-	rdpsnd_terminate_thread(rdpsnd);
> + 	if (rdpsnd->pool)
> + 		StreamPool_Return(rdpsnd->pool, rdpsnd->data_in);
> + 
> +@@ -1328,6 +1329,7 @@ static void free_internals(rdpsndPlugin*
> + 	if (!rdpsnd)
> + 		return;
> + 
> ++	rdpsnd_terminate_thread(rdpsnd);
> + 	freerdp_dsp_context_free(rdpsnd->dsp_context);
> + 	StreamPool_Free(rdpsnd->pool);
> + 	rdpsnd->pool = NULL;
> +@@ -1349,6 +1351,21 @@ static BOOL allocate_internals(rdpsndPlu
> + 		if (!rdpsnd->dsp_context)
> + 			return FALSE;
> + 	}
> ++	if (!rdpsnd->queue)
> ++	{
> ++		wObject obj = { 0 };
> ++
> ++		obj.fnObjectFree = _queue_free;
> ++		rdpsnd->queue = MessageQueue_New(&obj);
> ++		if (!rdpsnd->queue)
> ++			return CHANNEL_RC_NO_MEMORY;
> ++	}
> ++	if (!rdpsnd->thread)
> ++	{
> ++		rdpsnd->thread = CreateThread(NULL, 0, play_thread, rdpsnd, 0, NULL);
> ++		if (!rdpsnd->thread)
> ++			return CHANNEL_RC_INITIALIZATION_ERROR;
> ++	}
> + 
> + 	return TRUE;
> + }
> +@@ -1388,23 +1405,12 @@ static DWORD WINAPI play_thread(LPVOID a
> + 
> + static UINT rdpsnd_virtual_channel_event_initialized(rdpsndPlugin* rdpsnd)
> + {
> +-	wObject obj = { 0 };
> +-
> + 	if (!rdpsnd)
> + 		return ERROR_INVALID_PARAMETER;
> + 
> +-	obj.fnObjectFree = _queue_free;
> +-	rdpsnd->queue = MessageQueue_New(&obj);
> +-	if (!rdpsnd->queue)
> +-		return CHANNEL_RC_NO_MEMORY;
> +-
> + 	if (!allocate_internals(rdpsnd))
> + 		return CHANNEL_RC_NO_MEMORY;
> + 
> +-	rdpsnd->thread = CreateThread(NULL, 0, play_thread, rdpsnd, 0, NULL);
> +-	if (!rdpsnd->thread)
> +-		return CHANNEL_RC_INITIALIZATION_ERROR;
> +-
> + 	return CHANNEL_RC_OK;
> + }
> + 
> +@@ -1412,8 +1418,6 @@ void rdpsnd_virtual_channel_event_termin
> + {
> + 	if (rdpsnd)
> + 	{
> +-		rdpsnd_terminate_thread(rdpsnd);
> +-
> + 		free_internals(rdpsnd);
> + 		audio_formats_free(rdpsnd->fixed_format, 1);
> + 		free(rdpsnd->subsystem);
> +@@ -1602,13 +1606,13 @@ static UINT rdpsnd_on_close(IWTSVirtualC
> + 
> + 	cleanup_internals(rdpsnd);
> + 
> ++	free_internals(rdpsnd);
> + 	if (rdpsnd->device)
> + 	{
> + 		IFCALL(rdpsnd->device->Free, rdpsnd->device);
> + 		rdpsnd->device = NULL;
> + 	}
> + 
> +-	free_internals(rdpsnd);
> + 	free(pChannelCallback);
> + 	return CHANNEL_RC_OK;
> + }
> diff --git a/package/freerdp/freerdp.mk b/package/freerdp/freerdp.mk
> index 4017caa277..fe085d748b 100644
> --- a/package/freerdp/freerdp.mk
> +++ b/package/freerdp/freerdp.mk
> @@ -21,6 +21,50 @@ FREERDP_IGNORE_CVES += CVE-2024-32662
>  # https://security-tracker.debian.org/tracker/CVE-2025-68118
>  FREERDP_IGNORE_CVES += CVE-2025-68118
>  
> +# 0009-fix-missing-check-in-rdp-write-logon-info-v1.patch
> +FREERDP_IGNORE_CVES += CVE-2024-32661
> +
> +# 0010-fix-decoder-length-checks.patch
> +FREERDP_IGNORE_CVES += CVE-2026-23530
> +
> +# 0011-fix-missing-length-checks.patch
> +# 0012-check-clear-decomress-glyphData.patch
> +FREERDP_IGNORE_CVES += CVE-2026-23531
> +
> +# 0013-properly-clamp-SurfaceToSurface.patch
> +FREERDP_IGNORE_CVES += CVE-2026-23532
> +
> +# 0014-fix-clear-resize-buffer-checks.patch
> +FREERDP_IGNORE_CVES += CVE-2026-23533
> +
> +# 0015-fix-off-by-one-length-check.patch
> +FREERDP_IGNORE_CVES += CVE-2026-23534
> +
> +# 0016-fix-missing-NULL-check.patch
> +FREERDP_IGNORE_CVES += CVE-2026-23948
> +
> +# 0017-do-not-free-MsConfig-on-failure.patch
> +FREERDP_IGNORE_CVES += CVE-2026-24675
> +
> +# 0018-reset-audin-format.patch
> +FREERDP_IGNORE_CVES += CVE-2026-24676
> +
> +# 0019-ensure-InterfaceNumber-is-within-range.patch
> +FREERDP_IGNORE_CVES += CVE-2026-24679
> +
> +# 0020-cancel-all-usb-transfers-on-channel-close.patch
> +FREERDP_IGNORE_CVES += CVE-2026-24681
> +
> +# 0021-fix-audin-server-recv-formats-cleanup.patch
> +FREERDP_IGNORE_CVES += CVE-2026-24682
> +
> +# 0022-lock-context-when-updating-listener.patch
> +FREERDP_IGNORE_CVES += CVE-2026-24683
> +
> +# 0023-terminate-thread-before-free.patch
> +# 0024-only-clean-up-thread-before-free.patch
> +FREERDP_IGNORE_CVES += CVE-2026-24684
> +
>  FREERDP_INSTALL_STAGING = YES
>  
>  FREERDP_CONF_OPTS = \
> -- 
> 2.53.0
> 
> _______________________________________________
> buildroot mailing list
> buildroot at buildroot.org
> https://lists.buildroot.org/mailman/listinfo/buildroot


More information about the buildroot mailing list