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.
This commit is contained in:
matt335672
2026-08-07 11:43:19 +01:00
parent e4b0621229
commit f745c9152d
5 changed files with 46 additions and 58 deletions
+3 -3
View File
@@ -146,9 +146,9 @@ struct xrdp_drdynvc
int (*open_response)(struct xrdp_process *id, int chan_id, int (*open_response)(struct xrdp_process *id, int chan_id,
int creation_status); int creation_status);
int (*close_response)(struct xrdp_process *id, int chan_id); int (*close_response)(struct xrdp_process *id, int chan_id);
int (*data_first)(struct xrdp_process *id, int chan_id, char *data, int (*data_first)(struct xrdp_process *id, int chan_id, struct stream *s,
int bytes, int total_bytes); int total_bytes);
int (*data)(struct xrdp_process *id, int chan_id, char *data, int bytes); int (*data)(struct xrdp_process *id, int chan_id, struct stream *s);
}; };
struct vc_dechunker; // Forward declaration struct vc_dechunker; // Forward declaration
+3 -3
View File
@@ -91,9 +91,9 @@ struct xrdp_drdynvc_procs
int (*open_response)(struct xrdp_process *id, int chan_id, int (*open_response)(struct xrdp_process *id, int chan_id,
int creation_status); int creation_status);
int (*close_response)(struct xrdp_process *id, int chan_id); int (*close_response)(struct xrdp_process *id, int chan_id);
int (*data_first)(struct xrdp_process *id, int chan_id, int (*data_first)(struct xrdp_process *id, int chan_id, struct stream *s,
char *data, int bytes, int total_bytes); int total_bytes);
int (*data)(struct xrdp_process *id, int chan_id, char *data, int bytes); int (*data)(struct xrdp_process *id, int chan_id, struct stream *s);
}; };
/* Defined in xrdp_client_info.h */ /* Defined in xrdp_client_info.h */
+2 -3
View File
@@ -488,8 +488,7 @@ drdynvc_process_data_first(struct xrdp_channel *self,
drdynvc = self->drdynvcs + chan_id; drdynvc = self->drdynvcs + chan_id;
if (drdynvc->data_first != NULL) if (drdynvc->data_first != NULL)
{ {
return drdynvc->data_first(session->id, chan_id, s->p, return drdynvc->data_first(session->id, chan_id, s, total_bytes);
bytes, total_bytes);
} }
LOG_DEVEL(LOG_LEVEL_WARNING, "Dynamic Virtual Channel %s (%d): " LOG_DEVEL(LOG_LEVEL_WARNING, "Dynamic Virtual Channel %s (%d): "
"callback 'data_first' is NULL", "callback 'data_first' is NULL",
@@ -530,7 +529,7 @@ drdynvc_process_data(struct xrdp_channel *self,
drdynvc = self->drdynvcs + chan_id; drdynvc = self->drdynvcs + chan_id;
if (drdynvc->data != NULL) 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): " LOG_DEVEL(LOG_LEVEL_WARNING, "Dynamic Virtual Channel %s (%d): "
"callback 'data' is NULL", "callback 'data' is NULL",
+8 -11
View File
@@ -946,9 +946,10 @@ xrdp_egfx_close_response(struct xrdp_process *id, int chan_id)
/* from client */ /* from client */
static int static int
xrdp_egfx_data_first(struct xrdp_process *id, int chan_id, 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; struct xrdp_egfx *egfx;
int bytes = s_rem(s);
LOG(LOG_LEVEL_TRACE, "xrdp_egfx_data_first: bytes %d" LOG(LOG_LEVEL_TRACE, "xrdp_egfx_data_first: bytes %d"
" total_bytes %d", bytes, total_bytes); " 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); make_stream(egfx->s);
// Caller has checked total_bytes is >= 0 and bytes is < total_bytes // Caller has checked total_bytes is >= 0 and bytes is < total_bytes
init_stream(egfx->s, total_bytes); init_stream(egfx->s, total_bytes);
out_uint8a(egfx->s, data, bytes); out_uint8a(egfx->s, s->p, bytes);
return 0; return 0;
} }
/******************************************************************************/ /******************************************************************************/
/* from client */ /* from client */
static int 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; int error;
struct stream ls;
struct xrdp_wm *wm; struct xrdp_wm *wm;
struct xrdp_mm *mm; struct xrdp_mm *mm;
struct xrdp_egfx *egfx; 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) if (egfx->s == NULL)
{ {
g_memset(&ls, 0, sizeof(ls)); return xrdp_egfx_process(egfx, s);
ls.data = data;
ls.size = bytes;
ls.p = data;
ls.end = data + bytes;
return xrdp_egfx_process(egfx, &ls);
} }
int bytes = s_rem(s);
if (!s_check_rem_out(egfx->s, bytes)) if (!s_check_rem_out(egfx->s, bytes))
{ {
LOG(LOG_LEVEL_ERROR, "DYNVC_DATA PDU data overflow on channel %d", LOG(LOG_LEVEL_ERROR, "DYNVC_DATA PDU data overflow on channel %d",
chan_id); chan_id);
return 1; return 1;
} }
out_uint8a(egfx->s, data, bytes); out_uint8a(egfx->s, s->p, bytes);
if (!s_check_rem_out(egfx->s, 1)) if (!s_check_rem_out(egfx->s, 1))
{ {
s_mark_end(egfx->s); s_mark_end(egfx->s);
+30 -38
View File
@@ -1047,7 +1047,7 @@ dynamic_monitor_close_response(struct xrdp_process *id, int chan_id)
/******************************************************************************/ /******************************************************************************/
static int static int
dynamic_monitor_data_first(struct xrdp_process *id, int chan_id, 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:"); LOG_DEVEL(LOG_LEVEL_TRACE, "dynamic_monitor_data_first:");
return 0; return 0;
@@ -1529,12 +1529,9 @@ add_resize_request_to_queue(struct xrdp_mm *self,
/******************************************************************************/ /******************************************************************************/
static int static int
dynamic_monitor_data(struct xrdp_process *id, int chan_id, dynamic_monitor_data(struct xrdp_process *id, int chan_id, struct stream *s)
char *data, int bytes)
{ {
int error = 0; int error = 0;
struct stream ls;
struct stream *s;
int msg_type; int msg_type;
int msg_length; int msg_length;
struct xrdp_wm *wm; struct xrdp_wm *wm;
@@ -1552,12 +1549,6 @@ dynamic_monitor_data(struct xrdp_process *id, int chan_id,
return error; 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_type);
in_uint32_le(s, msg_length); in_uint32_le(s, msg_length);
LOG_DEVEL(LOG_LEVEL_DEBUG, 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 */ /* part data from client going to channel server */
static int static int
xrdp_mm_drdynvc_data_first(struct xrdp_process *id, int chan_id, char *data, xrdp_mm_drdynvc_data_first(struct xrdp_process *id, int chan_id,
int bytes, int total_bytes) struct stream *s, int total_bytes)
{ {
struct trans *trans; struct trans *trans;
struct stream *s; struct stream *out_s;
struct xrdp_wm *wm; struct xrdp_wm *wm;
int chansrv_chan_id; int chansrv_chan_id;
int bytes = s_rem(s);
// Size of PDU sent to chansrv // Size of PDU sent to chansrv
int pdu_size = 8 + 8 + 4 + 4 + 4 + bytes; int pdu_size = 8 + 8 + 4 + 4 + 4 + bytes;
wm = id->wm; wm = id->wm;
trans = wm->mm->chan_trans; trans = wm->mm->chan_trans;
s = trans_get_out_s(trans, pdu_size); out_s = trans_get_out_s(trans, pdu_size);
if (s == NULL) if (out_s == NULL)
{ {
return 1; return 1;
} }
out_uint32_le(s, 0); /* version */ out_uint32_le(out_s, 0); /* version */
out_uint32_le(s, pdu_size); out_uint32_le(out_s, pdu_size);
out_uint32_le(s, 17); /* msg id */ out_uint32_le(out_s, 17); /* msg id */
out_uint32_le(s, pdu_size - 8); out_uint32_le(out_s, pdu_size - 8);
chansrv_chan_id = wm->mm->xr2cr_cid_map[chan_id]; chansrv_chan_id = wm->mm->xr2cr_cid_map[chan_id];
out_uint32_le(s, chansrv_chan_id); out_uint32_le(out_s, chansrv_chan_id);
out_uint32_le(s, bytes); out_uint32_le(out_s, bytes);
out_uint32_le(s, total_bytes); out_uint32_le(out_s, total_bytes);
out_uint8a(s, data, bytes); out_uint8p(out_s, s->p, bytes);
s_mark_end(s); s_mark_end(out_s);
return trans_write_copy(trans); return trans_write_copy(trans);
} }
/*****************************************************************************/ /*****************************************************************************/
/* data from client going to channel server */ /* data from client going to channel server */
static int static int
xrdp_mm_drdynvc_data(struct xrdp_process *id, int chan_id, xrdp_mm_drdynvc_data(struct xrdp_process *id, int chan_id, struct stream *s)
char *data, int bytes)
{ {
struct trans *trans; struct trans *trans;
struct stream *s; struct stream *out_s;
struct xrdp_wm *wm; struct xrdp_wm *wm;
int chansrv_chan_id; int chansrv_chan_id;
int bytes = s_rem(s);
// Size of PDU sent to chansrv // Size of PDU sent to chansrv
int pdu_size = 8 + 8 + 4 + 4 + bytes; int pdu_size = 8 + 8 + 4 + 4 + bytes;
wm = id->wm; wm = id->wm;
trans = wm->mm->chan_trans; trans = wm->mm->chan_trans;
s = trans_get_out_s(trans, pdu_size); out_s = trans_get_out_s(trans, pdu_size);
if (s == NULL) if (out_s == NULL)
{ {
return 1; return 1;
} }
out_uint32_le(s, 0); /* version */ out_uint32_le(out_s, 0); /* version */
out_uint32_le(s, pdu_size); out_uint32_le(out_s, pdu_size);
out_uint32_le(s, 19); /* msg id */ out_uint32_le(out_s, 19); /* msg id */
out_uint32_le(s, pdu_size - 8); out_uint32_le(out_s, pdu_size - 8);
chansrv_chan_id = wm->mm->xr2cr_cid_map[chan_id]; chansrv_chan_id = wm->mm->xr2cr_cid_map[chan_id];
out_uint32_le(s, chansrv_chan_id); out_uint32_le(out_s, chansrv_chan_id);
out_uint32_le(s, bytes); out_uint32_le(out_s, bytes);
out_uint8a(s, data, bytes); out_uint8p(out_s, s->p, bytes);
s_mark_end(s); s_mark_end(out_s);
return trans_write_copy(trans); return trans_write_copy(trans);
} }