[Spice-devel] [PATCH spice-server v2 6/8] server: Limit the access to SpiceDataHeader of messages - only via red_channel.
Yonit Halperin
yhalperi at redhat.com
Tue Jan 10 03:25:20 PST 2012
---
server/inputs_channel.c | 10 +++++++---
server/main_channel.c | 8 ++++++--
server/red_channel.c | 34 +++++++++++++++++++++++++---------
server/red_channel.h | 24 ++++++++++--------------
server/red_tunnel_worker.c | 43 ++++++++++++++++++++++---------------------
server/red_worker.c | 9 ++++-----
server/smartcard.c | 18 +++++++++++-------
server/spicevmc.c | 24 ++++++++++++++----------
8 files changed, 99 insertions(+), 71 deletions(-)
diff --git a/server/inputs_channel.c b/server/inputs_channel.c
index c8b42e3..a987478 100644
--- a/server/inputs_channel.c
+++ b/server/inputs_channel.c
@@ -168,18 +168,22 @@ const VDAgentMouseState *inputs_get_mouse_state(void)
return &g_inputs_channel->mouse_state;
}
-static uint8_t *inputs_channel_alloc_msg_rcv_buf(RedChannelClient *rcc, SpiceDataHeader *msg_header)
+static uint8_t *inputs_channel_alloc_msg_rcv_buf(RedChannelClient *rcc,
+ uint16_t type,
+ uint32_t size)
{
InputsChannel *inputs_channel = SPICE_CONTAINEROF(rcc->channel, InputsChannel, base);
- if (msg_header->size > RECEIVE_BUF_SIZE) {
+ if (size > RECEIVE_BUF_SIZE) {
red_printf("error: too large incoming message");
return NULL;
}
return inputs_channel->recv_buf;
}
-static void inputs_channel_release_msg_rcv_buf(RedChannelClient *rcc, SpiceDataHeader *msg_header,
+static void inputs_channel_release_msg_rcv_buf(RedChannelClient *rcc,
+ uint16_t type,
+ uint32_t size,
uint8_t *msg)
{
}
diff --git a/server/main_channel.c b/server/main_channel.c
index 4b5b669..b55bf00 100644
--- a/server/main_channel.c
+++ b/server/main_channel.c
@@ -852,14 +852,18 @@ static int main_channel_handle_parsed(RedChannelClient *rcc, uint32_t size, uint
return TRUE;
}
-static uint8_t *main_channel_alloc_msg_rcv_buf(RedChannelClient *rcc, SpiceDataHeader *msg_header)
+static uint8_t *main_channel_alloc_msg_rcv_buf(RedChannelClient *rcc,
+ uint16_t type,
+ uint32_t size)
{
MainChannel *main_chan = SPICE_CONTAINEROF(rcc->channel, MainChannel, base);
return main_chan->recv_buf;
}
-static void main_channel_release_msg_rcv_buf(RedChannelClient *rcc, SpiceDataHeader *msg_header,
+static void main_channel_release_msg_rcv_buf(RedChannelClient *rcc,
+ uint16_t type,
+ uint32_t size,
uint8_t *msg)
{
}
diff --git a/server/red_channel.c b/server/red_channel.c
index 671bcf5..06b4ef0 100644
--- a/server/red_channel.c
+++ b/server/red_channel.c
@@ -103,7 +103,9 @@ static void red_peer_handle_incoming(RedsStream *stream, IncomingHandler *handle
if (handler->msg_pos < handler->header.size) {
if (!handler->msg) {
- handler->msg = handler->cb->alloc_msg_buf(handler->opaque, &handler->header);
+ handler->msg = handler->cb->alloc_msg_buf(handler->opaque,
+ handler->header.type,
+ handler->header.size);
if (handler->msg == NULL) {
red_printf("ERROR: channel refused to allocate buffer.");
handler->cb->on_error(handler->opaque);
@@ -115,7 +117,10 @@ static void red_peer_handle_incoming(RedsStream *stream, IncomingHandler *handle
handler->msg + handler->msg_pos,
handler->header.size - handler->msg_pos);
if (bytes_read == -1) {
- handler->cb->release_msg_buf(handler->opaque, &handler->header, handler->msg);
+ handler->cb->release_msg_buf(handler->opaque,
+ handler->header.type,
+ handler->header.size,
+ handler->msg);
handler->cb->on_error(handler->opaque);
return;
}
@@ -131,7 +136,9 @@ static void red_peer_handle_incoming(RedsStream *stream, IncomingHandler *handle
SPICE_VERSION_MINOR, &parsed_size, &parsed_free);
if (parsed == NULL) {
red_printf("failed to parse message type %d", handler->header.type);
- handler->cb->release_msg_buf(handler->opaque, &handler->header, handler->msg);
+ handler->cb->release_msg_buf(handler->opaque, handler->header.type,
+ handler->header.size,
+ handler->msg);
handler->cb->on_error(handler->opaque);
return;
}
@@ -139,11 +146,16 @@ static void red_peer_handle_incoming(RedsStream *stream, IncomingHandler *handle
handler->header.type, parsed);
parsed_free(parsed);
} else {
- ret_handle = handler->cb->handle_message(handler->opaque, &handler->header,
- handler->msg);
+ ret_handle = handler->cb->handle_message(handler->opaque,
+ handler->header.type,
+ handler->header.size,
+ handler->msg);
}
handler->msg_pos = 0;
- handler->cb->release_msg_buf(handler->opaque, &handler->header, handler->msg);
+ handler->cb->release_msg_buf(handler->opaque,
+ handler->header.type,
+ handler->header.size,
+ handler->msg);
handler->msg = NULL;
handler->header_pos = 0;
@@ -586,7 +598,10 @@ RedChannel *red_channel_create_dummy(int size, uint32_t type, uint32_t id)
return channel;
}
-static int do_nothing_handle_message(RedChannelClient *rcc, SpiceDataHeader *header, uint8_t *msg)
+static int do_nothing_handle_message(RedChannelClient *rcc,
+ uint16_t type,
+ uint32_t size,
+ uint8_t *msg)
{
return TRUE;
}
@@ -1204,10 +1219,11 @@ RedClient *red_channel_client_get_client(RedChannelClient *rcc)
return rcc->client;
}
-SpiceDataHeader *red_channel_client_get_header(RedChannelClient *rcc)
+void red_channel_client_set_header_sub_list(RedChannelClient *rcc, uint32_t sub_list)
{
- return rcc->send_data.header;
+ rcc->send_data.header->sub_list = sub_list;
}
+
/* end of accessors */
int red_channel_get_first_socket(RedChannel *channel)
diff --git a/server/red_channel.h b/server/red_channel.h
index cb80100..40792c1 100644
--- a/server/red_channel.h
+++ b/server/red_channel.h
@@ -38,11 +38,11 @@
At the final stage, this interface shouldn't be exposed. Only RedChannel will use it. */
typedef int (*handle_message_proc)(void *opaque,
- SpiceDataHeader *header, uint8_t *msg);
+ uint16_t type, uint32_t size, uint8_t *msg);
typedef int (*handle_parsed_proc)(void *opaque, uint32_t size, uint16_t type, void *message);
-typedef uint8_t *(*alloc_msg_recv_buf_proc)(void *opaque, SpiceDataHeader *msg_header);
+typedef uint8_t *(*alloc_msg_recv_buf_proc)(void *opaque, uint16_t type, uint32_t size);
typedef void (*release_msg_recv_buf_proc)(void *opaque,
- SpiceDataHeader *msg_header, uint8_t *msg);
+ uint16_t type, uint32_t size, uint8_t *msg);
typedef void (*on_incoming_error_proc)(void *opaque);
typedef struct IncomingHandlerInterface {
@@ -119,13 +119,13 @@ typedef struct PipeItem {
} PipeItem;
typedef uint8_t *(*channel_alloc_msg_recv_buf_proc)(RedChannelClient *channel,
- SpiceDataHeader *msg_header);
+ uint16_t type, uint32_t size);
typedef int (*channel_handle_parsed_proc)(RedChannelClient *rcc, uint32_t size, uint16_t type,
void *message);
typedef int (*channel_handle_message_proc)(RedChannelClient *rcc,
- SpiceDataHeader *header, uint8_t *msg);
+ uint16_t type, uint32_t size, uint8_t *msg);
typedef void (*channel_release_msg_recv_buf_proc)(RedChannelClient *channel,
- SpiceDataHeader *msg_header, uint8_t *msg);
+ uint16_t type, uint32_t size, uint8_t *msg);
typedef void (*channel_disconnect_proc)(RedChannelClient *rcc);
typedef int (*channel_configure_socket_proc)(RedChannelClient *rcc);
typedef void (*channel_send_pipe_item_proc)(RedChannelClient *rcc, PipeItem *item);
@@ -334,7 +334,7 @@ void red_channel_init_outgoing_messages_window(RedChannel *channel);
/* handles general channel msgs from the client */
int red_channel_client_handle_message(RedChannelClient *rcc, uint32_t size,
- uint16_t type, void *message);
+ uint16_t type, void *message);
/* when preparing send_data: should call init and then use marshaller */
void red_channel_client_init_send_data(RedChannelClient *rcc, uint16_t msg_type, PipeItem *item);
@@ -444,13 +444,9 @@ SpiceMarshaller *red_channel_client_get_marshaller(RedChannelClient *rcc);
RedsStream *red_channel_client_get_stream(RedChannelClient *rcc);
RedClient *red_channel_client_get_client(RedChannelClient *rcc);
-/* this is a convenience function for sending messages, sometimes (migration only?)
- * the serial from the header needs to be available for sending. Note that the header
- * pointer retrieved is not valid except between red_channel_reset_send_data and
- * red_channel_begin_send_message. red_channel_init_send_data changes the header (sets
- * the type in it) as a convenience function. It is preffered to do that through it and
- * not via the below accessor and direct header manipulation. */
-SpiceDataHeader *red_channel_client_get_header(RedChannelClient *rcc);
+/* Note that the header is valid only between red_channel_reset_send_data and
+ * red_channel_begin_send_message.*/
+void red_channel_client_set_header_sub_list(RedChannelClient *rcc, uint32_t sub_list);
/* return the sum of all the rcc pipe size */
uint32_t red_channel_max_pipe_size(RedChannel *channel);
diff --git a/server/red_tunnel_worker.c b/server/red_tunnel_worker.c
index 1e8267e..250e8b3 100644
--- a/server/red_tunnel_worker.c
+++ b/server/red_tunnel_worker.c
@@ -1644,27 +1644,27 @@ static int tunnel_channel_handle_socket_token(TunnelChannelClient *channel, RedS
}
static uint8_t *tunnel_channel_alloc_msg_rcv_buf(RedChannelClient *rcc,
- SpiceDataHeader *msg_header)
+ uint16_t type, uint32_t size)
{
TunnelChannelClient *tunnel_channel = (TunnelChannelClient *)rcc->channel;
- if (msg_header->type == SPICE_MSGC_TUNNEL_SOCKET_DATA) {
+ if (type == SPICE_MSGC_TUNNEL_SOCKET_DATA) {
return (__tunnel_worker_alloc_socket_rcv_buf(tunnel_channel->worker)->buf);
- } else if ((msg_header->type == SPICE_MSGC_MIGRATE_DATA) ||
- (msg_header->type == SPICE_MSGC_TUNNEL_SERVICE_ADD)) {
- return spice_malloc(msg_header->size);
+ } else if ((type == SPICE_MSGC_MIGRATE_DATA) ||
+ (type == SPICE_MSGC_TUNNEL_SERVICE_ADD)) {
+ return spice_malloc(size);
} else {
return (tunnel_channel->control_rcv_buf);
}
}
// called by the receive routine of the channel, before the buffer was assigned to a socket
-static void tunnel_channel_release_msg_rcv_buf(RedChannelClient *rcc, SpiceDataHeader *msg_header,
+static void tunnel_channel_release_msg_rcv_buf(RedChannelClient *rcc, uint16_t type, uint32_t size,
uint8_t *msg)
{
TunnelChannelClient *tunnel_channel = (TunnelChannelClient *)rcc->channel;
- if (msg_header->type == SPICE_MSGC_TUNNEL_SOCKET_DATA) {
+ if (type == SPICE_MSGC_TUNNEL_SOCKET_DATA) {
ASSERT(!(SPICE_CONTAINEROF(msg, RedSocketRawRcvBuf, buf)->base.usr_opaque));
__tunnel_worker_free_socket_rcv_buf(tunnel_channel->worker,
SPICE_CONTAINEROF(msg, RedSocketRawRcvBuf, buf));
@@ -2243,12 +2243,13 @@ error:
}
// msg was allocated by tunnel_channel_alloc_msg_rcv_buf
-static int tunnel_channel_handle_message(RedChannelClient *rcc, SpiceDataHeader *header, uint8_t *msg)
+static int tunnel_channel_handle_message(RedChannelClient *rcc, uint16_t type,
+ uint32_t size, uint8_t *msg)
{
TunnelChannelClient *tunnel_channel = (TunnelChannelClient *)rcc->channel;
RedSocket *sckt = NULL;
// retrieve the sckt
- switch (header->type) {
+ switch (type) {
case SPICE_MSGC_MIGRATE_FLUSH_MARK:
case SPICE_MSGC_MIGRATE_DATA:
case SPICE_MSGC_TUNNEL_SERVICE_ADD:
@@ -2269,12 +2270,12 @@ static int tunnel_channel_handle_message(RedChannelClient *rcc, SpiceDataHeader
}
break;
default:
- return red_channel_client_handle_message(rcc, header->size, header->type, msg);
+ return red_channel_client_handle_message(rcc, size, type, msg);
}
- switch (header->type) {
+ switch (type) {
case SPICE_MSGC_TUNNEL_SERVICE_ADD:
- if (header->size < sizeof(SpiceMsgcTunnelAddGenericService)) {
+ if (size < sizeof(SpiceMsgcTunnelAddGenericService)) {
red_printf("bad message size");
free(msg);
return FALSE;
@@ -2285,7 +2286,7 @@ static int tunnel_channel_handle_message(RedChannelClient *rcc, SpiceDataHeader
red_printf("REDC_TUNNEL_REMOVE_SERVICE not supported yet");
return FALSE;
case SPICE_MSGC_TUNNEL_SOCKET_OPEN_ACK:
- if (header->size != sizeof(SpiceMsgcTunnelSocketOpenAck)) {
+ if (size != sizeof(SpiceMsgcTunnelSocketOpenAck)) {
red_printf("bad message size");
return FALSE;
}
@@ -2294,7 +2295,7 @@ static int tunnel_channel_handle_message(RedChannelClient *rcc, SpiceDataHeader
((SpiceMsgcTunnelSocketOpenAck *)msg)->tokens);
case SPICE_MSGC_TUNNEL_SOCKET_OPEN_NACK:
- if (header->size != sizeof(SpiceMsgcTunnelSocketOpenNack)) {
+ if (size != sizeof(SpiceMsgcTunnelSocketOpenNack)) {
red_printf("bad message size");
return FALSE;
}
@@ -2302,35 +2303,35 @@ static int tunnel_channel_handle_message(RedChannelClient *rcc, SpiceDataHeader
return tunnel_channel_handle_socket_connect_nack(tunnel_channel, sckt);
case SPICE_MSGC_TUNNEL_SOCKET_DATA:
{
- if (header->size < sizeof(SpiceMsgcTunnelSocketData)) {
+ if (size < sizeof(SpiceMsgcTunnelSocketData)) {
red_printf("bad message size");
return FALSE;
}
return tunnel_channel_handle_socket_receive_data(tunnel_channel, sckt,
SPICE_CONTAINEROF(msg, RedSocketRawRcvBuf, buf),
- header->size - sizeof(SpiceMsgcTunnelSocketData));
+ size - sizeof(SpiceMsgcTunnelSocketData));
}
case SPICE_MSGC_TUNNEL_SOCKET_FIN:
- if (header->size != sizeof(SpiceMsgcTunnelSocketFin)) {
+ if (size != sizeof(SpiceMsgcTunnelSocketFin)) {
red_printf("bad message size");
return FALSE;
}
return tunnel_channel_handle_socket_fin(tunnel_channel, sckt);
case SPICE_MSGC_TUNNEL_SOCKET_CLOSED:
- if (header->size != sizeof(SpiceMsgcTunnelSocketClosed)) {
+ if (size != sizeof(SpiceMsgcTunnelSocketClosed)) {
red_printf("bad message size");
return FALSE;
}
return tunnel_channel_handle_socket_closed(tunnel_channel, sckt);
case SPICE_MSGC_TUNNEL_SOCKET_CLOSED_ACK:
- if (header->size != sizeof(SpiceMsgcTunnelSocketClosedAck)) {
+ if (size != sizeof(SpiceMsgcTunnelSocketClosedAck)) {
red_printf("bad message size");
return FALSE;
}
return tunnel_channel_handle_socket_closed_ack(tunnel_channel, sckt);
case SPICE_MSGC_TUNNEL_SOCKET_TOKEN:
- if (header->size != sizeof(SpiceMsgcTunnelSocketTokens)) {
+ if (size != sizeof(SpiceMsgcTunnelSocketTokens)) {
red_printf("bad message size");
return FALSE;
}
@@ -2338,7 +2339,7 @@ static int tunnel_channel_handle_message(RedChannelClient *rcc, SpiceDataHeader
return tunnel_channel_handle_socket_token(tunnel_channel, sckt,
(SpiceMsgcTunnelSocketTokens *)msg);
default:
- return red_channel_client_handle_message(rcc, header->size, header->type, msg);
+ return red_channel_client_handle_message(rcc, size, type, msg);
}
return TRUE;
}
diff --git a/server/red_worker.c b/server/red_worker.c
index d82c84e..f454302 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -1517,15 +1517,15 @@ static void release_upgrade_item(RedWorker* worker, UpgradeItem *item)
}
}
-static uint8_t *common_alloc_recv_buf(RedChannelClient *rcc, SpiceDataHeader *msg_header)
+static uint8_t *common_alloc_recv_buf(RedChannelClient *rcc, uint16_t type, uint32_t size)
{
CommonChannel *common = SPICE_CONTAINEROF(rcc->channel, CommonChannel, base);
return common->recv_buf;
}
-static void common_release_recv_buf(RedChannelClient *rcc,
- SpiceDataHeader *msg_header, uint8_t* msg)
+static void common_release_recv_buf(RedChannelClient *rcc, uint16_t type, uint32_t size,
+ uint8_t* msg)
{
}
@@ -7785,7 +7785,6 @@ static inline void display_begin_send_message(RedChannelClient *rcc,
{
DisplayChannelClient *dcc = RCC_TO_DCC(rcc);
FreeList *free_list = &dcc->send_data.free_list;
- SpiceDataHeader *header = red_channel_client_get_header(rcc);
if (free_list->res->count) {
int sub_list_len = 1;
@@ -7828,7 +7827,7 @@ static inline void display_begin_send_message(RedChannelClient *rcc,
spice_marshaller_add_uint32(sub_list_m, spice_marshaller_get_offset(wait_m));
}
spice_marshaller_add_uint32(sub_list_m, spice_marshaller_get_offset(inval_m));
- header->sub_list = spice_marshaller_get_offset(sub_list_m);
+ red_channel_client_set_header_sub_list(rcc, spice_marshaller_get_offset(sub_list_m));
}
red_channel_client_begin_send_message(rcc);
}
diff --git a/server/smartcard.c b/server/smartcard.c
index f9cafdf..08ba3da 100644
--- a/server/smartcard.c
+++ b/server/smartcard.c
@@ -273,15 +273,18 @@ static int smartcard_channel_client_config_socket(RedChannelClient *rcc)
}
static uint8_t *smartcard_channel_alloc_msg_rcv_buf(RedChannelClient *rcc,
- SpiceDataHeader *msg_header)
+ uint16_t type,
+ uint32_t size)
{
- return spice_malloc(msg_header->size);
+ return spice_malloc(size);
}
static void smartcard_channel_release_msg_rcv_buf(RedChannelClient *rcc,
- SpiceDataHeader *msg_header, uint8_t *msg)
+ uint16_t type,
+ uint32_t size,
+ uint8_t *msg)
{
- red_printf("freeing %d bytes", msg_header->size);
+ red_printf("freeing %d bytes", size);
free(msg);
}
@@ -439,14 +442,15 @@ static void smartcard_channel_write_to_reader(VSCMsgHeader *vheader)
}
static int smartcard_channel_handle_message(RedChannelClient *rcc,
- SpiceDataHeader *header,
+ uint16_t type,
+ uint32_t size,
uint8_t *msg)
{
VSCMsgHeader* vheader = (VSCMsgHeader*)msg;
- if (header->type != SPICE_MSGC_SMARTCARD_DATA) {
+ if (type != SPICE_MSGC_SMARTCARD_DATA) {
/* handle ack's, spicy sends them while spicec does not */
- return red_channel_client_handle_message(rcc, header->size, header->type, msg);
+ return red_channel_client_handle_message(rcc, size, type, msg);
}
ASSERT(header->size == vheader->length + sizeof(VSCMsgHeader));
diff --git a/server/spicevmc.c b/server/spicevmc.c
index a08f330..6df5313 100644
--- a/server/spicevmc.c
+++ b/server/spicevmc.c
@@ -126,7 +126,9 @@ static void spicevmc_red_channel_client_on_disconnect(RedChannelClient *rcc)
}
static int spicevmc_red_channel_client_handle_message(RedChannelClient *rcc,
- SpiceDataHeader *header, uint8_t *msg)
+ uint16_t type,
+ uint32_t size,
+ uint8_t *msg)
{
SpiceVmcState *state;
SpiceCharDeviceInstance *sin;
@@ -136,22 +138,22 @@ static int spicevmc_red_channel_client_handle_message(RedChannelClient *rcc,
sin = state->chardev_sin;
sif = SPICE_CONTAINEROF(sin->base.sif, SpiceCharDeviceInterface, base);
- if (header->type != SPICE_MSGC_SPICEVMC_DATA) {
- return red_channel_client_handle_message(rcc, header->size,
- header->type, msg);
+ if (type != SPICE_MSGC_SPICEVMC_DATA) {
+ return red_channel_client_handle_message(rcc, size, type, msg);
}
/*
* qemu spicevmc will consume everything we give it, no need for
* flow control checks (or to use a pipe).
*/
- sif->write(sin, msg, header->size);
+ sif->write(sin, msg, size);
return TRUE;
}
static uint8_t *spicevmc_red_channel_alloc_msg_rcv_buf(RedChannelClient *rcc,
- SpiceDataHeader *msg_header)
+ uint16_t type,
+ uint32_t size)
{
SpiceVmcState *state;
@@ -159,9 +161,9 @@ static uint8_t *spicevmc_red_channel_alloc_msg_rcv_buf(RedChannelClient *rcc,
assert(!state->rcv_buf_in_use);
- if (msg_header->size > state->rcv_buf_size) {
- state->rcv_buf = spice_realloc(state->rcv_buf, msg_header->size);
- state->rcv_buf_size = msg_header->size;
+ if (size > state->rcv_buf_size) {
+ state->rcv_buf = spice_realloc(state->rcv_buf, size);
+ state->rcv_buf_size = size;
}
state->rcv_buf_in_use = 1;
@@ -170,7 +172,9 @@ static uint8_t *spicevmc_red_channel_alloc_msg_rcv_buf(RedChannelClient *rcc,
}
static void spicevmc_red_channel_release_msg_rcv_buf(RedChannelClient *rcc,
- SpiceDataHeader *msg_header, uint8_t *msg)
+ uint16_t type,
+ uint32_t size,
+ uint8_t *msg)
{
SpiceVmcState *state;
--
1.7.6.4
More information about the Spice-devel
mailing list