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