|
|
9ae3a8 |
From 52fe55e2bf9df408ebe127a670ee698642d3fcb4 Mon Sep 17 00:00:00 2001
|
|
|
9ae3a8 |
From: "Daniel P. Berrange" <berrange@redhat.com>
|
|
|
9ae3a8 |
Date: Thu, 8 Feb 2018 17:50:38 +0100
|
|
|
9ae3a8 |
Subject: [PATCH 24/27] ui: place a hard cap on VNC server output buffer size
|
|
|
9ae3a8 |
MIME-Version: 1.0
|
|
|
9ae3a8 |
Content-Type: text/plain; charset=UTF-8
|
|
|
9ae3a8 |
Content-Transfer-Encoding: 8bit
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
RH-Author: Daniel P. Berrange <berrange@redhat.com>
|
|
|
9ae3a8 |
Message-id: <20180208175041.5634-25-berrange@redhat.com>
|
|
|
9ae3a8 |
Patchwork-id: 78957
|
|
|
9ae3a8 |
O-Subject: [RHEL-7.5 qemu-kvm PATCH v1 24/27] ui: place a hard cap on VNC server output buffer size
|
|
|
9ae3a8 |
Bugzilla: 1527405
|
|
|
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 |
The previous patches fix problems with throttling of forced framebuffer updates
|
|
|
9ae3a8 |
and audio data capture that would cause the QEMU output buffer size to grow
|
|
|
9ae3a8 |
without bound. Those fixes are graceful in that once the client catches up with
|
|
|
9ae3a8 |
reading data from the server, everything continues operating normally.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
There is some data which the server sends to the client that is impractical to
|
|
|
9ae3a8 |
throttle. Specifically there are various pseudo framebuffer update encodings to
|
|
|
9ae3a8 |
inform the client of things like desktop resizes, pointer changes, audio
|
|
|
9ae3a8 |
playback start/stop, LED state and so on. These generally only involve sending
|
|
|
9ae3a8 |
a very small amount of data to the client, but a malicious guest might be able
|
|
|
9ae3a8 |
to do things that trigger these changes at a very high rate. Throttling them is
|
|
|
9ae3a8 |
not practical as missed or delayed events would cause broken behaviour for the
|
|
|
9ae3a8 |
client.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
This patch thus takes a more forceful approach of setting an absolute upper
|
|
|
9ae3a8 |
bound on the amount of data we permit to be present in the output buffer at
|
|
|
9ae3a8 |
any time. The previous patch set a threshold for throttling the output buffer
|
|
|
9ae3a8 |
by allowing an amount of data equivalent to one complete framebuffer update and
|
|
|
9ae3a8 |
one seconds worth of audio data. On top of this it allowed for one further
|
|
|
9ae3a8 |
forced framebuffer update to be queued.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
To be conservative, we thus take that throttling threshold and multiply it by
|
|
|
9ae3a8 |
5 to form an absolute upper bound. If this bound is hit during vnc_write() we
|
|
|
9ae3a8 |
forceably disconnect the client, refusing to queue further data. This limit is
|
|
|
9ae3a8 |
high enough that it should never be hit unless a malicious client is trying to
|
|
|
9ae3a8 |
exploit the sever, or the network is completely saturated preventing any sending
|
|
|
9ae3a8 |
of data on the socket.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
This completes the fix for CVE-2017-15124 started in the previous patches.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
|
|
|
9ae3a8 |
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
|
|
|
9ae3a8 |
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
|
|
|
9ae3a8 |
Message-id: 20171218191228.31018-12-berrange@redhat.com
|
|
|
9ae3a8 |
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
|
|
9ae3a8 |
(cherry picked from commit f887cf165db20f405cb8805c716bd363aaadf815)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Conflicts:
|
|
|
9ae3a8 |
ui/vnc.c - context differences and no 'vs->disconnecting' flag.
|
|
|
9ae3a8 |
Using share_mode as a better check for the disconnecting state
|
|
|
9ae3a8 |
than csock == -1, because the worker thread calls vnc_write()
|
|
|
9ae3a8 |
with a fake VncState that has csock == -1.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
9ae3a8 |
---
|
|
|
9ae3a8 |
ui/vnc.c | 29 +++++++++++++++++++++++++++++
|
|
|
9ae3a8 |
1 file changed, 29 insertions(+)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
diff --git a/ui/vnc.c b/ui/vnc.c
|
|
|
9ae3a8 |
index 96b6caf..61fbec2 100644
|
|
|
9ae3a8 |
--- a/ui/vnc.c
|
|
|
9ae3a8 |
+++ b/ui/vnc.c
|
|
|
9ae3a8 |
@@ -1460,8 +1460,37 @@ void vnc_client_read(void *opaque)
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
+/*
|
|
|
9ae3a8 |
+ * Scale factor to apply to vs->throttle_output_offset when checking for
|
|
|
9ae3a8 |
+ * hard limit. Worst case normal usage could be x2, if we have a complete
|
|
|
9ae3a8 |
+ * incremental update and complete forced update in the output buffer.
|
|
|
9ae3a8 |
+ * So x3 should be good enough, but we pick x5 to be conservative and thus
|
|
|
9ae3a8 |
+ * (hopefully) never trigger incorrectly.
|
|
|
9ae3a8 |
+ */
|
|
|
9ae3a8 |
+#define VNC_THROTTLE_OUTPUT_LIMIT_SCALE 5
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
void vnc_write(VncState *vs, const void *data, size_t len)
|
|
|
9ae3a8 |
{
|
|
|
9ae3a8 |
+ if (vs->share_mode == VNC_SHARE_MODE_DISCONNECTED) {
|
|
|
9ae3a8 |
+ return;
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
+ /* Protection against malicious client/guest to prevent our output
|
|
|
9ae3a8 |
+ * buffer growing without bound if client stops reading data. This
|
|
|
9ae3a8 |
+ * should rarely trigger, because we have earlier throttling code
|
|
|
9ae3a8 |
+ * which stops issuing framebuffer updates and drops audio data
|
|
|
9ae3a8 |
+ * if the throttle_output_offset value is exceeded. So we only reach
|
|
|
9ae3a8 |
+ * this higher level if a huge number of pseudo-encodings get
|
|
|
9ae3a8 |
+ * triggered while data can't be sent on the socket.
|
|
|
9ae3a8 |
+ *
|
|
|
9ae3a8 |
+ * NB throttle_output_offset can be zero during early protocol
|
|
|
9ae3a8 |
+ * handshake, or from the job thread's VncState clone
|
|
|
9ae3a8 |
+ */
|
|
|
9ae3a8 |
+ if (vs->throttle_output_offset != 0 &&
|
|
|
9ae3a8 |
+ vs->output.offset > (vs->throttle_output_offset *
|
|
|
9ae3a8 |
+ VNC_THROTTLE_OUTPUT_LIMIT_SCALE)) {
|
|
|
9ae3a8 |
+ vnc_disconnect_start(vs);
|
|
|
9ae3a8 |
+ return;
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
buffer_reserve(&vs->output, len);
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
if (vs->csock != -1 && buffer_empty(&vs->output)) {
|
|
|
9ae3a8 |
--
|
|
|
9ae3a8 |
1.8.3.1
|
|
|
9ae3a8 |
|