From 4aa8bdf1eac3aab7e166393913019edf9616008c Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Thu, 11 Jun 2026 16:32:06 +0100 Subject: [PATCH] CVE-2026-55238: Possible OOB reads in capability processing Add missing per-capability length checks in the RDP Confirm Active PDU parser, and abort the parser if a buffer length violation is discovered. --- libxrdp/xrdp_caps.c | 134 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 109 insertions(+), 25 deletions(-) diff --git a/libxrdp/xrdp_caps.c b/libxrdp/xrdp_caps.c index acff9199..416bc940 100644 --- a/libxrdp/xrdp_caps.c +++ b/libxrdp/xrdp_caps.c @@ -415,6 +415,11 @@ xrdp_caps_process_input(struct xrdp_rdp *self, struct stream *s, int inputFlags; int client_does_fastpath_input; + if (len < 2) + { + LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_input: missing data"); + return 1; + } in_uint16_le(s, inputFlags); client_does_fastpath_input = (inputFlags & INPUT_FLAG_FASTPATH_INPUT) || (inputFlags & INPUT_FLAG_FASTPATH_INPUT2); @@ -689,6 +694,11 @@ xrdp_caps_process_multifragmentupdate(struct xrdp_rdp *self, struct stream *s, { int MaxRequestSize; + if (len < 4) + { + LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_multifragmentupdate: missing data"); + return 1; + } in_uint32_le(s, MaxRequestSize); if (self->client_info.use_fast_path & 1) { @@ -704,6 +714,11 @@ xrdp_caps_process_largepointer(struct xrdp_rdp *self, struct stream *s, { int largePointerSupportFlags; + if (len < 2) + { + LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_largepointer: missing data"); + return 1; + } in_uint16_le(s, largePointerSupportFlags); self->client_info.large_pointer_support_flags = largePointerSupportFlags; return 0; @@ -713,16 +728,25 @@ xrdp_caps_process_largepointer(struct xrdp_rdp *self, struct stream *s, static int xrdp_caps_process_frame_ack(struct xrdp_rdp *self, struct stream *s, int len) { + int max_count; LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_process_frame_ack:"); - self->client_info.use_frame_acks = 1; - in_uint32_le(s, self->client_info.max_unacknowledged_frame_count); - if (self->client_info.max_unacknowledged_frame_count < 0) + if (len < 4) { - LOG(LOG_LEVEL_WARNING, " invalid max_unacknowledged_frame_count value (%d), setting to 0", - self->client_info.max_unacknowledged_frame_count); - self->client_info.max_unacknowledged_frame_count = 0; + LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_frame_ack: missing data"); + return 1; } - LOG_DEVEL(LOG_LEVEL_TRACE, " max_unacknowledged_frame_count %d", self->client_info.max_unacknowledged_frame_count); + self->client_info.use_frame_acks = 1; + in_uint32_le(s, max_count); + if (max_count < 0) + { + LOG(LOG_LEVEL_WARNING, + " invalid max_unacknowledged_frame_count value (%d), setting to 0", + max_count); + max_count = 0; + } + LOG_DEVEL(LOG_LEVEL_TRACE, + " max_unacknowledged_frame_count %d", max_count); + self->client_info.max_unacknowledged_frame_count = max_count; return 0; } @@ -730,6 +754,12 @@ xrdp_caps_process_frame_ack(struct xrdp_rdp *self, struct stream *s, int len) static int xrdp_caps_process_surface_cmds(struct xrdp_rdp *self, struct stream *s, int len) { + // Check the data is there, whether or not we are logging it + if (len < 8) + { + LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_surface_cmds: missing data"); + return 1; + } #ifdef USE_DEVEL_LOGGING int cmdFlags; @@ -820,22 +850,34 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) case CAPSTYPE_GENERAL: LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " "capabilitySetType = CAPSTYPE_GENERAL"); - xrdp_caps_process_general(self, s, len); + if (xrdp_caps_process_general(self, s, len) != 0) + { + return 1; + } break; case CAPSTYPE_BITMAP: LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " "capabilitySetType = CAPSTYPE_BITMAP"); - xrdp_caps_process_bitmap(self, s, len); + if (xrdp_caps_process_bitmap(self, s, len) != 0) + { + return 1; + } break; case CAPSTYPE_ORDER: LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " "capabilitySetType = CAPSTYPE_ORDER"); - xrdp_caps_process_order(self, s, len); + if (xrdp_caps_process_order(self, s, len) != 0) + { + return 1; + } break; case CAPSTYPE_BITMAPCACHE: LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " "capabilitySetType = CAPSTYPE_BITMAPCACHE"); - xrdp_caps_process_bmpcache(self, s, len); + if (xrdp_caps_process_bmpcache(self, s, len) != 0) + { + return 1; + } break; case CAPSTYPE_CONTROL: LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " @@ -844,7 +886,10 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) case 6: LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " "capabilitySetType = 6"); - xrdp_caps_process_cache_v3_codec_id(self, s, len); + if (xrdp_caps_process_cache_v3_codec_id(self, s, len) != 0) + { + return 1; + } break; case CAPSTYPE_ACTIVATION: LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " @@ -853,7 +898,10 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) case CAPSTYPE_POINTER: LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " "capabilitySetType = CAPSTYPE_POINTER"); - xrdp_caps_process_pointer(self, s, len); + if (xrdp_caps_process_pointer(self, s, len) != 0) + { + return 1; + } break; case CAPSTYPE_SHARE: LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " @@ -870,7 +918,10 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) case CAPSTYPE_INPUT: LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " "capabilitySetType = CAPSTYPE_INPUT"); - xrdp_caps_process_input(self, s, len); + if (xrdp_caps_process_input(self, s, len) != 0) + { + return 1; + } break; case CAPSTYPE_FONT: LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " @@ -879,22 +930,34 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) case CAPSTYPE_BRUSH: LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " "capabilitySetType = CAPSTYPE_BRUSH"); - xrdp_caps_process_brushcache(self, s, len); + if (xrdp_caps_process_brushcache(self, s, len) != 0) + { + return 1; + } break; case CAPSTYPE_GLYPHCACHE: LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " "capabilitySetType = CAPSTYPE_GLYPHCACHE"); - xrdp_caps_process_glyphcache(self, s, len); + if (xrdp_caps_process_glyphcache(self, s, len) != 0) + { + return 1; + } break; case CAPSTYPE_OFFSCREENCACHE: LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " "capabilitySetType = CAPSTYPE_OFFSCREENCACHE"); - xrdp_caps_process_offscreen_bmpcache(self, s, len); + if (xrdp_caps_process_offscreen_bmpcache(self, s, len) != 0) + { + return 1; + } break; case CAPSTYPE_BITMAPCACHE_REV2: LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " "capabilitySetType = CAPSTYPE_BITMAPCACHE_REV2"); - xrdp_caps_process_bmpcache2(self, s, len); + if (xrdp_caps_process_bmpcache2(self, s, len) != 0) + { + return 1; + } break; case CAPSTYPE_VIRTUALCHANNEL: LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " @@ -911,37 +974,58 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) case CAPSTYPE_RAIL: LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " "capabilitySetType = CAPSTYPE_RAIL"); - xrdp_caps_process_rail(self, s, len); + if (xrdp_caps_process_rail(self, s, len) != 0) + { + return 1; + } break; case CAPSTYPE_WINDOW: LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " "capabilitySetType = CAPSTYPE_WINDOW"); - xrdp_caps_process_window(self, s, len); + if (xrdp_caps_process_window(self, s, len) != 0) + { + return 1; + } break; case CAPSSETTYPE_MULTIFRAGMENTUPDATE: LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " "capabilitySetType = CAPSSETTYPE_MULTIFRAGMENTUPDATE"); - xrdp_caps_process_multifragmentupdate(self, s, len); + if (xrdp_caps_process_multifragmentupdate(self, s, len) != 0) + { + return 1; + } break; case CAPSETTYPE_LARGE_POINTER: LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " "capabilitySetType = CAPSETTYPE_LARGE_POINTER"); - xrdp_caps_process_largepointer(self, s, len); + if (xrdp_caps_process_largepointer(self, s, len) != 0) + { + return 1; + } break; case CAPSETTYPE_SURFACE_COMMANDS: LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " "capabilitySetType = CAPSETTYPE_SURFACE_COMMANDS"); - xrdp_caps_process_surface_cmds(self, s, len); + if (xrdp_caps_process_surface_cmds(self, s, len) != 0) + { + return 1; + } break; case CAPSSETTYPE_BITMAP_CODECS: LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " "capabilitySetType = CAPSSETTYPE_BITMAP_CODECS"); - xrdp_caps_process_codecs(self, s, len); + if (xrdp_caps_process_codecs(self, s, len) != 0) + { + return 1; + } break; case CAPSTYPE_FRAME_ACKNOWLEDGE: LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " "capabilitySetType = CAPSTYPE_FRAME_ACKNOWLEDGE"); - xrdp_caps_process_frame_ack(self, s, len); + if (xrdp_caps_process_frame_ack(self, s, len) != 0) + { + return 1; + } break; default: LOG(LOG_LEVEL_WARNING, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "