Blame SOURCES/kvm-ui-place-a-hard-cap-on-VNC-server-output-buffer-size.patch

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