From afa6851dc80835d3101e40fcef51b6c5c0f43ea5 Mon Sep 17 00:00:00 2001 From: akallabeth 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 --- 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; }