From f745c9152d4967f0e8fc4c935e7538948997254d Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Fri, 7 Aug 2026 11:43:19 +0100 Subject: [PATCH] drdynvc: Change channel processing to use streams The channel processor in xrdp_channel.c for dynamic streams uses a data pointer and a length for passing PDUs or PDU fragments. We replace this with a standard stream pointer, so that the usual facilities can be used for checking length violcations. --- libxrdp/libxrdp.h | 6 ++-- libxrdp/libxrdpinc.h | 6 ++-- libxrdp/xrdp_channel.c | 5 ++-- xrdp/xrdp_egfx.c | 19 +++++------- xrdp/xrdp_mm.c | 68 +++++++++++++++++++----------------------- 5 files changed, 46 insertions(+), 58 deletions(-) diff --git a/libxrdp/libxrdp.h b/libxrdp/libxrdp.h index 5aa6075c..80593c4c 100644 --- a/libxrdp/libxrdp.h +++ b/libxrdp/libxrdp.h @@ -146,9 +146,9 @@ struct xrdp_drdynvc int (*open_response)(struct xrdp_process *id, int chan_id, int creation_status); int (*close_response)(struct xrdp_process *id, int chan_id); - int (*data_first)(struct xrdp_process *id, int chan_id, char *data, - int bytes, int total_bytes); - int (*data)(struct xrdp_process *id, int chan_id, char *data, int bytes); + int (*data_first)(struct xrdp_process *id, int chan_id, struct stream *s, + int total_bytes); + int (*data)(struct xrdp_process *id, int chan_id, struct stream *s); }; struct vc_dechunker; // Forward declaration diff --git a/libxrdp/libxrdpinc.h b/libxrdp/libxrdpinc.h index d84b544a..0b48d356 100644 --- a/libxrdp/libxrdpinc.h +++ b/libxrdp/libxrdpinc.h @@ -91,9 +91,9 @@ struct xrdp_drdynvc_procs int (*open_response)(struct xrdp_process *id, int chan_id, int creation_status); int (*close_response)(struct xrdp_process *id, int chan_id); - int (*data_first)(struct xrdp_process *id, int chan_id, - char *data, int bytes, int total_bytes); - int (*data)(struct xrdp_process *id, int chan_id, char *data, int bytes); + int (*data_first)(struct xrdp_process *id, int chan_id, struct stream *s, + int total_bytes); + int (*data)(struct xrdp_process *id, int chan_id, struct stream *s); }; /* Defined in xrdp_client_info.h */ diff --git a/libxrdp/xrdp_channel.c b/libxrdp/xrdp_channel.c index 1925b0d1..46202b86 100644 --- a/libxrdp/xrdp_channel.c +++ b/libxrdp/xrdp_channel.c @@ -488,8 +488,7 @@ drdynvc_process_data_first(struct xrdp_channel *self, drdynvc = self->drdynvcs + chan_id; if (drdynvc->data_first != NULL) { - return drdynvc->data_first(session->id, chan_id, s->p, - bytes, total_bytes); + return drdynvc->data_first(session->id, chan_id, s, total_bytes); } LOG_DEVEL(LOG_LEVEL_WARNING, "Dynamic Virtual Channel %s (%d): " "callback 'data_first' is NULL", @@ -530,7 +529,7 @@ drdynvc_process_data(struct xrdp_channel *self, drdynvc = self->drdynvcs + chan_id; if (drdynvc->data != NULL) { - return drdynvc->data(session->id, chan_id, s->p, bytes); + return drdynvc->data(session->id, chan_id, s); } LOG_DEVEL(LOG_LEVEL_WARNING, "Dynamic Virtual Channel %s (%d): " "callback 'data' is NULL", diff --git a/xrdp/xrdp_egfx.c b/xrdp/xrdp_egfx.c index 255f7646..6cc381ae 100644 --- a/xrdp/xrdp_egfx.c +++ b/xrdp/xrdp_egfx.c @@ -946,9 +946,10 @@ xrdp_egfx_close_response(struct xrdp_process *id, int chan_id) /* from client */ static int xrdp_egfx_data_first(struct xrdp_process *id, int chan_id, - char *data, int bytes, int total_bytes) + struct stream *s, int total_bytes) { struct xrdp_egfx *egfx; + int bytes = s_rem(s); LOG(LOG_LEVEL_TRACE, "xrdp_egfx_data_first: bytes %d" " total_bytes %d", bytes, total_bytes); @@ -962,17 +963,16 @@ xrdp_egfx_data_first(struct xrdp_process *id, int chan_id, make_stream(egfx->s); // Caller has checked total_bytes is >= 0 and bytes is < total_bytes init_stream(egfx->s, total_bytes); - out_uint8a(egfx->s, data, bytes); + out_uint8a(egfx->s, s->p, bytes); return 0; } /******************************************************************************/ /* from client */ static int -xrdp_egfx_data(struct xrdp_process *id, int chan_id, char *data, int bytes) +xrdp_egfx_data(struct xrdp_process *id, int chan_id, struct stream *s) { int error; - struct stream ls; struct xrdp_wm *wm; struct xrdp_mm *mm; struct xrdp_egfx *egfx; @@ -1004,20 +1004,17 @@ xrdp_egfx_data(struct xrdp_process *id, int chan_id, char *data, int bytes) if (egfx->s == NULL) { - g_memset(&ls, 0, sizeof(ls)); - ls.data = data; - ls.size = bytes; - ls.p = data; - ls.end = data + bytes; - return xrdp_egfx_process(egfx, &ls); + return xrdp_egfx_process(egfx, s); } + int bytes = s_rem(s); + if (!s_check_rem_out(egfx->s, bytes)) { LOG(LOG_LEVEL_ERROR, "DYNVC_DATA PDU data overflow on channel %d", chan_id); return 1; } - out_uint8a(egfx->s, data, bytes); + out_uint8a(egfx->s, s->p, bytes); if (!s_check_rem_out(egfx->s, 1)) { s_mark_end(egfx->s); diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index 0c3b7306..def835df 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -1047,7 +1047,7 @@ dynamic_monitor_close_response(struct xrdp_process *id, int chan_id) /******************************************************************************/ static int dynamic_monitor_data_first(struct xrdp_process *id, int chan_id, - char *data, int bytes, int total_bytes) + struct stream *s, int total_bytes) { LOG_DEVEL(LOG_LEVEL_TRACE, "dynamic_monitor_data_first:"); return 0; @@ -1529,12 +1529,9 @@ add_resize_request_to_queue(struct xrdp_mm *self, /******************************************************************************/ static int -dynamic_monitor_data(struct xrdp_process *id, int chan_id, - char *data, int bytes) +dynamic_monitor_data(struct xrdp_process *id, int chan_id, struct stream *s) { int error = 0; - struct stream ls; - struct stream *s; int msg_type; int msg_length; struct xrdp_wm *wm; @@ -1552,12 +1549,6 @@ dynamic_monitor_data(struct xrdp_process *id, int chan_id, return error; } - g_memset(&ls, 0, sizeof(ls)); - ls.data = data; - ls.p = ls.data; - ls.size = bytes; - ls.end = ls.data + bytes; - s = &ls; in_uint32_le(s, msg_type); in_uint32_le(s, msg_length); LOG_DEVEL(LOG_LEVEL_DEBUG, @@ -2156,65 +2147,66 @@ xrdp_mm_drdynvc_close_response(struct xrdp_process *id, int chan_id) /*****************************************************************************/ /* part data from client going to channel server */ static int -xrdp_mm_drdynvc_data_first(struct xrdp_process *id, int chan_id, char *data, - int bytes, int total_bytes) +xrdp_mm_drdynvc_data_first(struct xrdp_process *id, int chan_id, + struct stream *s, int total_bytes) { struct trans *trans; - struct stream *s; + struct stream *out_s; struct xrdp_wm *wm; int chansrv_chan_id; + int bytes = s_rem(s); // Size of PDU sent to chansrv int pdu_size = 8 + 8 + 4 + 4 + 4 + bytes; wm = id->wm; trans = wm->mm->chan_trans; - s = trans_get_out_s(trans, pdu_size); - if (s == NULL) + out_s = trans_get_out_s(trans, pdu_size); + if (out_s == NULL) { return 1; } - out_uint32_le(s, 0); /* version */ - out_uint32_le(s, pdu_size); - out_uint32_le(s, 17); /* msg id */ - out_uint32_le(s, pdu_size - 8); + out_uint32_le(out_s, 0); /* version */ + out_uint32_le(out_s, pdu_size); + out_uint32_le(out_s, 17); /* msg id */ + out_uint32_le(out_s, pdu_size - 8); chansrv_chan_id = wm->mm->xr2cr_cid_map[chan_id]; - out_uint32_le(s, chansrv_chan_id); - out_uint32_le(s, bytes); - out_uint32_le(s, total_bytes); - out_uint8a(s, data, bytes); - s_mark_end(s); + out_uint32_le(out_s, chansrv_chan_id); + out_uint32_le(out_s, bytes); + out_uint32_le(out_s, total_bytes); + out_uint8p(out_s, s->p, bytes); + s_mark_end(out_s); return trans_write_copy(trans); } /*****************************************************************************/ /* data from client going to channel server */ static int -xrdp_mm_drdynvc_data(struct xrdp_process *id, int chan_id, - char *data, int bytes) +xrdp_mm_drdynvc_data(struct xrdp_process *id, int chan_id, struct stream *s) { struct trans *trans; - struct stream *s; + struct stream *out_s; struct xrdp_wm *wm; int chansrv_chan_id; + int bytes = s_rem(s); // Size of PDU sent to chansrv int pdu_size = 8 + 8 + 4 + 4 + bytes; wm = id->wm; trans = wm->mm->chan_trans; - s = trans_get_out_s(trans, pdu_size); - if (s == NULL) + out_s = trans_get_out_s(trans, pdu_size); + if (out_s == NULL) { return 1; } - out_uint32_le(s, 0); /* version */ - out_uint32_le(s, pdu_size); - out_uint32_le(s, 19); /* msg id */ - out_uint32_le(s, pdu_size - 8); + out_uint32_le(out_s, 0); /* version */ + out_uint32_le(out_s, pdu_size); + out_uint32_le(out_s, 19); /* msg id */ + out_uint32_le(out_s, pdu_size - 8); chansrv_chan_id = wm->mm->xr2cr_cid_map[chan_id]; - out_uint32_le(s, chansrv_chan_id); - out_uint32_le(s, bytes); - out_uint8a(s, data, bytes); - s_mark_end(s); + out_uint32_le(out_s, chansrv_chan_id); + out_uint32_le(out_s, bytes); + out_uint8p(out_s, s->p, bytes); + s_mark_end(out_s); return trans_write_copy(trans); }