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

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