|
|
9ae3a8 |
From 0ee28ebbde0313e54b0c8e0f316aa75f97c87169 Mon Sep 17 00:00:00 2001
|
|
|
9ae3a8 |
From: "Daniel P. Berrange" <berrange@redhat.com>
|
|
|
9ae3a8 |
Date: Thu, 8 Feb 2018 17:50:41 +0100
|
|
|
9ae3a8 |
Subject: [PATCH 27/27] io: skip updates to client if websocket output buffer
|
|
|
9ae3a8 |
is non-zero
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
RH-Author: Daniel P. Berrange <berrange@redhat.com>
|
|
|
9ae3a8 |
Message-id: <20180208175041.5634-28-berrange@redhat.com>
|
|
|
9ae3a8 |
Patchwork-id: 78959
|
|
|
9ae3a8 |
O-Subject: [RHEL-7.5 qemu-kvm PATCH v1 27/27] io: skip updates to client if websocket output buffer is non-zero
|
|
|
9ae3a8 |
Bugzilla: 1518711
|
|
|
9ae3a8 |
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
|
|
9ae3a8 |
RH-Acked-by: Gerd Hoffmann <kraxel@redhat.com>
|
|
|
9ae3a8 |
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
From: "Daniel P. Berrange" <berrange@redhat.com>
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
When getting a framebuffer update from the guest, we first check
|
|
|
9ae3a8 |
to see if there's still any queued data in the VNC send buffer.
|
|
|
9ae3a8 |
If there is, we skip the update so that we avoid having the send
|
|
|
9ae3a8 |
buffer grow without bound. Unfortunately, the code is only
|
|
|
9ae3a8 |
monitoring the normal send buffer, and not the websockets send
|
|
|
9ae3a8 |
buffer which is separate.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
This flaw causes the websockets send buffer to grow without bound
|
|
|
9ae3a8 |
if the other end of the underlying data channel doesn't
|
|
|
9ae3a8 |
read data being sent. This can be seen with VNC if a client
|
|
|
9ae3a8 |
is on a slow WAN link and the guest OS is sending many screen
|
|
|
9ae3a8 |
updates. A malicious VNC client can act like it is on a slow
|
|
|
9ae3a8 |
link by playing a video in the guest and then reading data
|
|
|
9ae3a8 |
very slowly, causing QEMU host memory to expand arbitrarily.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
This issue is assigned CVE-2017-15268, publically reported in
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
https://bugs.launchpad.net/qemu/+bug/1718964
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Reviewed-by: Eric Blake <eblake@redhat.com>
|
|
|
9ae3a8 |
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
The corresponding upstream fix is present in commit
|
|
|
9ae3a8 |
a7b20a8efa28e5f22c26c06cd06c2f12bc863493, however, this
|
|
|
9ae3a8 |
patch is a complete re-implementation since the upstream
|
|
|
9ae3a8 |
code for websockets is completely different to that in
|
|
|
9ae3a8 |
QEMU 1.5.3. As such ignore the Reviewed-by tag above.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
9ae3a8 |
---
|
|
|
9ae3a8 |
ui/vnc-ws.c | 10 ++++++++--
|
|
|
9ae3a8 |
ui/vnc.c | 3 +++
|
|
|
9ae3a8 |
2 files changed, 11 insertions(+), 2 deletions(-)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
diff --git a/ui/vnc-ws.c b/ui/vnc-ws.c
|
|
|
9ae3a8 |
index 7133be9..fbfadde 100644
|
|
|
9ae3a8 |
--- a/ui/vnc-ws.c
|
|
|
9ae3a8 |
+++ b/ui/vnc-ws.c
|
|
|
9ae3a8 |
@@ -173,8 +173,13 @@ long vnc_client_write_ws(VncState *vs)
|
|
|
9ae3a8 |
long ret;
|
|
|
9ae3a8 |
VNC_DEBUG("Write WS: Pending output %p size %zd offset %zd\n",
|
|
|
9ae3a8 |
vs->output.buffer, vs->output.capacity, vs->output.offset);
|
|
|
9ae3a8 |
- vncws_encode_frame(&vs->ws_output, vs->output.buffer, vs->output.offset);
|
|
|
9ae3a8 |
- buffer_reset(&vs->output);
|
|
|
9ae3a8 |
+ /* We don't consume more from 'output' unless we've finished
|
|
|
9ae3a8 |
+ * sending the previous websockets frame. This ensures that
|
|
|
9ae3a8 |
+ * we still correctly throttle forced framebuffer updates */
|
|
|
9ae3a8 |
+ if (vs->ws_output.offset == 0) {
|
|
|
9ae3a8 |
+ vncws_encode_frame(&vs->ws_output, vs->output.buffer, vs->output.offset);
|
|
|
9ae3a8 |
+ buffer_reset(&vs->output);
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
ret = vnc_client_write_buf(vs, vs->ws_output.buffer, vs->ws_output.offset);
|
|
|
9ae3a8 |
if (!ret) {
|
|
|
9ae3a8 |
return 0;
|
|
|
9ae3a8 |
@@ -183,6 +188,7 @@ long vnc_client_write_ws(VncState *vs)
|
|
|
9ae3a8 |
buffer_advance(&vs->ws_output, ret);
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
if (vs->ws_output.offset == 0) {
|
|
|
9ae3a8 |
+ vs->force_update_offset = 0;
|
|
|
9ae3a8 |
qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
diff --git a/ui/vnc.c b/ui/vnc.c
|
|
|
9ae3a8 |
index 2be87b8..99b1ab1 100644
|
|
|
9ae3a8 |
--- a/ui/vnc.c
|
|
|
9ae3a8 |
+++ b/ui/vnc.c
|
|
|
9ae3a8 |
@@ -915,6 +915,9 @@ static bool vnc_should_update(VncState *vs)
|
|
|
9ae3a8 |
* is completely idle.
|
|
|
9ae3a8 |
*/
|
|
|
9ae3a8 |
if (vs->output.offset < vs->throttle_output_offset &&
|
|
|
9ae3a8 |
+#ifdef CONFIG_VNC_WS
|
|
|
9ae3a8 |
+ vs->ws_output.offset < vs->throttle_output_offset &&
|
|
|
9ae3a8 |
+#endif
|
|
|
9ae3a8 |
vs->job_update == VNC_STATE_UPDATE_NONE) {
|
|
|
9ae3a8 |
return true;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
--
|
|
|
9ae3a8 |
1.8.3.1
|
|
|
9ae3a8 |
|