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 <[email protected]> --- 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 e8146d0..525e2d7 100644 --- a/ui/vnc-ws.c +++ b/ui/vnc-ws.c @@ -81,8 +81,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) { @@ -99,6 +102,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); } } -- 2.1.0
