From da7fa8a15dfafd07e5956b69996d99880596c333 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Fri, 16 Feb 2018 11:48:41 -0800 Subject: recipes-devtools: Bump QEMU to 2.11.1 Bump the QEMU version to the bug fix release of 2.11.1 and remove the patches that are no longer required. Signed-off-by: Alistair Francis Signed-off-by: Ross Burton --- .../qemu/qemu/CVE-2017-15124.patch | 1476 -------------------- meta/recipes-devtools/qemu/qemu_2.11.0.bb | 59 - meta/recipes-devtools/qemu/qemu_2.11.1.bb | 58 + 3 files changed, 58 insertions(+), 1535 deletions(-) delete mode 100644 meta/recipes-devtools/qemu/qemu/CVE-2017-15124.patch delete mode 100644 meta/recipes-devtools/qemu/qemu_2.11.0.bb create mode 100644 meta/recipes-devtools/qemu/qemu_2.11.1.bb (limited to 'meta/recipes-devtools/qemu') diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2017-15124.patch b/meta/recipes-devtools/qemu/qemu/CVE-2017-15124.patch deleted file mode 100644 index a47b6d0510..0000000000 --- a/meta/recipes-devtools/qemu/qemu/CVE-2017-15124.patch +++ /dev/null @@ -1,1476 +0,0 @@ -VNC server implementation in Quick Emulator (QEMU) 2.11.0 and older was found to -be vulnerable to an unbounded memory allocation issue, as it did not throttle -the framebuffer updates sent to its client. If the client did not consume these -updates, VNC server allocates growing memory to hold onto this data. A malicious -remote VNC client could use this flaw to cause DoS to the server host. - -CVE: CVE-2017-15124 -Upstream-Status: Backport -Signed-off-by: Ross Burton - -From 090fdc83b0960f68d204624a73c6814780da52d9 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Wed, 20 Dec 2017 15:06:18 +0100 -Subject: [PATCH 01/14] vnc: fix debug spelling -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Marc-André Lureau -Message-id: 20171220140618.12701-1-marcandre.lureau@redhat.com -Signed-off-by: Gerd Hoffmann ---- - ui/vnc.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ui/vnc.c b/ui/vnc.c -index 9f8d5a1b1f..7d537b5c6b 100644 ---- a/ui/vnc.c -+++ b/ui/vnc.c -@@ -2255,7 +2255,7 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len) - } - vs->as.nchannels = read_u8(data, 5); - if (vs->as.nchannels != 1 && vs->as.nchannels != 2) { -- VNC_DEBUG("Invalid audio channel coount %d\n", -+ VNC_DEBUG("Invalid audio channel count %d\n", - read_u8(data, 5)); - vnc_client_error(vs); - break; --- -2.11.0 - - -From 6af998db05aec9af95a06f84ad94f1b96785e667 Mon Sep 17 00:00:00 2001 -From: "Daniel P. Berrange" -Date: Mon, 18 Dec 2017 19:12:16 +0000 -Subject: [PATCH 02/14] ui: remove 'sync' parameter from vnc_update_client -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -There is only one caller of vnc_update_client and that always passes false -for the 'sync' parameter. - -Signed-off-by: Daniel P. Berrange -Reviewed-by: Darren Kenny -Reviewed-by: Marc-André Lureau -Message-id: 20171218191228.31018-2-berrange@redhat.com -Signed-off-by: Gerd Hoffmann ---- - ui/vnc.c | 11 +++-------- - 1 file changed, 3 insertions(+), 8 deletions(-) - -diff --git a/ui/vnc.c b/ui/vnc.c -index 7d537b5c6b..d72a61bde3 100644 ---- a/ui/vnc.c -+++ b/ui/vnc.c -@@ -596,7 +596,7 @@ VncInfo2List *qmp_query_vnc_servers(Error **errp) - 3) resolutions > 1024 - */ - --static int vnc_update_client(VncState *vs, int has_dirty, bool sync); -+static int vnc_update_client(VncState *vs, int has_dirty); - static void vnc_disconnect_start(VncState *vs); - - static void vnc_colordepth(VncState *vs); -@@ -961,7 +961,7 @@ static int find_and_clear_dirty_height(VncState *vs, - return h; - } - --static int vnc_update_client(VncState *vs, int has_dirty, bool sync) -+static int vnc_update_client(VncState *vs, int has_dirty) - { - if (vs->disconnecting) { - vnc_disconnect_finish(vs); -@@ -1025,9 +1025,6 @@ static int vnc_update_client(VncState *vs, int has_dirty, bool sync) - } - - vnc_job_push(job); -- if (sync) { -- vnc_jobs_join(vs); -- } - vs->force_update = 0; - vs->has_dirty = 0; - return n; -@@ -1035,8 +1032,6 @@ static int vnc_update_client(VncState *vs, int has_dirty, bool sync) - - if (vs->disconnecting) { - vnc_disconnect_finish(vs); -- } else if (sync) { -- vnc_jobs_join(vs); - } - - return 0; -@@ -2863,7 +2858,7 @@ static void vnc_refresh(DisplayChangeListener *dcl) - vnc_unlock_display(vd); - - QTAILQ_FOREACH_SAFE(vs, &vd->clients, next, vn) { -- rects += vnc_update_client(vs, has_dirty, false); -+ rects += vnc_update_client(vs, has_dirty); - /* vs might be free()ed here */ - } - --- -2.11.0 - - -From c53df961617736f94731d94b62c2954c261d2bae Mon Sep 17 00:00:00 2001 -From: "Daniel P. Berrange" -Date: Mon, 18 Dec 2017 19:12:17 +0000 -Subject: [PATCH 03/14] ui: remove unreachable code in vnc_update_client -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -A previous commit: - - commit 5a8be0f73d6f60ff08746377eb09ca459f39deab - Author: Gerd Hoffmann - Date: Wed Jul 13 12:21:20 2016 +0200 - - vnc: make sure we finish disconnect - -Added a check for vs->disconnecting at the very start of the -vnc_update_client method. This means that the very next "if" -statement check for !vs->disconnecting always evaluates true, -and is thus redundant. This in turn means the vs->disconnecting -check at the very end of the method never evaluates true, and -is thus unreachable code. - -Signed-off-by: Daniel P. Berrange -Reviewed-by: Darren Kenny -Reviewed-by: Marc-André Lureau -Message-id: 20171218191228.31018-3-berrange@redhat.com -Signed-off-by: Gerd Hoffmann ---- - ui/vnc.c | 6 +----- - 1 file changed, 1 insertion(+), 5 deletions(-) - -diff --git a/ui/vnc.c b/ui/vnc.c -index d72a61bde3..29a7208475 100644 ---- a/ui/vnc.c -+++ b/ui/vnc.c -@@ -969,7 +969,7 @@ static int vnc_update_client(VncState *vs, int has_dirty) - } - - vs->has_dirty += has_dirty; -- if (vs->need_update && !vs->disconnecting) { -+ if (vs->need_update) { - VncDisplay *vd = vs->vd; - VncJob *job; - int y; -@@ -1030,10 +1030,6 @@ static int vnc_update_client(VncState *vs, int has_dirty) - return n; - } - -- if (vs->disconnecting) { -- vnc_disconnect_finish(vs); -- } -- - return 0; - } - --- -2.11.0 - - -From b939eb89b6f320544a9328fa908d881d0024c1ee Mon Sep 17 00:00:00 2001 -From: "Daniel P. Berrange" -Date: Mon, 18 Dec 2017 19:12:18 +0000 -Subject: [PATCH 04/14] ui: remove redundant indentation in vnc_client_update -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Now that previous dead / unreachable code has been removed, we can simplify -the indentation in the vnc_client_update method. - -Signed-off-by: Daniel P. Berrange -Reviewed-by: Darren Kenny -Reviewed-by: Marc-André Lureau -Message-id: 20171218191228.31018-4-berrange@redhat.com -Signed-off-by: Gerd Hoffmann ---- - ui/vnc.c | 112 ++++++++++++++++++++++++++++++++------------------------------- - 1 file changed, 57 insertions(+), 55 deletions(-) - -diff --git a/ui/vnc.c b/ui/vnc.c -index 29a7208475..7582111ca6 100644 ---- a/ui/vnc.c -+++ b/ui/vnc.c -@@ -963,74 +963,76 @@ static int find_and_clear_dirty_height(VncState *vs, - - static int vnc_update_client(VncState *vs, int has_dirty) - { -+ VncDisplay *vd = vs->vd; -+ VncJob *job; -+ int y; -+ int height, width; -+ int n = 0; -+ - if (vs->disconnecting) { - vnc_disconnect_finish(vs); - return 0; - } - - vs->has_dirty += has_dirty; -- if (vs->need_update) { -- VncDisplay *vd = vs->vd; -- VncJob *job; -- int y; -- int height, width; -- int n = 0; -- -- if (vs->output.offset && !vs->audio_cap && !vs->force_update) -- /* kernel send buffers are full -> drop frames to throttle */ -- return 0; -+ if (!vs->need_update) { -+ return 0; -+ } - -- if (!vs->has_dirty && !vs->audio_cap && !vs->force_update) -- return 0; -+ if (vs->output.offset && !vs->audio_cap && !vs->force_update) { -+ /* kernel send buffers are full -> drop frames to throttle */ -+ return 0; -+ } - -- /* -- * Send screen updates to the vnc client using the server -- * surface and server dirty map. guest surface updates -- * happening in parallel don't disturb us, the next pass will -- * send them to the client. -- */ -- job = vnc_job_new(vs); -- -- height = pixman_image_get_height(vd->server); -- width = pixman_image_get_width(vd->server); -- -- y = 0; -- for (;;) { -- int x, h; -- unsigned long x2; -- unsigned long offset = find_next_bit((unsigned long *) &vs->dirty, -- height * VNC_DIRTY_BPL(vs), -- y * VNC_DIRTY_BPL(vs)); -- if (offset == height * VNC_DIRTY_BPL(vs)) { -- /* no more dirty bits */ -+ if (!vs->has_dirty && !vs->audio_cap && !vs->force_update) { -+ return 0; -+ } -+ -+ /* -+ * Send screen updates to the vnc client using the server -+ * surface and server dirty map. guest surface updates -+ * happening in parallel don't disturb us, the next pass will -+ * send them to the client. -+ */ -+ job = vnc_job_new(vs); -+ -+ height = pixman_image_get_height(vd->server); -+ width = pixman_image_get_width(vd->server); -+ -+ y = 0; -+ for (;;) { -+ int x, h; -+ unsigned long x2; -+ unsigned long offset = find_next_bit((unsigned long *) &vs->dirty, -+ height * VNC_DIRTY_BPL(vs), -+ y * VNC_DIRTY_BPL(vs)); -+ if (offset == height * VNC_DIRTY_BPL(vs)) { -+ /* no more dirty bits */ -+ break; -+ } -+ y = offset / VNC_DIRTY_BPL(vs); -+ x = offset % VNC_DIRTY_BPL(vs); -+ x2 = find_next_zero_bit((unsigned long *) &vs->dirty[y], -+ VNC_DIRTY_BPL(vs), x); -+ bitmap_clear(vs->dirty[y], x, x2 - x); -+ h = find_and_clear_dirty_height(vs, y, x, x2, height); -+ x2 = MIN(x2, width / VNC_DIRTY_PIXELS_PER_BIT); -+ if (x2 > x) { -+ n += vnc_job_add_rect(job, x * VNC_DIRTY_PIXELS_PER_BIT, y, -+ (x2 - x) * VNC_DIRTY_PIXELS_PER_BIT, h); -+ } -+ if (!x && x2 == width / VNC_DIRTY_PIXELS_PER_BIT) { -+ y += h; -+ if (y == height) { - break; - } -- y = offset / VNC_DIRTY_BPL(vs); -- x = offset % VNC_DIRTY_BPL(vs); -- x2 = find_next_zero_bit((unsigned long *) &vs->dirty[y], -- VNC_DIRTY_BPL(vs), x); -- bitmap_clear(vs->dirty[y], x, x2 - x); -- h = find_and_clear_dirty_height(vs, y, x, x2, height); -- x2 = MIN(x2, width / VNC_DIRTY_PIXELS_PER_BIT); -- if (x2 > x) { -- n += vnc_job_add_rect(job, x * VNC_DIRTY_PIXELS_PER_BIT, y, -- (x2 - x) * VNC_DIRTY_PIXELS_PER_BIT, h); -- } -- if (!x && x2 == width / VNC_DIRTY_PIXELS_PER_BIT) { -- y += h; -- if (y == height) { -- break; -- } -- } - } -- -- vnc_job_push(job); -- vs->force_update = 0; -- vs->has_dirty = 0; -- return n; - } - -- return 0; -+ vnc_job_push(job); -+ vs->force_update = 0; -+ vs->has_dirty = 0; -+ return n; - } - - /* audio */ --- -2.11.0 - - -From 3541b08475d51bddf8aded36576a0ff5a547a978 Mon Sep 17 00:00:00 2001 -From: "Daniel P. Berrange" -Date: Mon, 18 Dec 2017 19:12:19 +0000 -Subject: [PATCH 05/14] ui: avoid pointless VNC updates if framebuffer isn't - dirty -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The vnc_update_client() method checks the 'has_dirty' flag to see if there are -dirty regions that are pending to send to the client. Regardless of this flag, -if a forced update is requested, updates must be sent. For unknown reasons -though, the code also tries to sent updates if audio capture is enabled. This -makes no sense as audio capture state does not impact framebuffer contents, so -this check is removed. - -Signed-off-by: Daniel P. Berrange -Reviewed-by: Darren Kenny -Reviewed-by: Marc-André Lureau -Message-id: 20171218191228.31018-5-berrange@redhat.com -Signed-off-by: Gerd Hoffmann ---- - ui/vnc.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ui/vnc.c b/ui/vnc.c -index 7582111ca6..a79848f083 100644 ---- a/ui/vnc.c -+++ b/ui/vnc.c -@@ -984,7 +984,7 @@ static int vnc_update_client(VncState *vs, int has_dirty) - return 0; - } - -- if (!vs->has_dirty && !vs->audio_cap && !vs->force_update) { -+ if (!vs->has_dirty && !vs->force_update) { - return 0; - } - --- -2.11.0 - - -From 8f61f1c5a6bc06438a1172efa80bc7606594fa07 Mon Sep 17 00:00:00 2001 -From: "Daniel P. Berrange" -Date: Mon, 18 Dec 2017 19:12:20 +0000 -Subject: [PATCH 06/14] ui: track how much decoded data we consumed when doing - SASL encoding -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -When we encode data for writing with SASL, we encode the entire pending output -buffer. The subsequent write, however, may not be able to send the full encoded -data in one go though, particularly with a slow network. So we delay setting the -output buffer offset back to zero until all the SASL encoded data is sent. - -Between encoding the data and completing sending of the SASL encoded data, -however, more data might have been placed on the pending output buffer. So it -is not valid to set offset back to zero. Instead we must keep track of how much -data we consumed during encoding and subtract only that amount. - -With the current bug we would be throwing away some pending data without having -sent it at all. By sheer luck this did not previously cause any serious problem -because appending data to the send buffer is always an atomic action, so we -only ever throw away complete RFB protocol messages. In the case of frame buffer -updates we'd catch up fairly quickly, so no obvious problem was visible. - -Signed-off-by: Daniel P. Berrange -Reviewed-by: Darren Kenny -Reviewed-by: Marc-André Lureau -Message-id: 20171218191228.31018-6-berrange@redhat.com -Signed-off-by: Gerd Hoffmann ---- - ui/vnc-auth-sasl.c | 3 ++- - ui/vnc-auth-sasl.h | 1 + - 2 files changed, 3 insertions(+), 1 deletion(-) - -diff --git a/ui/vnc-auth-sasl.c b/ui/vnc-auth-sasl.c -index 23f28280e7..761493b9b2 100644 ---- a/ui/vnc-auth-sasl.c -+++ b/ui/vnc-auth-sasl.c -@@ -67,6 +67,7 @@ long vnc_client_write_sasl(VncState *vs) - if (err != SASL_OK) - return vnc_client_io_error(vs, -1, NULL); - -+ vs->sasl.encodedRawLength = vs->output.offset; - vs->sasl.encodedOffset = 0; - } - -@@ -78,7 +79,7 @@ long vnc_client_write_sasl(VncState *vs) - - vs->sasl.encodedOffset += ret; - if (vs->sasl.encodedOffset == vs->sasl.encodedLength) { -- vs->output.offset = 0; -+ vs->output.offset -= vs->sasl.encodedRawLength; - vs->sasl.encoded = NULL; - vs->sasl.encodedOffset = vs->sasl.encodedLength = 0; - } -diff --git a/ui/vnc-auth-sasl.h b/ui/vnc-auth-sasl.h -index cb42745a6b..b9d8de1c10 100644 ---- a/ui/vnc-auth-sasl.h -+++ b/ui/vnc-auth-sasl.h -@@ -53,6 +53,7 @@ struct VncStateSASL { - */ - const uint8_t *encoded; - unsigned int encodedLength; -+ unsigned int encodedRawLength; - unsigned int encodedOffset; - char *username; - char *mechlist; --- -2.11.0 - - -From fef1bbadfb2c3027208eb3d14b43e1bdb51166ca Mon Sep 17 00:00:00 2001 -From: "Daniel P. Berrange" -Date: Mon, 18 Dec 2017 19:12:21 +0000 -Subject: [PATCH 07/14] ui: introduce enum to track VNC client framebuffer - update request state -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Currently the VNC servers tracks whether a client has requested an incremental -or forced update with two boolean flags. There are only really 3 distinct -states to track, so create an enum to more accurately reflect permitted states. - -Signed-off-by: Daniel P. Berrange -Reviewed-by: Darren Kenny -Reviewed-by: Marc-André Lureau -Message-id: 20171218191228.31018-7-berrange@redhat.com -Signed-off-by: Gerd Hoffmann ---- - ui/vnc.c | 21 +++++++++++---------- - ui/vnc.h | 9 +++++++-- - 2 files changed, 18 insertions(+), 12 deletions(-) - -diff --git a/ui/vnc.c b/ui/vnc.c -index a79848f083..30e2feeae3 100644 ---- a/ui/vnc.c -+++ b/ui/vnc.c -@@ -975,16 +975,17 @@ static int vnc_update_client(VncState *vs, int has_dirty) - } - - vs->has_dirty += has_dirty; -- if (!vs->need_update) { -+ if (vs->update == VNC_STATE_UPDATE_NONE) { - return 0; - } - -- if (vs->output.offset && !vs->audio_cap && !vs->force_update) { -+ if (vs->output.offset && !vs->audio_cap && -+ vs->update != VNC_STATE_UPDATE_FORCE) { - /* kernel send buffers are full -> drop frames to throttle */ - return 0; - } - -- if (!vs->has_dirty && !vs->force_update) { -+ if (!vs->has_dirty && vs->update != VNC_STATE_UPDATE_FORCE) { - return 0; - } - -@@ -1030,7 +1031,7 @@ static int vnc_update_client(VncState *vs, int has_dirty) - } - - vnc_job_push(job); -- vs->force_update = 0; -+ vs->update = VNC_STATE_UPDATE_INCREMENTAL; - vs->has_dirty = 0; - return n; - } -@@ -1869,14 +1870,14 @@ static void ext_key_event(VncState *vs, int down, - static void framebuffer_update_request(VncState *vs, int incremental, - int x, int y, int w, int h) - { -- vs->need_update = 1; -- - if (incremental) { -- return; -+ if (vs->update != VNC_STATE_UPDATE_FORCE) { -+ vs->update = VNC_STATE_UPDATE_INCREMENTAL; -+ } -+ } else { -+ vs->update = VNC_STATE_UPDATE_FORCE; -+ vnc_set_area_dirty(vs->dirty, vs->vd, x, y, w, h); - } -- -- vs->force_update = 1; -- vnc_set_area_dirty(vs->dirty, vs->vd, x, y, w, h); - } - - static void send_ext_key_event_ack(VncState *vs) -diff --git a/ui/vnc.h b/ui/vnc.h -index 694cf32ca9..b9d310e640 100644 ---- a/ui/vnc.h -+++ b/ui/vnc.h -@@ -252,6 +252,12 @@ struct VncJob - QTAILQ_ENTRY(VncJob) next; - }; - -+typedef enum { -+ VNC_STATE_UPDATE_NONE, -+ VNC_STATE_UPDATE_INCREMENTAL, -+ VNC_STATE_UPDATE_FORCE, -+} VncStateUpdate; -+ - struct VncState - { - QIOChannelSocket *sioc; /* The underlying socket */ -@@ -264,8 +270,7 @@ struct VncState - * vnc-jobs-async.c */ - - VncDisplay *vd; -- int need_update; -- int force_update; -+ VncStateUpdate update; /* Most recent pending request from client */ - int has_dirty; - uint32_t features; - int absolute; --- -2.11.0 - - -From 728a7ac95484a7ba5e624ccbac4c1326571576b0 Mon Sep 17 00:00:00 2001 -From: "Daniel P. Berrange" -Date: Mon, 18 Dec 2017 19:12:22 +0000 -Subject: [PATCH 08/14] ui: correctly reset framebuffer update state after - processing dirty regions -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -According to the RFB protocol, a client sends one or more framebuffer update -requests to the server. The server can reply with a single framebuffer update -response, that covers all previously received requests. Once the client has -read this update from the server, it may send further framebuffer update -requests to monitor future changes. The client is free to delay sending the -framebuffer update request if it needs to throttle the amount of data it is -reading from the server. - -The QEMU VNC server, however, has never correctly handled the framebuffer -update requests. Once QEMU has received an update request, it will continue to -send client updates forever, even if the client hasn't asked for further -updates. This prevents the client from throttling back data it gets from the -server. This change fixes the flawed logic such that after a set of updates are -sent out, QEMU waits for a further update request before sending more data. - -Signed-off-by: Daniel P. Berrange -Reviewed-by: Darren Kenny -Reviewed-by: Marc-André Lureau -Message-id: 20171218191228.31018-8-berrange@redhat.com -Signed-off-by: Gerd Hoffmann ---- - ui/vnc.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ui/vnc.c b/ui/vnc.c -index 30e2feeae3..243c72be13 100644 ---- a/ui/vnc.c -+++ b/ui/vnc.c -@@ -1031,7 +1031,7 @@ static int vnc_update_client(VncState *vs, int has_dirty) - } - - vnc_job_push(job); -- vs->update = VNC_STATE_UPDATE_INCREMENTAL; -+ vs->update = VNC_STATE_UPDATE_NONE; - vs->has_dirty = 0; - return n; - } --- -2.11.0 - - -From 0bad834228b9ee63e4239108d02dcb94568254d0 Mon Sep 17 00:00:00 2001 -From: "Daniel P. Berrange" -Date: Mon, 18 Dec 2017 19:12:23 +0000 -Subject: [PATCH 09/14] ui: refactor code for determining if an update should - be sent to the client -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The logic for determining if it is possible to send an update to the client -will become more complicated shortly, so pull it out into a separate method -for easier extension later. - -Signed-off-by: Daniel P. Berrange -Reviewed-by: Darren Kenny -Reviewed-by: Marc-André Lureau -Message-id: 20171218191228.31018-9-berrange@redhat.com -Signed-off-by: Gerd Hoffmann ---- - ui/vnc.c | 27 ++++++++++++++++++++------- - 1 file changed, 20 insertions(+), 7 deletions(-) - -diff --git a/ui/vnc.c b/ui/vnc.c -index 243c72be13..4ba7fc076a 100644 ---- a/ui/vnc.c -+++ b/ui/vnc.c -@@ -961,6 +961,25 @@ static int find_and_clear_dirty_height(VncState *vs, - return h; - } - -+static bool vnc_should_update(VncState *vs) -+{ -+ switch (vs->update) { -+ case VNC_STATE_UPDATE_NONE: -+ break; -+ case VNC_STATE_UPDATE_INCREMENTAL: -+ /* Only allow incremental updates if the output buffer -+ * is empty, or if audio capture is enabled. -+ */ -+ if (!vs->output.offset || vs->audio_cap) { -+ return true; -+ } -+ break; -+ case VNC_STATE_UPDATE_FORCE: -+ return true; -+ } -+ return false; -+} -+ - static int vnc_update_client(VncState *vs, int has_dirty) - { - VncDisplay *vd = vs->vd; -@@ -975,13 +994,7 @@ static int vnc_update_client(VncState *vs, int has_dirty) - } - - vs->has_dirty += has_dirty; -- if (vs->update == VNC_STATE_UPDATE_NONE) { -- return 0; -- } -- -- if (vs->output.offset && !vs->audio_cap && -- vs->update != VNC_STATE_UPDATE_FORCE) { -- /* kernel send buffers are full -> drop frames to throttle */ -+ if (!vnc_should_update(vs)) { - return 0; - } - --- -2.11.0 - - -From e2b72cb6e0443d90d7ab037858cb6834b6cca852 Mon Sep 17 00:00:00 2001 -From: "Daniel P. Berrange" -Date: Mon, 18 Dec 2017 19:12:24 +0000 -Subject: [PATCH 10/14] ui: fix VNC client throttling when audio capture is - active -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The VNC server must throttle data sent to the client to prevent the 'output' -buffer size growing without bound, if the client stops reading data off the -socket (either maliciously or due to stalled/slow network connection). - -The current throttling is very crude because it simply checks whether the -output buffer offset is zero. This check must be disabled if audio capture is -enabled, because when streaming audio the output buffer offset will rarely be -zero due to queued audio data, and so this would starve framebuffer updates. - -As a result, the VNC client can cause QEMU to allocate arbitrary amounts of RAM. -They can first start something in the guest that triggers lots of framebuffer -updates eg play a youtube video. Then enable audio capture, and simply never -read data back from the server. This can easily make QEMU's VNC server send -buffer consume 100MB of RAM per second, until the OOM killer starts reaping -processes (hopefully the rogue QEMU process, but it might pick others...). - -To address this we make the throttling more intelligent, so we can throttle -when audio capture is active too. To determine how to throttle incremental -updates or audio data, we calculate a size threshold. Normally the threshold is -the approximate number of bytes associated with a single complete framebuffer -update. ie width * height * bytes per pixel. We'll send incremental updates -until we hit this threshold, at which point we'll stop sending updates until -data has been written to the wire, causing the output buffer offset to fall -back below the threshold. - -If audio capture is enabled, we increase the size of the threshold to also -allow for upto 1 seconds worth of audio data samples. ie nchannels * bytes -per sample * frequency. This allows the output buffer to have a mixture of -incremental framebuffer updates and audio data queued, but once the threshold -is exceeded, audio data will be dropped and incremental updates will be -throttled. - -This unbounded memory growth affects all VNC server configurations supported by -QEMU, with no workaround possible. The mitigating factor is that it can only be -triggered by a client that has authenticated with the VNC server, and who is -able to trigger a large quantity of framebuffer updates or audio samples from -the guest OS. Mostly they'll just succeed in getting the OOM killer to kill -their own QEMU process, but its possible other processes can get taken out as -collateral damage. - -This is a more general variant of the similar unbounded memory usage flaw in -the websockets server, that was previously assigned CVE-2017-15268, and fixed -in 2.11 by: - - commit a7b20a8efa28e5f22c26c06cd06c2f12bc863493 - Author: Daniel P. Berrange - Date: Mon Oct 9 14:43:42 2017 +0100 - - io: monitor encoutput buffer size from websocket GSource - -This new general memory usage flaw has been assigned CVE-2017-15124, and is -partially fixed by this patch. - -Signed-off-by: Daniel P. Berrange -Reviewed-by: Darren Kenny -Reviewed-by: Marc-André Lureau -Message-id: 20171218191228.31018-10-berrange@redhat.com -Signed-off-by: Gerd Hoffmann ---- - ui/vnc.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- - ui/vnc.h | 6 ++++++ - 2 files changed, 70 insertions(+), 8 deletions(-) - -diff --git a/ui/vnc.c b/ui/vnc.c -index 4ba7fc076a..9e03cc7c01 100644 ---- a/ui/vnc.c -+++ b/ui/vnc.c -@@ -60,6 +60,7 @@ static QTAILQ_HEAD(, VncDisplay) vnc_displays = - - static int vnc_cursor_define(VncState *vs); - static void vnc_release_modifiers(VncState *vs); -+static void vnc_update_throttle_offset(VncState *vs); - - static void vnc_set_share_mode(VncState *vs, VncShareMode mode) - { -@@ -766,6 +767,7 @@ static void vnc_dpy_switch(DisplayChangeListener *dcl, - vnc_set_area_dirty(vs->dirty, vd, 0, 0, - vnc_width(vd), - vnc_height(vd)); -+ vnc_update_throttle_offset(vs); - } - } - -@@ -961,16 +963,67 @@ static int find_and_clear_dirty_height(VncState *vs, - return h; - } - -+/* -+ * Figure out how much pending data we should allow in the output -+ * buffer before we throttle incremental display updates, and/or -+ * drop audio samples. -+ * -+ * We allow for equiv of 1 full display's worth of FB updates, -+ * and 1 second of audio samples. If audio backlog was larger -+ * than that the client would already suffering awful audio -+ * glitches, so dropping samples is no worse really). -+ */ -+static void vnc_update_throttle_offset(VncState *vs) -+{ -+ size_t offset = -+ vs->client_width * vs->client_height * vs->client_pf.bytes_per_pixel; -+ -+ if (vs->audio_cap) { -+ int freq = vs->as.freq; -+ /* We don't limit freq when reading settings from client, so -+ * it could be upto MAX_INT in size. 48khz is a sensible -+ * upper bound for trustworthy clients */ -+ int bps; -+ if (freq > 48000) { -+ freq = 48000; -+ } -+ switch (vs->as.fmt) { -+ default: -+ case AUD_FMT_U8: -+ case AUD_FMT_S8: -+ bps = 1; -+ break; -+ case AUD_FMT_U16: -+ case AUD_FMT_S16: -+ bps = 2; -+ break; -+ case AUD_FMT_U32: -+ case AUD_FMT_S32: -+ bps = 4; -+ break; -+ } -+ offset += freq * bps * vs->as.nchannels; -+ } -+ -+ /* Put a floor of 1MB on offset, so that if we have a large pending -+ * buffer and the display is resized to a small size & back again -+ * we don't suddenly apply a tiny send limit -+ */ -+ offset = MAX(offset, 1024 * 1024); -+ -+ vs->throttle_output_offset = offset; -+} -+ - static bool vnc_should_update(VncState *vs) - { - switch (vs->update) { - case VNC_STATE_UPDATE_NONE: - break; - case VNC_STATE_UPDATE_INCREMENTAL: -- /* Only allow incremental updates if the output buffer -- * is empty, or if audio capture is enabled. -+ /* Only allow incremental updates if the pending send queue -+ * is less than the permitted threshold - */ -- if (!vs->output.offset || vs->audio_cap) { -+ if (vs->output.offset < vs->throttle_output_offset) { - return true; - } - break; -@@ -1084,11 +1137,13 @@ static void audio_capture(void *opaque, void *buf, int size) - VncState *vs = opaque; - - vnc_lock_output(vs); -- vnc_write_u8(vs, VNC_MSG_SERVER_QEMU); -- vnc_write_u8(vs, VNC_MSG_SERVER_QEMU_AUDIO); -- vnc_write_u16(vs, VNC_MSG_SERVER_QEMU_AUDIO_DATA); -- vnc_write_u32(vs, size); -- vnc_write(vs, buf, size); -+ if (vs->output.offset < vs->throttle_output_offset) { -+ vnc_write_u8(vs, VNC_MSG_SERVER_QEMU); -+ vnc_write_u8(vs, VNC_MSG_SERVER_QEMU_AUDIO); -+ vnc_write_u16(vs, VNC_MSG_SERVER_QEMU_AUDIO_DATA); -+ vnc_write_u32(vs, size); -+ vnc_write(vs, buf, size); -+ } - vnc_unlock_output(vs); - vnc_flush(vs); - } -@@ -2288,6 +2343,7 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len) - break; - } - -+ vnc_update_throttle_offset(vs); - vnc_read_when(vs, protocol_client_msg, 1); - return 0; - } -diff --git a/ui/vnc.h b/ui/vnc.h -index b9d310e640..8fe69595c6 100644 ---- a/ui/vnc.h -+++ b/ui/vnc.h -@@ -298,6 +298,12 @@ struct VncState - - VncClientInfo *info; - -+ /* We allow multiple incremental updates or audio capture -+ * samples to be queued in output buffer, provided the -+ * buffer size doesn't exceed this threshold. The value -+ * is calculating dynamically based on framebuffer size -+ * and audio sample settings in vnc_update_throttle_offset() */ -+ size_t throttle_output_offset; - Buffer output; - Buffer input; - /* current output mode information */ --- -2.11.0 - - -From ada8d2e4369ea49677d8672ac81bce73eefd5b54 Mon Sep 17 00:00:00 2001 -From: "Daniel P. Berrange" -Date: Mon, 18 Dec 2017 19:12:25 +0000 -Subject: [PATCH 11/14] ui: fix VNC client throttling when forced update is - requested -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The VNC server must throttle data sent to the client to prevent the 'output' -buffer size growing without bound, if the client stops reading data off the -socket (either maliciously or due to stalled/slow network connection). - -The current throttling is very crude because it simply checks whether the -output buffer offset is zero. This check is disabled if the client has requested -a forced update, because we want to send these as soon as possible. - -As a result, the VNC client can cause QEMU to allocate arbitrary amounts of RAM. -They can first start something in the guest that triggers lots of framebuffer -updates eg play a youtube video. Then repeatedly send full framebuffer update -requests, but never read data back from the server. This can easily make QEMU's -VNC server send buffer consume 100MB of RAM per second, until the OOM killer -starts reaping processes (hopefully the rogue QEMU process, but it might pick -others...). - -To address this we make the throttling more intelligent, so we can throttle -full updates. When we get a forced update request, we keep track of exactly how -much data we put on the output buffer. We will not process a subsequent forced -update request until this data has been fully sent on the wire. We always allow -one forced update request to be in flight, regardless of what data is queued -for incremental updates or audio data. The slight complication is that we do -not initially know how much data an update will send, as this is done in the -background by the VNC job thread. So we must track the fact that the job thread -has an update pending, and not process any further updates until this job is -has been completed & put data on the output buffer. - -This unbounded memory growth affects all VNC server configurations supported by -QEMU, with no workaround possible. The mitigating factor is that it can only be -triggered by a client that has authenticated with the VNC server, and who is -able to trigger a large quantity of framebuffer updates or audio samples from -the guest OS. Mostly they'll just succeed in getting the OOM killer to kill -their own QEMU process, but its possible other processes can get taken out as -collateral damage. - -This is a more general variant of the similar unbounded memory usage flaw in -the websockets server, that was previously assigned CVE-2017-15268, and fixed -in 2.11 by: - - commit a7b20a8efa28e5f22c26c06cd06c2f12bc863493 - Author: Daniel P. Berrange - Date: Mon Oct 9 14:43:42 2017 +0100 - - io: monitor encoutput buffer size from websocket GSource - -This new general memory usage flaw has been assigned CVE-2017-15124, and is -partially fixed by this patch. - -Signed-off-by: Daniel P. Berrange -Reviewed-by: Darren Kenny -Reviewed-by: Marc-André Lureau -Message-id: 20171218191228.31018-11-berrange@redhat.com -Signed-off-by: Gerd Hoffmann ---- - ui/vnc-auth-sasl.c | 5 +++++ - ui/vnc-jobs.c | 5 +++++ - ui/vnc.c | 28 ++++++++++++++++++++++++---- - ui/vnc.h | 7 +++++++ - 4 files changed, 41 insertions(+), 4 deletions(-) - -diff --git a/ui/vnc-auth-sasl.c b/ui/vnc-auth-sasl.c -index 761493b9b2..8c1cdde3db 100644 ---- a/ui/vnc-auth-sasl.c -+++ b/ui/vnc-auth-sasl.c -@@ -79,6 +79,11 @@ long vnc_client_write_sasl(VncState *vs) - - vs->sasl.encodedOffset += ret; - if (vs->sasl.encodedOffset == vs->sasl.encodedLength) { -+ if (vs->sasl.encodedRawLength >= vs->force_update_offset) { -+ vs->force_update_offset = 0; -+ } else { -+ vs->force_update_offset -= vs->sasl.encodedRawLength; -+ } - vs->output.offset -= vs->sasl.encodedRawLength; - vs->sasl.encoded = NULL; - vs->sasl.encodedOffset = vs->sasl.encodedLength = 0; -diff --git a/ui/vnc-jobs.c b/ui/vnc-jobs.c -index f7867771ae..e326679dd0 100644 ---- a/ui/vnc-jobs.c -+++ b/ui/vnc-jobs.c -@@ -152,6 +152,11 @@ void vnc_jobs_consume_buffer(VncState *vs) - vs->ioc, G_IO_IN | G_IO_OUT, vnc_client_io, vs, NULL); - } - buffer_move(&vs->output, &vs->jobs_buffer); -+ -+ if (vs->job_update == VNC_STATE_UPDATE_FORCE) { -+ vs->force_update_offset = vs->output.offset; -+ } -+ vs->job_update = VNC_STATE_UPDATE_NONE; - } - flush = vs->ioc != NULL && vs->abort != true; - vnc_unlock_output(vs); -diff --git a/ui/vnc.c b/ui/vnc.c -index 9e03cc7c01..4805ac41d0 100644 ---- a/ui/vnc.c -+++ b/ui/vnc.c -@@ -1021,14 +1021,28 @@ static bool vnc_should_update(VncState *vs) - break; - case VNC_STATE_UPDATE_INCREMENTAL: - /* Only allow incremental updates if the pending send queue -- * is less than the permitted threshold -+ * is less than the permitted threshold, and the job worker -+ * is completely idle. - */ -- if (vs->output.offset < vs->throttle_output_offset) { -+ if (vs->output.offset < vs->throttle_output_offset && -+ vs->job_update == VNC_STATE_UPDATE_NONE) { - return true; - } - break; - case VNC_STATE_UPDATE_FORCE: -- return true; -+ /* Only allow forced updates if the pending send queue -+ * does not contain a previous forced update, and the -+ * job worker is completely idle. -+ * -+ * Note this means we'll queue a forced update, even if -+ * the output buffer size is otherwise over the throttle -+ * output limit. -+ */ -+ if (vs->force_update_offset == 0 && -+ vs->job_update == VNC_STATE_UPDATE_NONE) { -+ return true; -+ } -+ break; - } - return false; - } -@@ -1096,8 +1110,9 @@ static int vnc_update_client(VncState *vs, int has_dirty) - } - } - -- vnc_job_push(job); -+ vs->job_update = vs->update; - vs->update = VNC_STATE_UPDATE_NONE; -+ vnc_job_push(job); - vs->has_dirty = 0; - return n; - } -@@ -1332,6 +1347,11 @@ static ssize_t vnc_client_write_plain(VncState *vs) - if (!ret) - return 0; - -+ if (ret >= vs->force_update_offset) { -+ vs->force_update_offset = 0; -+ } else { -+ vs->force_update_offset -= ret; -+ } - buffer_advance(&vs->output, ret); - - if (vs->output.offset == 0) { -diff --git a/ui/vnc.h b/ui/vnc.h -index 8fe69595c6..3f4cd4d93d 100644 ---- a/ui/vnc.h -+++ b/ui/vnc.h -@@ -271,6 +271,7 @@ struct VncState - - VncDisplay *vd; - VncStateUpdate update; /* Most recent pending request from client */ -+ VncStateUpdate job_update; /* Currently processed by job thread */ - int has_dirty; - uint32_t features; - int absolute; -@@ -298,6 +299,12 @@ struct VncState - - VncClientInfo *info; - -+ /* Job thread bottom half has put data for a forced update -+ * into the output buffer. This offset points to the end of -+ * the update data in the output buffer. This lets us determine -+ * when a force update is fully sent to the client, allowing -+ * us to process further forced updates. */ -+ size_t force_update_offset; - /* We allow multiple incremental updates or audio capture - * samples to be queued in output buffer, provided the - * buffer size doesn't exceed this threshold. The value --- -2.11.0 - - -From f887cf165db20f405cb8805c716bd363aaadf815 Mon Sep 17 00:00:00 2001 -From: "Daniel P. Berrange" -Date: Mon, 18 Dec 2017 19:12:26 +0000 -Subject: [PATCH 12/14] ui: place a hard cap on VNC server output buffer size -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The previous patches fix problems with throttling of forced framebuffer updates -and audio data capture that would cause the QEMU output buffer size to grow -without bound. Those fixes are graceful in that once the client catches up with -reading data from the server, everything continues operating normally. - -There is some data which the server sends to the client that is impractical to -throttle. Specifically there are various pseudo framebuffer update encodings to -inform the client of things like desktop resizes, pointer changes, audio -playback start/stop, LED state and so on. These generally only involve sending -a very small amount of data to the client, but a malicious guest might be able -to do things that trigger these changes at a very high rate. Throttling them is -not practical as missed or delayed events would cause broken behaviour for the -client. - -This patch thus takes a more forceful approach of setting an absolute upper -bound on the amount of data we permit to be present in the output buffer at -any time. The previous patch set a threshold for throttling the output buffer -by allowing an amount of data equivalent to one complete framebuffer update and -one seconds worth of audio data. On top of this it allowed for one further -forced framebuffer update to be queued. - -To be conservative, we thus take that throttling threshold and multiply it by -5 to form an absolute upper bound. If this bound is hit during vnc_write() we -forceably disconnect the client, refusing to queue further data. This limit is -high enough that it should never be hit unless a malicious client is trying to -exploit the sever, or the network is completely saturated preventing any sending -of data on the socket. - -This completes the fix for CVE-2017-15124 started in the previous patches. - -Signed-off-by: Daniel P. Berrange -Reviewed-by: Darren Kenny -Reviewed-by: Marc-André Lureau -Message-id: 20171218191228.31018-12-berrange@redhat.com -Signed-off-by: Gerd Hoffmann ---- - ui/vnc.c | 29 +++++++++++++++++++++++++++++ - 1 file changed, 29 insertions(+) - -diff --git a/ui/vnc.c b/ui/vnc.c -index 4805ac41d0..e53e84587a 100644 ---- a/ui/vnc.c -+++ b/ui/vnc.c -@@ -1521,8 +1521,37 @@ gboolean vnc_client_io(QIOChannel *ioc G_GNUC_UNUSED, - } - - -+/* -+ * Scale factor to apply to vs->throttle_output_offset when checking for -+ * hard limit. Worst case normal usage could be x2, if we have a complete -+ * incremental update and complete forced update in the output buffer. -+ * So x3 should be good enough, but we pick x5 to be conservative and thus -+ * (hopefully) never trigger incorrectly. -+ */ -+#define VNC_THROTTLE_OUTPUT_LIMIT_SCALE 5 -+ - void vnc_write(VncState *vs, const void *data, size_t len) - { -+ if (vs->disconnecting) { -+ return; -+ } -+ /* Protection against malicious client/guest to prevent our output -+ * buffer growing without bound if client stops reading data. This -+ * should rarely trigger, because we have earlier throttling code -+ * which stops issuing framebuffer updates and drops audio data -+ * if the throttle_output_offset value is exceeded. So we only reach -+ * this higher level if a huge number of pseudo-encodings get -+ * triggered while data can't be sent on the socket. -+ * -+ * NB throttle_output_offset can be zero during early protocol -+ * handshake, or from the job thread's VncState clone -+ */ -+ if (vs->throttle_output_offset != 0 && -+ vs->output.offset > (vs->throttle_output_offset * -+ VNC_THROTTLE_OUTPUT_LIMIT_SCALE)) { -+ vnc_disconnect_start(vs); -+ return; -+ } - buffer_reserve(&vs->output, len); - - if (vs->ioc != NULL && buffer_empty(&vs->output)) { --- -2.11.0 - - -From 6aa22a29187e1908f5db738d27c64a9efc8d0bfa Mon Sep 17 00:00:00 2001 -From: "Daniel P. Berrange" -Date: Mon, 18 Dec 2017 19:12:27 +0000 -Subject: [PATCH 13/14] ui: add trace events related to VNC client throttling -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The VNC client throttling is quite subtle so will benefit from having trace -points available for live debugging. - -Signed-off-by: Daniel P. Berrange -Reviewed-by: Darren Kenny -Reviewed-by: Marc-André Lureau -Message-id: 20171218191228.31018-13-berrange@redhat.com -Signed-off-by: Gerd Hoffmann ---- - ui/trace-events | 7 +++++++ - ui/vnc.c | 23 +++++++++++++++++++++++ - 2 files changed, 30 insertions(+) - -diff --git a/ui/trace-events b/ui/trace-events -index 1a9f126330..85f74f948b 100644 ---- a/ui/trace-events -+++ b/ui/trace-events -@@ -35,6 +35,13 @@ vnc_client_connect(void *state, void *ioc) "VNC client connect state=%p ioc=%p" - vnc_client_disconnect_start(void *state, void *ioc) "VNC client disconnect start state=%p ioc=%p" - vnc_client_disconnect_finish(void *state, void *ioc) "VNC client disconnect finish state=%p ioc=%p" - vnc_client_io_wrap(void *state, void *ioc, const char *type) "VNC client I/O wrap state=%p ioc=%p type=%s" -+vnc_client_throttle_threshold(void *state, void *ioc, size_t oldoffset, size_t offset, int client_width, int client_height, int bytes_per_pixel, void *audio_cap) "VNC client throttle threshold state=%p ioc=%p oldoffset=%zu newoffset=%zu width=%d height=%d bpp=%d audio=%p" -+vnc_client_throttle_incremental(void *state, void *ioc, int job_update, size_t offset) "VNC client throttle incremental state=%p ioc=%p job-update=%d offset=%zu" -+vnc_client_throttle_forced(void *state, void *ioc, int job_update, size_t offset) "VNC client throttle forced state=%p ioc=%p job-update=%d offset=%zu" -+vnc_client_throttle_audio(void *state, void *ioc, size_t offset) "VNC client throttle audio state=%p ioc=%p offset=%zu" -+vnc_client_unthrottle_forced(void *state, void *ioc) "VNC client unthrottle forced offset state=%p ioc=%p" -+vnc_client_unthrottle_incremental(void *state, void *ioc, size_t offset) "VNC client unthrottle incremental state=%p ioc=%p offset=%zu" -+vnc_client_output_limit(void *state, void *ioc, size_t offset, size_t threshold) "VNC client output limit state=%p ioc=%p offset=%zu threshold=%zu" - vnc_auth_init(void *display, int websock, int auth, int subauth) "VNC auth init state=%p websock=%d auth=%d subauth=%d" - vnc_auth_start(void *state, int method) "VNC client auth start state=%p method=%d" - vnc_auth_pass(void *state, int method) "VNC client auth passed state=%p method=%d" -diff --git a/ui/vnc.c b/ui/vnc.c -index e53e84587a..0a5e629d5d 100644 ---- a/ui/vnc.c -+++ b/ui/vnc.c -@@ -1011,6 +1011,12 @@ static void vnc_update_throttle_offset(VncState *vs) - */ - offset = MAX(offset, 1024 * 1024); - -+ if (vs->throttle_output_offset != offset) { -+ trace_vnc_client_throttle_threshold( -+ vs, vs->ioc, vs->throttle_output_offset, offset, vs->client_width, -+ vs->client_height, vs->client_pf.bytes_per_pixel, vs->audio_cap); -+ } -+ - vs->throttle_output_offset = offset; - } - -@@ -1028,6 +1034,8 @@ static bool vnc_should_update(VncState *vs) - vs->job_update == VNC_STATE_UPDATE_NONE) { - return true; - } -+ trace_vnc_client_throttle_incremental( -+ vs, vs->ioc, vs->job_update, vs->output.offset); - break; - case VNC_STATE_UPDATE_FORCE: - /* Only allow forced updates if the pending send queue -@@ -1042,6 +1050,8 @@ static bool vnc_should_update(VncState *vs) - vs->job_update == VNC_STATE_UPDATE_NONE) { - return true; - } -+ trace_vnc_client_throttle_forced( -+ vs, vs->ioc, vs->job_update, vs->force_update_offset); - break; - } - return false; -@@ -1158,6 +1168,8 @@ static void audio_capture(void *opaque, void *buf, int size) - vnc_write_u16(vs, VNC_MSG_SERVER_QEMU_AUDIO_DATA); - vnc_write_u32(vs, size); - vnc_write(vs, buf, size); -+ } else { -+ trace_vnc_client_throttle_audio(vs, vs->ioc, vs->output.offset); - } - vnc_unlock_output(vs); - vnc_flush(vs); -@@ -1328,6 +1340,7 @@ ssize_t vnc_client_write_buf(VncState *vs, const uint8_t *data, size_t datalen) - */ - static ssize_t vnc_client_write_plain(VncState *vs) - { -+ size_t offset; - ssize_t ret; - - #ifdef CONFIG_VNC_SASL -@@ -1348,11 +1361,19 @@ static ssize_t vnc_client_write_plain(VncState *vs) - return 0; - - if (ret >= vs->force_update_offset) { -+ if (vs->force_update_offset != 0) { -+ trace_vnc_client_unthrottle_forced(vs, vs->ioc); -+ } - vs->force_update_offset = 0; - } else { - vs->force_update_offset -= ret; - } -+ offset = vs->output.offset; - buffer_advance(&vs->output, ret); -+ if (offset >= vs->throttle_output_offset && -+ vs->output.offset < vs->throttle_output_offset) { -+ trace_vnc_client_unthrottle_incremental(vs, vs->ioc, vs->output.offset); -+ } - - if (vs->output.offset == 0) { - if (vs->ioc_tag) { -@@ -1549,6 +1570,8 @@ void vnc_write(VncState *vs, const void *data, size_t len) - if (vs->throttle_output_offset != 0 && - vs->output.offset > (vs->throttle_output_offset * - VNC_THROTTLE_OUTPUT_LIMIT_SCALE)) { -+ trace_vnc_client_output_limit(vs, vs->ioc, vs->output.offset, -+ vs->throttle_output_offset); - vnc_disconnect_start(vs); - return; - } --- -2.11.0 - - -From 30b80fd5269257f55203b7072c505b4ebaab5115 Mon Sep 17 00:00:00 2001 -From: "Daniel P. Berrange" -Date: Mon, 18 Dec 2017 19:12:28 +0000 -Subject: [PATCH 14/14] ui: mix misleading comments & return types of VNC I/O - helper methods -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -While the QIOChannel APIs for reading/writing data return ssize_t, with negative -value indicating an error, the VNC code passes this return value through the -vnc_client_io_error() method. This detects the error condition, disconnects the -client and returns 0 to indicate error. Thus all the VNC helper methods should -return size_t (unsigned), and misleading comments which refer to the possibility -of negative return values need fixing. - -Signed-off-by: Daniel P. Berrange -Reviewed-by: Darren Kenny -Reviewed-by: Marc-André Lureau -Message-id: 20171218191228.31018-14-berrange@redhat.com -Signed-off-by: Gerd Hoffmann ---- - ui/vnc-auth-sasl.c | 8 ++++---- - ui/vnc-auth-sasl.h | 4 ++-- - ui/vnc.c | 29 +++++++++++++++-------------- - ui/vnc.h | 6 +++--- - 4 files changed, 24 insertions(+), 23 deletions(-) - -diff --git a/ui/vnc-auth-sasl.c b/ui/vnc-auth-sasl.c -index 8c1cdde3db..74a5f513f2 100644 ---- a/ui/vnc-auth-sasl.c -+++ b/ui/vnc-auth-sasl.c -@@ -48,9 +48,9 @@ void vnc_sasl_client_cleanup(VncState *vs) - } - - --long vnc_client_write_sasl(VncState *vs) -+size_t vnc_client_write_sasl(VncState *vs) - { -- long ret; -+ size_t ret; - - VNC_DEBUG("Write SASL: Pending output %p size %zd offset %zd " - "Encoded: %p size %d offset %d\n", -@@ -106,9 +106,9 @@ long vnc_client_write_sasl(VncState *vs) - } - - --long vnc_client_read_sasl(VncState *vs) -+size_t vnc_client_read_sasl(VncState *vs) - { -- long ret; -+ size_t ret; - uint8_t encoded[4096]; - const char *decoded; - unsigned int decodedLen; -diff --git a/ui/vnc-auth-sasl.h b/ui/vnc-auth-sasl.h -index b9d8de1c10..2ae224ee3a 100644 ---- a/ui/vnc-auth-sasl.h -+++ b/ui/vnc-auth-sasl.h -@@ -65,8 +65,8 @@ struct VncDisplaySASL { - - void vnc_sasl_client_cleanup(VncState *vs); - --long vnc_client_read_sasl(VncState *vs); --long vnc_client_write_sasl(VncState *vs); -+size_t vnc_client_read_sasl(VncState *vs); -+size_t vnc_client_write_sasl(VncState *vs); - - void start_auth_sasl(VncState *vs); - -diff --git a/ui/vnc.c b/ui/vnc.c -index 0a5e629d5d..665a143578 100644 ---- a/ui/vnc.c -+++ b/ui/vnc.c -@@ -1272,7 +1272,7 @@ void vnc_disconnect_finish(VncState *vs) - g_free(vs); - } - --ssize_t vnc_client_io_error(VncState *vs, ssize_t ret, Error **errp) -+size_t vnc_client_io_error(VncState *vs, ssize_t ret, Error **errp) - { - if (ret <= 0) { - if (ret == 0) { -@@ -1315,9 +1315,9 @@ void vnc_client_error(VncState *vs) - * - * Returns the number of bytes written, which may be less than - * the requested 'datalen' if the socket would block. Returns -- * -1 on error, and disconnects the client socket. -+ * 0 on I/O error, and disconnects the client socket. - */ --ssize_t vnc_client_write_buf(VncState *vs, const uint8_t *data, size_t datalen) -+size_t vnc_client_write_buf(VncState *vs, const uint8_t *data, size_t datalen) - { - Error *err = NULL; - ssize_t ret; -@@ -1335,13 +1335,13 @@ ssize_t vnc_client_write_buf(VncState *vs, const uint8_t *data, size_t datalen) - * will switch the FD poll() handler back to read monitoring. - * - * Returns the number of bytes written, which may be less than -- * the buffered output data if the socket would block. Returns -- * -1 on error, and disconnects the client socket. -+ * the buffered output data if the socket would block. Returns -+ * 0 on I/O error, and disconnects the client socket. - */ --static ssize_t vnc_client_write_plain(VncState *vs) -+static size_t vnc_client_write_plain(VncState *vs) - { - size_t offset; -- ssize_t ret; -+ size_t ret; - - #ifdef CONFIG_VNC_SASL - VNC_DEBUG("Write Plain: Pending output %p size %zd offset %zd. Wait SSF %d\n", -@@ -1442,9 +1442,9 @@ void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting) - * - * Returns the number of bytes read, which may be less than - * the requested 'datalen' if the socket would block. Returns -- * -1 on error, and disconnects the client socket. -+ * 0 on I/O error or EOF, and disconnects the client socket. - */ --ssize_t vnc_client_read_buf(VncState *vs, uint8_t *data, size_t datalen) -+size_t vnc_client_read_buf(VncState *vs, uint8_t *data, size_t datalen) - { - ssize_t ret; - Error *err = NULL; -@@ -1460,12 +1460,13 @@ ssize_t vnc_client_read_buf(VncState *vs, uint8_t *data, size_t datalen) - * when not using any SASL SSF encryption layers. Will read as much - * data as possible without blocking. - * -- * Returns the number of bytes read. Returns -1 on error, and -- * disconnects the client socket. -+ * Returns the number of bytes read, which may be less than -+ * the requested 'datalen' if the socket would block. Returns -+ * 0 on I/O error or EOF, and disconnects the client socket. - */ --static ssize_t vnc_client_read_plain(VncState *vs) -+static size_t vnc_client_read_plain(VncState *vs) - { -- ssize_t ret; -+ size_t ret; - VNC_DEBUG("Read plain %p size %zd offset %zd\n", - vs->input.buffer, vs->input.capacity, vs->input.offset); - buffer_reserve(&vs->input, 4096); -@@ -1491,7 +1492,7 @@ static void vnc_jobs_bh(void *opaque) - */ - static int vnc_client_read(VncState *vs) - { -- ssize_t ret; -+ size_t ret; - - #ifdef CONFIG_VNC_SASL - if (vs->sasl.conn && vs->sasl.runSSF) -diff --git a/ui/vnc.h b/ui/vnc.h -index 3f4cd4d93d..0c33a5f7fe 100644 ---- a/ui/vnc.h -+++ b/ui/vnc.h -@@ -524,8 +524,8 @@ gboolean vnc_client_io(QIOChannel *ioc, - GIOCondition condition, - void *opaque); - --ssize_t vnc_client_read_buf(VncState *vs, uint8_t *data, size_t datalen); --ssize_t vnc_client_write_buf(VncState *vs, const uint8_t *data, size_t datalen); -+size_t vnc_client_read_buf(VncState *vs, uint8_t *data, size_t datalen); -+size_t vnc_client_write_buf(VncState *vs, const uint8_t *data, size_t datalen); - - /* Protocol I/O functions */ - void vnc_write(VncState *vs, const void *data, size_t len); -@@ -544,7 +544,7 @@ uint32_t read_u32(uint8_t *data, size_t offset); - - /* Protocol stage functions */ - void vnc_client_error(VncState *vs); --ssize_t vnc_client_io_error(VncState *vs, ssize_t ret, Error **errp); -+size_t vnc_client_io_error(VncState *vs, ssize_t ret, Error **errp); - - void start_client_init(VncState *vs); - void start_auth_vnc(VncState *vs); --- -2.11.0 diff --git a/meta/recipes-devtools/qemu/qemu_2.11.0.bb b/meta/recipes-devtools/qemu/qemu_2.11.0.bb deleted file mode 100644 index 10760dc2db..0000000000 --- a/meta/recipes-devtools/qemu/qemu_2.11.0.bb +++ /dev/null @@ -1,59 +0,0 @@ -require qemu.inc - -inherit ptest - -RDEPENDS_${PN}-ptest = "bash make" - -LIC_FILES_CHKSUM = "file://COPYING;md5=441c28d2cf86e15a37fa47e15a72fbac \ - file://COPYING.LIB;endline=24;md5=c04def7ae38850e7d3ef548588159913" - -SRC_URI = "http://wiki.qemu-project.org/download/${BP}.tar.bz2 \ - file://powerpc_rom.bin \ - file://disable-grabs.patch \ - file://wacom.patch \ - file://add-ptest-in-makefile-v10.patch \ - file://run-ptest \ - file://qemu-enlarge-env-entry-size.patch \ - file://no-valgrind.patch \ - file://pathlimit.patch \ - file://qemu-2.5.0-cflags.patch \ - file://glibc-2.25.patch \ - file://chardev-connect-socket-to-a-spawned-command.patch \ - file://apic-fixup-fallthrough-to-PIC.patch \ - file://linux-user-Fix-webkitgtk-hangs-on-32-bit-x86-target.patch \ - file://memfd.patch \ - file://CVE-2017-15124.patch \ - " -UPSTREAM_CHECK_REGEX = "qemu-(?P\d+\..*)\.tar" - - -SRC_URI_append_class-native = " \ - file://fix-libcap-header-issue-on-some-distro.patch \ - file://cpus.c-qemu_cpu_kick_thread_debugging.patch \ - " - -SRC_URI[md5sum] = "335994a755bc655e88a87aeb36bfc0b9" -SRC_URI[sha256sum] = "c4f034c7665a84a1c3be72c8da37f3c31ec063475699df062ab646d8b2e17fcb" - -COMPATIBLE_HOST_mipsarchn32 = "null" -COMPATIBLE_HOST_mipsarchn64 = "null" - -do_install_append() { - # Prevent QA warnings about installed ${localstatedir}/run - if [ -d ${D}${localstatedir}/run ]; then rmdir ${D}${localstatedir}/run; fi - install -Dm 0755 ${WORKDIR}/powerpc_rom.bin ${D}${datadir}/qemu -} - -do_compile_ptest() { - make buildtest-TESTS -} - -do_install_ptest() { - cp -rL ${B}/tests ${D}${PTEST_PATH} - find ${D}${PTEST_PATH}/tests -type f -name "*.[Sshcod]" | xargs -i rm -rf {} - - cp ${S}/tests/Makefile.include ${D}${PTEST_PATH}/tests - # Don't check the file genreated by configure - sed -i -e '/wildcard config-host.mak/d' \ - -e '$ {/endif/d}' ${D}${PTEST_PATH}/tests/Makefile.include -} diff --git a/meta/recipes-devtools/qemu/qemu_2.11.1.bb b/meta/recipes-devtools/qemu/qemu_2.11.1.bb new file mode 100644 index 0000000000..f0e20cc125 --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu_2.11.1.bb @@ -0,0 +1,58 @@ +require qemu.inc + +inherit ptest + +RDEPENDS_${PN}-ptest = "bash make" + +LIC_FILES_CHKSUM = "file://COPYING;md5=441c28d2cf86e15a37fa47e15a72fbac \ + file://COPYING.LIB;endline=24;md5=c04def7ae38850e7d3ef548588159913" + +SRC_URI = "http://wiki.qemu-project.org/download/${BP}.tar.bz2 \ + file://powerpc_rom.bin \ + file://disable-grabs.patch \ + file://wacom.patch \ + file://add-ptest-in-makefile-v10.patch \ + file://run-ptest \ + file://qemu-enlarge-env-entry-size.patch \ + file://no-valgrind.patch \ + file://pathlimit.patch \ + file://qemu-2.5.0-cflags.patch \ + file://glibc-2.25.patch \ + file://chardev-connect-socket-to-a-spawned-command.patch \ + file://apic-fixup-fallthrough-to-PIC.patch \ + file://linux-user-Fix-webkitgtk-hangs-on-32-bit-x86-target.patch \ + file://memfd.patch \ + " +UPSTREAM_CHECK_REGEX = "qemu-(?P\d+\..*)\.tar" + + +SRC_URI_append_class-native = " \ + file://fix-libcap-header-issue-on-some-distro.patch \ + file://cpus.c-qemu_cpu_kick_thread_debugging.patch \ + " + +SRC_URI[md5sum] = "61cf862b6007eba4ac98247776af2e27" +SRC_URI[sha256sum] = "d9df2213ceed32e91dab7bc9dd19c1af83f91ba72c7aeef7605dfaaf81732ccb" + +COMPATIBLE_HOST_mipsarchn32 = "null" +COMPATIBLE_HOST_mipsarchn64 = "null" + +do_install_append() { + # Prevent QA warnings about installed ${localstatedir}/run + if [ -d ${D}${localstatedir}/run ]; then rmdir ${D}${localstatedir}/run; fi + install -Dm 0755 ${WORKDIR}/powerpc_rom.bin ${D}${datadir}/qemu +} + +do_compile_ptest() { + make buildtest-TESTS +} + +do_install_ptest() { + cp -rL ${B}/tests ${D}${PTEST_PATH} + find ${D}${PTEST_PATH}/tests -type f -name "*.[Sshcod]" | xargs -i rm -rf {} + + cp ${S}/tests/Makefile.include ${D}${PTEST_PATH}/tests + # Don't check the file genreated by configure + sed -i -e '/wildcard config-host.mak/d' \ + -e '$ {/endif/d}' ${D}${PTEST_PATH}/tests/Makefile.include +} -- cgit 1.2.3-korg