05bba0
From 62121d1bd1f17f5b9822b98f4ee2c9fd159b50e5 Mon Sep 17 00:00:00 2001
605027
From: Gerd Hoffmann <kraxel@redhat.com>
05bba0
Date: Wed, 20 May 2015 08:39:09 +0200
05bba0
Subject: [PATCH 2/6] CVE-2015-1779: limit size of HTTP headers from websockets
605027
 clients
605027
05bba0
Message-id: <1432111149-11644-3-git-send-email-kraxel@redhat.com>
05bba0
Patchwork-id: 65097
05bba0
O-Subject: [RHEL-7.2 qemu-kvm PATCH 2/2] CVE-2015-1779: limit size of HTTP headers from websockets clients
05bba0
Bugzilla: 1206497
605027
RH-Acked-by: Thomas Huth <thuth@redhat.com>
605027
RH-Acked-by: Petr Matousek <pmatouse@redhat.com>
05bba0
RH-Acked-by: Daniel P. Berrange <berrange@redhat.com>
605027
605027
From: "Daniel P. Berrange" <berrange@redhat.com>
605027
605027
The VNC server websockets decoder will read and buffer data from
605027
websockets clients until it sees the end of the HTTP headers,
605027
as indicated by \r\n\r\n. In theory this allows a malicious to
605027
trick QEMU into consuming an arbitrary amount of RAM. In practice,
605027
because QEMU runs g_strstr_len() across the buffered header data,
605027
it will spend increasingly long burning CPU time searching for
605027
the substring match and less & less time reading data. So while
605027
this does cause arbitrary memory growth, the bigger problem is
605027
that QEMU will be burning 100% of available CPU time.
605027
605027
A novnc websockets client typically sends headers of around
605027
512 bytes in length. As such it is reasonable to place a 4096
605027
byte limit on the amount of data buffered while searching for
605027
the end of HTTP headers.
605027
605027
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
605027
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
605027
(cherry picked from commit 2cdb5e142fb93e875fa53c52864ef5eb8d5d8b41)
605027
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
605027
---
605027
 ui/vnc-ws.c | 10 ++++++++--
605027
 1 file changed, 8 insertions(+), 2 deletions(-)
605027
605027
diff --git a/ui/vnc-ws.c b/ui/vnc-ws.c
605027
index a7d457c..7133be9 100644
605027
--- a/ui/vnc-ws.c
605027
+++ b/ui/vnc-ws.c
605027
@@ -88,8 +88,11 @@ void vncws_handshake_read(void *opaque)
605027
     VncState *vs = opaque;
605027
     uint8_t *handshake_end;
605027
     long ret;
605027
-    buffer_reserve(&vs->ws_input, 4096);
605027
-    ret = vnc_client_read_buf(vs, buffer_end(&vs->ws_input), 4096);
605027
+    /* Typical HTTP headers from novnc are 512 bytes, so limiting
605027
+     * total header size to 4096 is easily enough. */
605027
+    size_t want = 4096 - vs->ws_input.offset;
605027
+    buffer_reserve(&vs->ws_input, want);
605027
+    ret = vnc_client_read_buf(vs, buffer_end(&vs->ws_input), want);
605027
 
605027
     if (!ret) {
605027
         if (vs->csock == -1) {
605027
@@ -106,6 +109,9 @@ void vncws_handshake_read(void *opaque)
605027
         vncws_process_handshake(vs, vs->ws_input.buffer, vs->ws_input.offset);
605027
         buffer_advance(&vs->ws_input, handshake_end - vs->ws_input.buffer +
605027
                 strlen(WS_HANDSHAKE_END));
605027
+    } else if (vs->ws_input.offset >= 4096) {
605027
+        VNC_DEBUG("End of headers not found in first 4096 bytes\n");
605027
+        vnc_client_error(vs);
605027
     }
605027
 }
605027
 
605027
-- 
605027
1.8.3.1
605027