From ca67a006d45855cdaadbbe22b8fc82a658e9760a5f7662a5c2ffd806c1cd9a1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= Date: Tue, 7 Mar 2017 15:00:43 +0000 Subject: [PATCH 1/2] Accepting request 459243 from home:michals:boo1012215 Add endian swapping to run on BE guests (boo#1012215). OBS-URL: https://build.opensuse.org/request/show/459243 OBS-URL: https://build.opensuse.org/package/show/Virtualization/spice-vdagent?expand=0&rev=19 --- spice-vdagent.changes | 5 + spice-vdagent.spec | 4 +- vdagentd-do-endian-swapping.patch | 719 ++++++++++++++++++++++++++++++ 3 files changed, 727 insertions(+), 1 deletion(-) create mode 100644 vdagentd-do-endian-swapping.patch diff --git a/spice-vdagent.changes b/spice-vdagent.changes index e611a36..bc492c5 100644 --- a/spice-vdagent.changes +++ b/spice-vdagent.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Mon Feb 20 13:56:35 UTC 2017 - msuchanek@suse.com + +- Add endian swapping to run on BE guests (boo#1012215). + ------------------------------------------------------------------- Fri Nov 25 18:53:15 UTC 2016 - zaitor@opensuse.org diff --git a/spice-vdagent.spec b/spice-vdagent.spec index 412e33d..bb503d1 100644 --- a/spice-vdagent.spec +++ b/spice-vdagent.spec @@ -1,7 +1,7 @@ # # spec file for package spice-vdagent # -# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany. # Copyright (c) 2014 B1 Systems GmbH, Vohburg, Germany. # # All modifications and additions to the file contributed by third parties @@ -26,6 +26,7 @@ Group: Applications/System Url: http://spice-space.org/ Source0: http://spice-space.org/download/releases/%{name}-%{version}.tar.bz2 Patch0: spice-vdagent-var_run.patch +Patch1: vdagentd-do-endian-swapping.patch BuildRequires: alsa-devel >= 1.0.22 BuildRequires: desktop-file-utils BuildRequires: glib2-devel @@ -57,6 +58,7 @@ Features: %prep %setup -q %patch0 -p1 +%patch1 -p1 %build %configure \ diff --git a/vdagentd-do-endian-swapping.patch b/vdagentd-do-endian-swapping.patch new file mode 100644 index 0000000..d7d195a --- /dev/null +++ b/vdagentd-do-endian-swapping.patch @@ -0,0 +1,719 @@ +From 1c0c3a0d32d71f2b3890b39b245981c3f32777c5 Mon Sep 17 00:00:00 2001 +From: Michal Suchanek +Date: Mon, 23 Jan 2017 14:53:53 +0100 +Subject: [PATCH] Move mouse-specific handling out of virtio_port_read_complete + +Move some mouse-specific code from the start of +virtio_port_read_complete to a separate helper +as is the case with other message types. + +Signed-off-by: Michal Suchanek +Acked-by: Christophe Fergeau +--- + src/vdagentd.c | 43 ++++++++++++++++++++++++------------------- + 1 file changed, 24 insertions(+), 19 deletions(-) + +diff --git a/src/vdagentd.c b/src/vdagentd.c +index a699681..4d587d1 100644 +--- a/src/vdagentd.c ++++ b/src/vdagentd.c +@@ -118,6 +118,29 @@ static void do_client_disconnect(void) + } + } + ++void do_client_mouse(struct vdagentd_uinput **uinputp, VDAgentMouseState *mouse) ++{ ++ vdagentd_uinput_do_mouse(uinputp, mouse); ++ if (!*uinputp) { ++ /* Try to re-open the tablet */ ++ struct agent_data *agent_data = ++ udscs_get_user_data(active_session_conn); ++ if (agent_data) ++ *uinputp = vdagentd_uinput_create(uinput_device, ++ agent_data->width, ++ agent_data->height, ++ agent_data->screen_info, ++ agent_data->screen_count, ++ debug > 1, ++ uinput_fake); ++ if (!*uinputp) { ++ syslog(LOG_CRIT, "Fatal uinput error"); ++ retval = 1; ++ quit = 1; ++ } ++ } ++} ++ + static void do_client_monitors(struct vdagent_virtio_port *vport, int port_nr, + VDAgentMessage *message_header, VDAgentMonitorsConfig *new_monitors) + { +@@ -333,25 +356,7 @@ static int virtio_port_read_complete( + case VD_AGENT_MOUSE_STATE: + if (message_header->size != sizeof(VDAgentMouseState)) + goto size_error; +- vdagentd_uinput_do_mouse(&uinput, (VDAgentMouseState *)data); +- if (!uinput) { +- /* Try to re-open the tablet */ +- struct agent_data *agent_data = +- udscs_get_user_data(active_session_conn); +- if (agent_data) +- uinput = vdagentd_uinput_create(uinput_device, +- agent_data->width, +- agent_data->height, +- agent_data->screen_info, +- agent_data->screen_count, +- debug > 1, +- uinput_fake); +- if (!uinput) { +- syslog(LOG_CRIT, "Fatal uinput error"); +- retval = 1; +- quit = 1; +- } +- } ++ do_client_mouse(&uinput, (VDAgentMouseState *)data); + break; + case VD_AGENT_MONITORS_CONFIG: + if (message_header->size < sizeof(VDAgentMonitorsConfig)) +-- +2.10.2 + +From a430acfb779f9cfcc01aaa18a656c8d5a7042a27 Mon Sep 17 00:00:00 2001 +From: Michal Suchanek +Date: Fri, 27 Jan 2017 18:53:38 +0100 +Subject: [PATCH] vdagentd: Quiet uninitialized variable warning. + +With gcc 6.2.1 I cannot build vdagentd because gcc detects msg_type as +potentially uninitialized and vdagentd is built with -Werror. + +gcc 4.8.5 does not detect the issue and gcc 7 should be able to tell +that do_client_file_xfer is called only with values of +message_header->type handled in the switch. + +Signed-off-by: Michal Suchanek +Acked-by: Christophe Fergeau +--- + src/vdagentd.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/vdagentd.c b/src/vdagentd.c +index 4d587d1..0e0d4a3 100644 +--- a/src/vdagentd.c ++++ b/src/vdagentd.c +@@ -328,6 +328,8 @@ static void do_client_file_xfer(struct vdagent_virtio_port *vport, + id = d->id; + break; + } ++ default: ++ g_return_if_reached(); /* quiet uninitialized variable warning */ + } + + conn = g_hash_table_lookup(active_xfers, GUINT_TO_POINTER(id)); +-- +2.10.2 + +From dd8ac5e041ab3f8d8c9b3f53e7564566ee183c20 Mon Sep 17 00:00:00 2001 +From: Victor Toso +Date: Mon, 23 Jan 2017 14:53:54 +0100 +Subject: [PATCH] vdagentd: early return on bad message size + +The payload size for each message should be the size of the expected +struct or bigger when it contain arrays of no fixed size. + +This patch creates: + * vdagent_message_min_size[] static array with the expected size for + each message; + * vdagent_message_check_size() which checks the size of message's + payload based on the type of message and by using + vdagent_message_min_size[] as reference" + +Signed-off-by: Victor Toso +Signed-off-by: Michal Suchanek +Acked-by: Christophe Fergeau +--- + src/vdagentd.c | 133 +++++++++++++++++++++++++++++++++++++++------------------ + 1 file changed, 91 insertions(+), 42 deletions(-) + +diff --git a/src/vdagentd.c b/src/vdagentd.c +index 0e0d4a3..579446a 100644 +--- a/src/vdagentd.c ++++ b/src/vdagentd.c +@@ -341,34 +341,109 @@ static void do_client_file_xfer(struct vdagent_virtio_port *vport, + udscs_write(conn, msg_type, 0, 0, data, message_header->size); + } + ++static gsize vdagent_message_min_size[] = ++{ ++ -1, /* Does not exist */ ++ sizeof(VDAgentMouseState), /* VD_AGENT_MOUSE_STATE */ ++ sizeof(VDAgentMonitorsConfig), /* VD_AGENT_MONITORS_CONFIG */ ++ sizeof(VDAgentReply), /* VD_AGENT_REPLY */ ++ sizeof(VDAgentClipboard), /* VD_AGENT_CLIPBOARD */ ++ sizeof(VDAgentDisplayConfig), /* VD_AGENT_DISPLAY_CONFIG */ ++ sizeof(VDAgentAnnounceCapabilities), /* VD_AGENT_ANNOUNCE_CAPABILITIES */ ++ sizeof(VDAgentClipboardGrab), /* VD_AGENT_CLIPBOARD_GRAB */ ++ sizeof(VDAgentClipboardRequest), /* VD_AGENT_CLIPBOARD_REQUEST */ ++ sizeof(VDAgentClipboardRelease), /* VD_AGENT_CLIPBOARD_RELEASE */ ++ sizeof(VDAgentFileXferStartMessage), /* VD_AGENT_FILE_XFER_START */ ++ sizeof(VDAgentFileXferStatusMessage), /* VD_AGENT_FILE_XFER_STATUS */ ++ sizeof(VDAgentFileXferDataMessage), /* VD_AGENT_FILE_XFER_DATA */ ++ 0, /* VD_AGENT_CLIENT_DISCONNECTED */ ++ sizeof(VDAgentMaxClipboard), /* VD_AGENT_MAX_CLIPBOARD */ ++ sizeof(VDAgentAudioVolumeSync), /* VD_AGENT_AUDIO_VOLUME_SYNC */ ++}; ++ ++static gboolean vdagent_message_check_size(const VDAgentMessage *message_header) ++{ ++ uint32_t min_size = 0; ++ ++ if (message_header->protocol != VD_AGENT_PROTOCOL) { ++ syslog(LOG_ERR, "message with wrong protocol version ignoring"); ++ return FALSE; ++ } ++ ++ if (!message_header->type || ++ message_header->type >= G_N_ELEMENTS(vdagent_message_min_size)) { ++ syslog(LOG_WARNING, "unknown message type %d, ignoring", ++ message_header->type); ++ return FALSE; ++ } ++ ++ min_size = vdagent_message_min_size[message_header->type]; ++ if (VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size, ++ VD_AGENT_CAP_CLIPBOARD_SELECTION)) { ++ switch (message_header->type) { ++ case VD_AGENT_CLIPBOARD_GRAB: ++ case VD_AGENT_CLIPBOARD_REQUEST: ++ case VD_AGENT_CLIPBOARD: ++ case VD_AGENT_CLIPBOARD_RELEASE: ++ min_size += 4; ++ } ++ } ++ ++ switch (message_header->type) { ++ case VD_AGENT_MONITORS_CONFIG: ++ case VD_AGENT_CLIPBOARD: ++ case VD_AGENT_CLIPBOARD_GRAB: ++ case VD_AGENT_CLIPBOARD_REQUEST: ++ case VD_AGENT_CLIPBOARD_RELEASE: ++ case VD_AGENT_AUDIO_VOLUME_SYNC: ++ case VD_AGENT_ANNOUNCE_CAPABILITIES: ++ if (message_header->size < min_size) { ++ syslog(LOG_ERR, "read: invalid message size: %u for message type: %u", ++ message_header->size, message_header->type); ++ return FALSE; ++ } ++ break; ++ case VD_AGENT_MOUSE_STATE: ++ case VD_AGENT_MAX_CLIPBOARD: ++ if (message_header->size != min_size) { ++ syslog(LOG_ERR, "read: invalid message size: %u for message type: %u", ++ message_header->size, message_header->type); ++ return FALSE; ++ } ++ break; ++ case VD_AGENT_FILE_XFER_START: ++ case VD_AGENT_FILE_XFER_DATA: ++ case VD_AGENT_FILE_XFER_STATUS: ++ case VD_AGENT_CLIENT_DISCONNECTED: ++ /* No size checks for these at the moment */ ++ break; ++ case VD_AGENT_DISPLAY_CONFIG: ++ case VD_AGENT_REPLY: ++ default: ++ g_warn_if_reached(); ++ return FALSE; ++ } ++ return TRUE; ++} ++ + static int virtio_port_read_complete( + struct vdagent_virtio_port *vport, + int port_nr, + VDAgentMessage *message_header, + uint8_t *data) + { +- uint32_t min_size = 0; +- +- if (message_header->protocol != VD_AGENT_PROTOCOL) { +- syslog(LOG_ERR, "message with wrong protocol version ignoring"); ++ if (!vdagent_message_check_size(message_header)) + return 0; +- } + + switch (message_header->type) { + case VD_AGENT_MOUSE_STATE: +- if (message_header->size != sizeof(VDAgentMouseState)) +- goto size_error; + do_client_mouse(&uinput, (VDAgentMouseState *)data); + break; + case VD_AGENT_MONITORS_CONFIG: +- if (message_header->size < sizeof(VDAgentMonitorsConfig)) +- goto size_error; + do_client_monitors(vport, port_nr, message_header, + (VDAgentMonitorsConfig *)data); + break; + case VD_AGENT_ANNOUNCE_CAPABILITIES: +- if (message_header->size < sizeof(VDAgentAnnounceCapabilities)) +- goto size_error; + do_client_capabilities(vport, message_header, + (VDAgentAnnounceCapabilities *)data); + break; +@@ -376,21 +451,6 @@ static int virtio_port_read_complete( + case VD_AGENT_CLIPBOARD_REQUEST: + case VD_AGENT_CLIPBOARD: + case VD_AGENT_CLIPBOARD_RELEASE: +- switch (message_header->type) { +- case VD_AGENT_CLIPBOARD_GRAB: +- min_size = sizeof(VDAgentClipboardGrab); break; +- case VD_AGENT_CLIPBOARD_REQUEST: +- min_size = sizeof(VDAgentClipboardRequest); break; +- case VD_AGENT_CLIPBOARD: +- min_size = sizeof(VDAgentClipboard); break; +- } +- if (VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size, +- VD_AGENT_CAP_CLIPBOARD_SELECTION)) { +- min_size += 4; +- } +- if (message_header->size < min_size) { +- goto size_error; +- } + do_client_clipboard(vport, message_header, data); + break; + case VD_AGENT_FILE_XFER_START: +@@ -402,31 +462,20 @@ static int virtio_port_read_complete( + vdagent_virtio_port_reset(vport, VDP_CLIENT_PORT); + do_client_disconnect(); + break; +- case VD_AGENT_MAX_CLIPBOARD: +- if (message_header->size != sizeof(VDAgentMaxClipboard)) +- goto size_error; +- VDAgentMaxClipboard *msg = (VDAgentMaxClipboard *)data; +- syslog(LOG_DEBUG, "Set max clipboard: %d", msg->max); +- max_clipboard = msg->max; ++ case VD_AGENT_MAX_CLIPBOARD: { ++ max_clipboard = ((VDAgentMaxClipboard *)data)->max; ++ syslog(LOG_DEBUG, "Set max clipboard: %d", max_clipboard); + break; ++ } + case VD_AGENT_AUDIO_VOLUME_SYNC: +- if (message_header->size < sizeof(VDAgentAudioVolumeSync)) +- goto size_error; +- + do_client_volume_sync(vport, port_nr, message_header, + (VDAgentAudioVolumeSync *)data); + break; + default: +- syslog(LOG_WARNING, "unknown message type %d, ignoring", +- message_header->type); ++ g_warn_if_reached(); + } + + return 0; +- +-size_error: +- syslog(LOG_ERR, "read: invalid message size: %u for message type: %u", +- message_header->size, message_header->type); +- return 0; + } + + static void virtio_write_clipboard(uint8_t selection, uint32_t msg_type, +-- +2.10.2 + +From 3102dca497aae947c29455876cad5ba882613224 Mon Sep 17 00:00:00 2001 +From: Christophe Fergeau +Date: Mon, 30 Jan 2017 12:57:55 +0100 +Subject: [PATCH] vdagentd: Add missing size checks + +Acked-by: Victor Toso +--- + src/vdagentd.c | 14 ++++++-------- + 1 file changed, 6 insertions(+), 8 deletions(-) + +diff --git a/src/vdagentd.c b/src/vdagentd.c +index 579446a..ffafba9 100644 +--- a/src/vdagentd.c ++++ b/src/vdagentd.c +@@ -391,6 +391,8 @@ static gboolean vdagent_message_check_size(const VDAgentMessage *message_header) + + switch (message_header->type) { + case VD_AGENT_MONITORS_CONFIG: ++ case VD_AGENT_FILE_XFER_START: ++ case VD_AGENT_FILE_XFER_DATA: + case VD_AGENT_CLIPBOARD: + case VD_AGENT_CLIPBOARD_GRAB: + case VD_AGENT_CLIPBOARD_REQUEST: +@@ -404,21 +406,17 @@ static gboolean vdagent_message_check_size(const VDAgentMessage *message_header) + } + break; + case VD_AGENT_MOUSE_STATE: ++ case VD_AGENT_FILE_XFER_STATUS: ++ case VD_AGENT_DISPLAY_CONFIG: ++ case VD_AGENT_REPLY: + case VD_AGENT_MAX_CLIPBOARD: ++ case VD_AGENT_CLIENT_DISCONNECTED: + if (message_header->size != min_size) { + syslog(LOG_ERR, "read: invalid message size: %u for message type: %u", + message_header->size, message_header->type); + return FALSE; + } + break; +- case VD_AGENT_FILE_XFER_START: +- case VD_AGENT_FILE_XFER_DATA: +- case VD_AGENT_FILE_XFER_STATUS: +- case VD_AGENT_CLIENT_DISCONNECTED: +- /* No size checks for these at the moment */ +- break; +- case VD_AGENT_DISPLAY_CONFIG: +- case VD_AGENT_REPLY: + default: + g_warn_if_reached(); + return FALSE; +-- +2.10.2 + +From 1b59bd11ebc3edce1957bfaaaeb90e559171e4ad Mon Sep 17 00:00:00 2001 +From: Christophe Fergeau +Date: Mon, 30 Jan 2017 12:58:06 +0100 +Subject: [PATCH] vdagentd: Adjust size checks + +Acked-by: Victor Toso +--- + src/vdagentd.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/vdagentd.c b/src/vdagentd.c +index ffafba9..a1bbf71 100644 +--- a/src/vdagentd.c ++++ b/src/vdagentd.c +@@ -395,8 +395,6 @@ static gboolean vdagent_message_check_size(const VDAgentMessage *message_header) + case VD_AGENT_FILE_XFER_DATA: + case VD_AGENT_CLIPBOARD: + case VD_AGENT_CLIPBOARD_GRAB: +- case VD_AGENT_CLIPBOARD_REQUEST: +- case VD_AGENT_CLIPBOARD_RELEASE: + case VD_AGENT_AUDIO_VOLUME_SYNC: + case VD_AGENT_ANNOUNCE_CAPABILITIES: + if (message_header->size < min_size) { +@@ -409,6 +407,8 @@ static gboolean vdagent_message_check_size(const VDAgentMessage *message_header) + case VD_AGENT_FILE_XFER_STATUS: + case VD_AGENT_DISPLAY_CONFIG: + case VD_AGENT_REPLY: ++ case VD_AGENT_CLIPBOARD_REQUEST: ++ case VD_AGENT_CLIPBOARD_RELEASE: + case VD_AGENT_MAX_CLIPBOARD: + case VD_AGENT_CLIENT_DISCONNECTED: + if (message_header->size != min_size) { +-- +2.10.2 + +From 44b2511b2dd621ca6267f73c4f29fccfb0302bc6 Mon Sep 17 00:00:00 2001 +From: Michal Suchanek +Date: Fri, 27 Jan 2017 18:53:40 +0100 +Subject: [PATCH] vdagentd: Do endian swapping. + +This allows running big endian and little endian guest side by side using +cut & paste between them. + +There is a general design idea that swapping should come as close to +virtio_read/virtio_write as possible. In particular, the protocol +between vdagent and vdagentd is guest-specific and in native endian. +With muliple layers of headers this is a bit tricky. A few message types +have to be swapped fully before passing through vdagentd. + +Signed-off-by: Michal Suchanek +Signed-off-by: Victor Toso +--- + src/vdagent-virtio-port.c | 36 +++++++++------ + src/vdagentd.c | 109 +++++++++++++++++++++++++++++++++++++++++----- + 2 files changed, 120 insertions(+), 25 deletions(-) + +diff --git a/src/vdagent-virtio-port.c b/src/vdagent-virtio-port.c +index 6267c74..2d1ee5b 100644 +--- a/src/vdagent-virtio-port.c ++++ b/src/vdagent-virtio-port.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + #include "vdagent-virtio-port.h" + +@@ -216,16 +217,16 @@ int vdagent_virtio_port_write_start( + return -1; + } + +- chunk_header.port = port_nr; +- chunk_header.size = sizeof(message_header) + data_size; ++ chunk_header.port = GUINT32_TO_LE(port_nr); ++ chunk_header.size = GUINT32_TO_LE(sizeof(message_header) + data_size); + memcpy(new_wbuf->buf + new_wbuf->write_pos, &chunk_header, + sizeof(chunk_header)); + new_wbuf->write_pos += sizeof(chunk_header); + +- message_header.protocol = VD_AGENT_PROTOCOL; +- message_header.type = message_type; +- message_header.opaque = message_opaque; +- message_header.size = data_size; ++ message_header.protocol = GUINT32_TO_LE(VD_AGENT_PROTOCOL); ++ message_header.type = GUINT32_TO_LE(message_type); ++ message_header.opaque = GUINT64_TO_LE(message_opaque); ++ message_header.size = GUINT32_TO_LE(data_size); + memcpy(new_wbuf->buf + new_wbuf->write_pos, &message_header, + sizeof(message_header)); + new_wbuf->write_pos += sizeof(message_header); +@@ -309,13 +310,20 @@ static void vdagent_virtio_port_do_chunk(struct vdagent_virtio_port **vportp) + memcpy((uint8_t *)&port->message_header + port->message_header_read, + vport->chunk_data, read); + port->message_header_read += read; +- if (port->message_header_read == sizeof(port->message_header) && +- port->message_header.size) { +- port->message_data = malloc(port->message_header.size); +- if (!port->message_data) { +- syslog(LOG_ERR, "out of memory, disconnecting virtio"); +- vdagent_virtio_port_destroy(vportp); +- return; ++ if (port->message_header_read == sizeof(port->message_header)) { ++ ++ port->message_header.protocol = GUINT32_FROM_LE(port->message_header.protocol); ++ port->message_header.type = GUINT32_FROM_LE(port->message_header.type); ++ port->message_header.opaque = GUINT64_FROM_LE(port->message_header.opaque); ++ port->message_header.size = GUINT32_FROM_LE(port->message_header.size); ++ ++ if (port->message_header.size) { ++ port->message_data = malloc(port->message_header.size); ++ if (!port->message_data) { ++ syslog(LOG_ERR, "out of memory, disconnecting virtio"); ++ vdagent_virtio_port_destroy(vportp); ++ return; ++ } + } + } + pos = read; +@@ -420,6 +428,8 @@ static void vdagent_virtio_port_do_read(struct vdagent_virtio_port **vportp) + if (vport->chunk_header_read < sizeof(vport->chunk_header)) { + vport->chunk_header_read += n; + if (vport->chunk_header_read == sizeof(vport->chunk_header)) { ++ vport->chunk_header.size = GUINT32_FROM_LE(vport->chunk_header.size); ++ vport->chunk_header.port = GUINT32_FROM_LE(vport->chunk_header.port); + if (vport->chunk_header.size > VD_AGENT_MAX_DATA_SIZE) { + syslog(LOG_ERR, "chunk size %u too large", + vport->chunk_header.size); +diff --git a/src/vdagentd.c b/src/vdagentd.c +index a1bbf71..5ea98eb 100644 +--- a/src/vdagentd.c ++++ b/src/vdagentd.c +@@ -78,6 +78,34 @@ static int client_connected = 0; + static int max_clipboard = -1; + + /* utility functions */ ++static void virtio_msg_uint32_to_le(uint8_t *_msg, uint32_t size, uint32_t offset) ++{ ++ uint32_t i, *msg = (uint32_t *)(_msg + offset); ++ ++ /* offset - size % 4 should be 0 - extra bytes are ignored */ ++ for (i = 0; i < (size - offset) / 4; i++) ++ msg[i] = GUINT32_TO_LE(msg[i]); ++} ++ ++static void virtio_msg_uint32_from_le(uint8_t *_msg, uint32_t size, uint32_t offset) ++{ ++ uint32_t i, *msg = (uint32_t *)(_msg + offset); ++ ++ /* offset - size % 4 should be 0 - extra bytes are ignored */ ++ for (i = 0; i < (size - offset) / 4; i++) ++ msg[i] = GUINT32_FROM_LE(msg[i]); ++} ++ ++static void virtio_msg_uint16_from_le(uint8_t *_msg, uint32_t size, uint32_t offset) ++{ ++ uint32_t i; ++ uint16_t *msg = (uint16_t *)(_msg + offset); ++ ++ /* offset - size % 2 should be 0 - extra bytes are ignored */ ++ for (i = 0; i < (size - offset) / 2; i++) ++ msg[i] = GUINT16_FROM_LE(msg[i]); ++} ++ + /* vdagentd <-> spice-client communication handling */ + static void send_capabilities(struct vdagent_virtio_port *vport, + uint32_t request) +@@ -102,6 +130,7 @@ static void send_capabilities(struct vdagent_virtio_port *vport, + VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_GUEST_LINEEND_LF); + VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_MAX_CLIPBOARD); + VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_AUDIO_VOLUME_SYNC); ++ virtio_msg_uint32_to_le((uint8_t *)caps, size, 0); + + vdagent_virtio_port_write(vport, VDP_CLIENT_PORT, + VD_AGENT_ANNOUNCE_CAPABILITIES, 0, +@@ -174,8 +203,8 @@ static void do_client_monitors(struct vdagent_virtio_port *vport, int port_nr, + (uint8_t *)mon_config, size); + + /* Acknowledge reception of monitors config to spice server / client */ +- reply.type = VD_AGENT_MONITORS_CONFIG; +- reply.error = VD_AGENT_SUCCESS; ++ reply.type = GUINT32_TO_LE(VD_AGENT_MONITORS_CONFIG); ++ reply.error = GUINT32_TO_LE(VD_AGENT_SUCCESS); + vdagent_virtio_port_write(vport, port_nr, VD_AGENT_REPLY, 0, + (uint8_t *)&reply, sizeof(reply)); + } +@@ -278,8 +307,8 @@ static void send_file_xfer_status(struct vdagent_virtio_port *vport, + const char *msg, uint32_t id, uint32_t xfer_status) + { + VDAgentFileXferStatusMessage status = { +- .id = id, +- .result = xfer_status, ++ .id = GUINT32_TO_LE(id), ++ .result = GUINT32_TO_LE(xfer_status), + }; + syslog(LOG_WARNING, msg, id); + if (vport) +@@ -361,6 +390,50 @@ static gsize vdagent_message_min_size[] = + sizeof(VDAgentAudioVolumeSync), /* VD_AGENT_AUDIO_VOLUME_SYNC */ + }; + ++static void vdagent_message_clipboard_from_le(VDAgentMessage *message_header, ++ uint8_t *data) ++{ ++ gsize min_size = vdagent_message_min_size[message_header->type]; ++ uint32_t *data_type = (uint32_t *) data; ++ ++ if (VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size, ++ VD_AGENT_CAP_CLIPBOARD_SELECTION)) { ++ min_size += 4; ++ data_type++; ++ } ++ ++ switch (message_header->type) { ++ case VD_AGENT_CLIPBOARD_REQUEST: ++ case VD_AGENT_CLIPBOARD: ++ *data_type = GUINT32_FROM_LE(*data_type); ++ break; ++ case VD_AGENT_CLIPBOARD_GRAB: ++ virtio_msg_uint32_from_le(data, message_header->size, min_size); ++ break; ++ default: ++ g_warn_if_reached(); ++ } ++} ++ ++static void vdagent_message_file_xfer_from_le(VDAgentMessage *message_header, ++ uint8_t *data) ++{ ++ uint32_t *id = (uint32_t *)data; ++ *id = GUINT32_FROM_LE(*id); ++ id++; /* status */ ++ ++ switch (message_header->type) { ++ case VD_AGENT_FILE_XFER_DATA: { ++ VDAgentFileXferDataMessage *msg = (VDAgentFileXferDataMessage *)data; ++ msg->size = GUINT64_FROM_LE(msg->size); ++ break; ++ } ++ case VD_AGENT_FILE_XFER_STATUS: ++ *id = GUINT32_FROM_LE(*id); /* status */ ++ break; ++ } ++} ++ + static gboolean vdagent_message_check_size(const VDAgentMessage *message_header) + { + uint32_t min_size = 0; +@@ -435,13 +508,16 @@ static int virtio_port_read_complete( + + switch (message_header->type) { + case VD_AGENT_MOUSE_STATE: ++ virtio_msg_uint32_from_le(data, message_header->size, 0); + do_client_mouse(&uinput, (VDAgentMouseState *)data); + break; + case VD_AGENT_MONITORS_CONFIG: ++ virtio_msg_uint32_from_le(data, message_header->size, 0); + do_client_monitors(vport, port_nr, message_header, + (VDAgentMonitorsConfig *)data); + break; + case VD_AGENT_ANNOUNCE_CAPABILITIES: ++ virtio_msg_uint32_from_le(data, message_header->size, 0); + do_client_capabilities(vport, message_header, + (VDAgentAnnounceCapabilities *)data); + break; +@@ -449,11 +525,13 @@ static int virtio_port_read_complete( + case VD_AGENT_CLIPBOARD_REQUEST: + case VD_AGENT_CLIPBOARD: + case VD_AGENT_CLIPBOARD_RELEASE: ++ vdagent_message_clipboard_from_le(message_header, data); + do_client_clipboard(vport, message_header, data); + break; + case VD_AGENT_FILE_XFER_START: + case VD_AGENT_FILE_XFER_STATUS: + case VD_AGENT_FILE_XFER_DATA: ++ vdagent_message_file_xfer_from_le(message_header, data); + do_client_file_xfer(vport, message_header, data); + break; + case VD_AGENT_CLIENT_DISCONNECTED: +@@ -461,14 +539,18 @@ static int virtio_port_read_complete( + do_client_disconnect(); + break; + case VD_AGENT_MAX_CLIPBOARD: { +- max_clipboard = ((VDAgentMaxClipboard *)data)->max; ++ max_clipboard = GUINT32_FROM_LE(((VDAgentMaxClipboard *)data)->max); + syslog(LOG_DEBUG, "Set max clipboard: %d", max_clipboard); + break; + } +- case VD_AGENT_AUDIO_VOLUME_SYNC: +- do_client_volume_sync(vport, port_nr, message_header, +- (VDAgentAudioVolumeSync *)data); ++ case VD_AGENT_AUDIO_VOLUME_SYNC: { ++ VDAgentAudioVolumeSync *vdata = (VDAgentAudioVolumeSync *)data; ++ virtio_msg_uint16_from_le((uint8_t *)vdata, message_header->size, ++ offsetof(VDAgentAudioVolumeSync, volume)); ++ ++ do_client_volume_sync(vport, port_nr, message_header, vdata); + break; ++ } + default: + g_warn_if_reached(); + } +@@ -477,7 +559,7 @@ static int virtio_port_read_complete( + } + + static void virtio_write_clipboard(uint8_t selection, uint32_t msg_type, +- uint32_t data_type, const uint8_t *data, uint32_t data_size) ++ uint32_t data_type, uint8_t *data, uint32_t data_size) + { + uint32_t size = data_size; + +@@ -498,15 +580,18 @@ static void virtio_write_clipboard(uint8_t selection, uint32_t msg_type, + vdagent_virtio_port_write_append(virtio_port, sel, 4); + } + if (data_type != -1) { ++ data_type = GUINT32_TO_LE(data_type); + vdagent_virtio_port_write_append(virtio_port, (uint8_t*)&data_type, 4); + } + ++ if (msg_type == VD_AGENT_CLIPBOARD_GRAB) ++ virtio_msg_uint32_to_le(data, data_size, 0); + vdagent_virtio_port_write_append(virtio_port, data, data_size); + } + + /* vdagentd <-> vdagent communication handling */ + static int do_agent_clipboard(struct udscs_connection *conn, +- struct udscs_message_header *header, const uint8_t *data) ++ struct udscs_message_header *header, uint8_t *data) + { + uint8_t selection = header->arg1; + uint32_t msg_type = 0, data_type = -1, size = header->size; +@@ -820,8 +905,8 @@ static void agent_read_complete(struct udscs_connection **connp, + break; + case VDAGENTD_FILE_XFER_STATUS:{ + VDAgentFileXferStatusMessage status; +- status.id = header->arg1; +- status.result = header->arg2; ++ status.id = GUINT32_TO_LE(header->arg1); ++ status.result = GUINT32_TO_LE(header->arg2); + vdagent_virtio_port_write(virtio_port, VDP_CLIENT_PORT, + VD_AGENT_FILE_XFER_STATUS, 0, + (uint8_t *)&status, sizeof(status)); +-- +2.10.2 + From f9b02811a9345b1be1a0b0facf7b427c0b4bcf0d18c8ac154882f3c1d93ace0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= Date: Tue, 7 Mar 2017 15:29:13 +0000 Subject: [PATCH 2/2] Add mention of vdagentd-do-endian-swapping.patch OBS-URL: https://build.opensuse.org/package/show/Virtualization/spice-vdagent?expand=0&rev=20 --- spice-vdagent.changes | 1 + spice-vdagent.spec | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/spice-vdagent.changes b/spice-vdagent.changes index bc492c5..aec3677 100644 --- a/spice-vdagent.changes +++ b/spice-vdagent.changes @@ -2,6 +2,7 @@ Mon Feb 20 13:56:35 UTC 2017 - msuchanek@suse.com - Add endian swapping to run on BE guests (boo#1012215). + vdagentd-do-endian-swapping.patch ------------------------------------------------------------------- Fri Nov 25 18:53:15 UTC 2016 - zaitor@opensuse.org diff --git a/spice-vdagent.spec b/spice-vdagent.spec index bb503d1..92f9b3f 100644 --- a/spice-vdagent.spec +++ b/spice-vdagent.spec @@ -1,7 +1,7 @@ # # spec file for package spice-vdagent # -# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2017 SUSE LINUX Products GmbH, Nuernberg, Germany. # Copyright (c) 2014 B1 Systems GmbH, Vohburg, Germany. # # All modifications and additions to the file contributed by third parties