Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions debian/changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
freerdp2 (2.11.2+dfsg1-1deepin1) unstable; urgency=medium

* Security fixes:
* CVE-2026-24675: [channels,urbdrc] do not free MsConfig on failure
* CVE-2026-24681: [channels,urbdrc] cancel all usb transfers on channel close
* CVE-2026-25941: [channels,rdpgfx] check available stream length
* CVE-2026-26986: [client,x11] fix xf_rail_window_common cleanup
* CVE-2026-29776: [core,orders] improve input validation
* CVE-2026-33952: [core,gateway] Check rpcconn_common_hdr_t::auth_length is

-- deepin-ci-robot <packages@deepin.org> Thu, 28 May 2026 23:28:12 +0800

freerdp2 (2.11.2+dfsg1-1) unstable; urgency=medium

* New upstream release. (Closes: #1051638).
Expand Down
53 changes: 53 additions & 0 deletions debian/patches/CVE-2026-23948.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
From 4d44e3c097656a8b9ec696353647b0888ca45860 Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Mon, 19 Jan 2026 20:11:24 +0100
Subject: [PATCH] [core,info] fix missing NULL check

---
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
@@ -1447,7 +1447,7 @@ static BOOL rdp_write_logon_info_v1(wStream* s, logon_info* info)
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)
{
size_t domainLen = 0;
size_t usernameLen = 0;
@@ -1462,11 +1462,14 @@ static BOOL rdp_write_logon_info_v2(wStream* s, logon_info* info)
*/
Stream_Write_UINT32(s, logonInfoV2Size);
Stream_Write_UINT32(s, info->sessionId);
- domainLen = strnlen(info->domain, 256); /* lmcons.h UNLEN */
+ if (info->domain)
+ domainLen = strnlen(info->domain, 256); /* lmcons.h UNLEN */
if (domainLen >= UINT32_MAX / sizeof(WCHAR))
return FALSE;
Stream_Write_UINT32(s, (UINT32)(domainLen + 1) * sizeof(WCHAR));
- usernameLen = strnlen(info->username, 256); /* lmcons.h UNLEN */
+
+ if (info->username)
+ usernameLen = strnlen(info->username, 256); /* lmcons.h UNLEN */
if (usernameLen >= UINT32_MAX / sizeof(WCHAR))
return FALSE;
Stream_Write_UINT32(s, (UINT32)(usernameLen + 1) * sizeof(WCHAR));
@@ -1534,10 +1537,11 @@ static BOOL rdp_write_logon_info_ex(wStream* s, logon_info_ex* info)
BOOL rdp_send_save_session_info(rdpContext* context, UINT32 type, void* data)
{
UINT16 sec_flags = 0;
- wStream* s = NULL;
BOOL status = 0;
+
+ WINPR_ASSERT(context);
rdpRdp* rdp = context->rdp;
- s = rdp_data_pdu_init(rdp, &sec_flags);
+ wStream* s = rdp_data_pdu_init(rdp, &sec_flags);

if (!s)
return FALSE;
49 changes: 49 additions & 0 deletions debian/patches/CVE-2026-24491.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
From e02e052f6692550e539d10f99de9c35a23492db2 Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Mon, 26 Jan 2026 10:06:29 +0100
Subject: [PATCH] [channels,drdynvc] reset channel_callback before close

The channel_callback usually frees up the memory of the callback. To
ensure that there is no access to any of the data structures in it
invalidate the pointer used to access it before a free.
---
channels/drdynvc/client/drdynvc_main.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/channels/drdynvc/client/drdynvc_main.c b/channels/drdynvc/client/drdynvc_main.c
index 78dde80ee333..fe2821a6ab2e 100644
--- a/channels/drdynvc/client/drdynvc_main.c
+++ b/channels/drdynvc/client/drdynvc_main.c
@@ -510,6 +510,7 @@ static UINT dvcman_channel_close(DVCMAN_CHANNEL* channel, BOOL perRequest, BOOL

{
IWTSVirtualChannelCallback* cb = channel->channel_callback;
+ channel->channel_callback = NULL;
if (cb)
{
check_open_close_receive(channel);
@@ -517,8 +518,6 @@ static UINT dvcman_channel_close(DVCMAN_CHANNEL* channel, BOOL perRequest, BOOL
}
}

- channel->channel_callback = NULL;
-
if (channel->dvcman && channel->dvcman->drdynvc)
{
if (context)
@@ -796,14 +795,13 @@ static DVCMAN_CHANNEL* dvcman_create_channel(drdynvcPlugin* drdynvc,
*/
static UINT dvcman_open_channel(drdynvcPlugin* drdynvc, DVCMAN_CHANNEL* channel)
{
- IWTSVirtualChannelCallback* pCallback = NULL;
UINT error = CHANNEL_RC_OK;

WINPR_ASSERT(drdynvc);
WINPR_ASSERT(channel);
if (channel->state == DVC_CHANNEL_RUNNING)
{
- pCallback = channel->channel_callback;
+ IWTSVirtualChannelCallback* pCallback = channel->channel_callback;

if (pCallback->OnOpen)
{
24 changes: 24 additions & 0 deletions debian/patches/CVE-2026-24675.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
From d676518809c319eec15911c705c13536036af2ae Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@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.
---
channels/urbdrc/client/data_transfer.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)

--- freerdp2.orig/channels/urbdrc/client/data_transfer.c
+++ freerdp2/channels/urbdrc/client/data_transfer.c
@@ -570,10 +570,8 @@ static UINT urb_select_interface(IUDEVIC
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))
{
160 changes: 160 additions & 0 deletions debian/patches/CVE-2026-24677.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
From d2d4f449312ddafd4a4c6c8a4f856c7f0d44a3b5 Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Mon, 26 Jan 2026 10:38:03 +0100
Subject: [PATCH] [channels,rdpecam] ensure sws context size matches

---
channels/rdpecam/client/camera.h | 2 +
channels/rdpecam/client/camera_device_main.c | 7 ++-
channels/rdpecam/client/encoding.c | 48 ++++++++++++++++----
channels/remdesk/server/remdesk_main.c | 3 +-
4 files changed, 47 insertions(+), 13 deletions(-)

diff --git a/channels/rdpecam/client/camera.h b/channels/rdpecam/client/camera.h
index f0f4f9d9a0b1..05d9f98ba1fa 100644
--- a/channels/rdpecam/client/camera.h
+++ b/channels/rdpecam/client/camera.h
@@ -121,6 +121,8 @@ typedef struct
#endif

/* sws_scale */
+ uint32_t swsWidth;
+ uint32_t swsHeight;
struct SwsContext* sws;

} CameraDeviceStream;
diff --git a/channels/rdpecam/client/camera_device_main.c b/channels/rdpecam/client/camera_device_main.c
index db53246f01f2..b76a37ca80de 100644
--- a/channels/rdpecam/client/camera_device_main.c
+++ b/channels/rdpecam/client/camera_device_main.c
@@ -121,7 +121,7 @@ static BOOL mediaSupportDrops(CAM_MEDIA_FORMAT format)
}
}

-static UINT ecam_dev_send_pending(CameraDevice* dev, int streamIndex, CameraDeviceStream* stream)
+static UINT ecam_dev_send_pending(CameraDevice* dev, size_t streamIndex, CameraDeviceStream* stream)
{
WINPR_ASSERT(dev);
WINPR_ASSERT(stream);
@@ -160,8 +160,7 @@ static UINT ecam_dev_send_pending(CameraDevice* dev, int streamIndex, CameraDevi
stream->samplesRequested--;
stream->haveSample = FALSE;

- return ecam_dev_send_sample_response(dev, WINPR_ASSERTING_INT_CAST(size_t, streamIndex),
- encodedSample, encodedSize);
+ return ecam_dev_send_sample_response(dev, streamIndex, encodedSample, encodedSize);
}

static UINT ecam_dev_sample_captured_callback(CameraDevice* dev, int streamIndex,
@@ -229,7 +228,7 @@ static UINT ecam_dev_sample_captured_callback(CameraDevice* dev, int streamIndex
Stream_SealLength(stream->pendingSample);
stream->haveSample = TRUE;

- ret = ecam_dev_send_pending(dev, streamIndex, stream);
+ ret = ecam_dev_send_pending(dev, WINPR_ASSERTING_INT_CAST(size_t, streamIndex), stream);

out:
LeaveCriticalSection(&stream->lock);
diff --git a/channels/rdpecam/client/encoding.c b/channels/rdpecam/client/encoding.c
index c5535fd7fbec..3d333ce68952 100644
--- a/channels/rdpecam/client/encoding.c
+++ b/channels/rdpecam/client/encoding.c
@@ -220,6 +220,30 @@ static enum AVPixelFormat ecamToAVPixFormat(CAM_MEDIA_FORMAT ecamFormat)
}
}

+static void ecam_sws_free(CameraDeviceStream* stream)
+{
+ if (stream->sws)
+ {
+ sws_freeContext(stream->sws);
+ stream->sws = NULL;
+ }
+}
+
+static BOOL ecam_sws_valid(const CameraDeviceStream* stream)
+{
+ if (!stream->sws)
+ return FALSE;
+ if (stream->swsWidth != stream->currMediaType.Width)
+ return FALSE;
+ if (stream->swsHeight != stream->currMediaType.Height)
+ return FALSE;
+ if (stream->currMediaType.Width > INT32_MAX)
+ return FALSE;
+ if (stream->currMediaType.Height > INT32_MAX)
+ return FALSE;
+ return TRUE;
+}
+
/**
* Function description
* initialize libswscale
@@ -230,9 +254,16 @@ static BOOL ecam_init_sws_context(CameraDeviceStream* stream, enum AVPixelFormat
{
WINPR_ASSERT(stream);

- if (stream->sws)
+ if (stream->currMediaType.Width > INT32_MAX)
+ return FALSE;
+ if (stream->currMediaType.Height > INT32_MAX)
+ return FALSE;
+
+ if (ecam_sws_valid(stream))
return TRUE;

+ ecam_sws_free(stream);
+
/* replacing deprecated JPEG formats, still produced by decoder */
switch (pixFormat)
{
@@ -260,8 +291,10 @@ static BOOL ecam_init_sws_context(CameraDeviceStream* stream, enum AVPixelFormat
break;
}

- const int width = (int)stream->currMediaType.Width;
- const int height = (int)stream->currMediaType.Height;
+ stream->swsWidth = stream->currMediaType.Width;
+ stream->swsHeight = stream->currMediaType.Height;
+ const int width = WINPR_ASSERTING_INT_CAST(int, stream->currMediaType.Width);
+ const int height = WINPR_ASSERTING_INT_CAST(int, stream->currMediaType.Height);

const enum AVPixelFormat outPixFormat =
h264_context_get_option(stream->h264, H264_CONTEXT_OPTION_HW_ACCEL) ? AV_PIX_FMT_NV12
@@ -295,6 +328,9 @@ static BOOL ecam_encoder_compress_h264(CameraDeviceStream* stream, const BYTE* s
CAM_MEDIA_FORMAT inputFormat = streamInputFormat(stream);
enum AVPixelFormat pixFormat = AV_PIX_FMT_NONE;

+ if (!ecam_sws_valid(stream))
+ return FALSE;
+
#if defined(WITH_INPUT_FORMAT_H264)
if (inputFormat == CAM_MEDIA_FORMAT_MJPG_H264)
{
@@ -385,11 +421,7 @@ static void ecam_encoder_context_free_h264(CameraDeviceStream* stream)
{
WINPR_ASSERT(stream);

- if (stream->sws)
- {
- sws_freeContext(stream->sws);
- stream->sws = NULL;
- }
+ ecam_sws_free(stream);

#if defined(WITH_INPUT_FORMAT_MJPG)
if (stream->avOutFrame)
diff --git a/channels/remdesk/server/remdesk_main.c b/channels/remdesk/server/remdesk_main.c
index 713b3370cee6..445027aacc22 100644
--- a/channels/remdesk/server/remdesk_main.c
+++ b/channels/remdesk/server/remdesk_main.c
@@ -526,7 +526,8 @@ static DWORD WINAPI remdesk_server_thread(LPVOID arg)
Stream_SealLength(s);
Stream_SetPosition(s, 0);

- if ((error = remdesk_server_receive_pdu(context, s)))
+ error = remdesk_server_receive_pdu(context, s);
+ if (error)
{
WLog_ERR(TAG, "remdesk_server_receive_pdu failed with error %" PRIu32 "!",
error);
24 changes: 24 additions & 0 deletions debian/patches/CVE-2026-24678.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
From f3ab1a16139036179d9852745fdade18fec11600 Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Mon, 26 Jan 2026 10:54:33 +0100
Subject: [PATCH] [channels,rdpecam] ensure all streams are stopped

When closing the channel ensure there are no more streams running.
---
channels/rdpecam/client/camera_device_main.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/channels/rdpecam/client/camera_device_main.c b/channels/rdpecam/client/camera_device_main.c
index b76a37ca80de..9ba3c65c5d5c 100644
--- a/channels/rdpecam/client/camera_device_main.c
+++ b/channels/rdpecam/client/camera_device_main.c
@@ -789,6 +789,9 @@ static UINT ecam_dev_on_close(IWTSVirtualChannelCallback* pChannelCallback)

WLog_DBG(TAG, "entered");

+ for (size_t i = 0; i < ECAM_DEVICE_MAX_STREAMS; i++)
+ ecam_dev_stop_stream(dev, i);
+
/* make sure this channel is not used for sample responses */
for (size_t i = 0; i < ECAM_DEVICE_MAX_STREAMS; i++)
if (dev->streams[i].hSampleReqChannel == hchannel)
39 changes: 39 additions & 0 deletions debian/patches/CVE-2026-24679.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
From 2d563a50be17c1b407ca448b1321378c0726dd31 Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Mon, 26 Jan 2026 10:59:39 +0100
Subject: [PATCH] [channels,urbdrc] ensure InterfaceNumber is within range

---
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
@@ -539,19 +539,19 @@ static int libusb_udev_select_interface(IUDEVICE* idev, BYTE InterfaceNumber, BY
int error = 0;
int diff = 0;
UDEVICE* pdev = (UDEVICE*)idev;
- URBDRC_PLUGIN* urbdrc = NULL;
- MSUSB_CONFIG_DESCRIPTOR* MsConfig = NULL;
- MSUSB_INTERFACE_DESCRIPTOR** MsInterfaces = NULL;

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,
21 changes: 21 additions & 0 deletions debian/patches/CVE-2026-24680.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
From c42ecbd183b001e76bfc3614cddfad0034acc758 Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Mon, 26 Jan 2026 11:01:17 +0100
Subject: [PATCH] [client,sdl] reset pointer after memory release

---
client/SDL/SDL3/sdl_pointer.cpp | 1 +
1 file changed, 1 insertion(+)

diff --git a/client/SDL/SDL3/sdl_pointer.cpp b/client/SDL/SDL3/sdl_pointer.cpp
index a5e1147e3954..472e460667aa 100644
--- a/client/SDL/SDL3/sdl_pointer.cpp
+++ b/client/SDL/SDL3/sdl_pointer.cpp
@@ -61,6 +61,7 @@ static BOOL sdl_Pointer_New(rdpContext* context, rdpPointer* pointer)
&context->gdi->palette))
{
winpr_aligned_free(ptr->data);
+ ptr->data = nullptr;
return FALSE;
}

Loading
Loading