54 lines
2.4 KiB
Diff
54 lines
2.4 KiB
Diff
|
References: bsc#962632 CVE-2015-1779
|
||
|
|
||
|
Subject: CVE-2015-1779: limit size of HTTP headers from websockets clients
|
||
|
From: Daniel P. Berrange berrange@redhat.com Mon Mar 23 22:58:22 2015 +0000
|
||
|
Date: Wed Apr 1 17:12:55 2015 +0200:
|
||
|
Git: 2cdb5e142fb93e875fa53c52864ef5eb8d5d8b41
|
||
|
|
||
|
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>
|
||
|
|
||
|
Index: xen-4.6.0-testing/tools/qemu-xen-dir-remote/ui/vnc-ws.c
|
||
|
===================================================================
|
||
|
--- xen-4.6.0-testing.orig/tools/qemu-xen-dir-remote/ui/vnc-ws.c
|
||
|
+++ xen-4.6.0-testing/tools/qemu-xen-dir-remote/ui/vnc-ws.c
|
||
|
@@ -89,8 +89,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) {
|
||
|
@@ -107,6 +110,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);
|
||
|
}
|
||
|
}
|
||
|
|