A client which can reach a VNC websocket port crashes QEMU before it has authenticated, by sending an HTTP greeting whose request line holds no space:
printf 'stats\r\nx\r\n\r\n' | nc $host $port Three defects line up to produce it. The greeting is rejected without queueing a response, so the handshake goes on to flush an empty buffer. A zero length sendmsg() succeeds and returns 0, which qio_channel_socket_writev() mistakes for failure and reports as QIO_CHANNEL_ERR_BLOCK with errp left unset. The handshake treats every negative return as fatal and hands that NULL Error to error_get_pretty(). Patches 1 to 3 close the three links. Patch 5 is the same NULL Error on the read side of the handshake, where ERR_BLOCK is folded into -1. It is reachable for a wss:// client, whose master channel is then a TLS channel: a wakeup carrying only part of a record makes gnutls report EAGAIN. The tests drive the handshake through a channel which reports ERR_BLOCK on demand, covering both directions. No test reproduces the original crash itself, which turns on a stale errno and is not reliably reproducible in a unit test. What they pin is that a 400 is emitted and that ERR_BLOCK no longer reaches error_get_pretty(). Signed-off-by: Denis V. Lunev <[email protected]> CC: Daniel P. Berrangé <[email protected]> CC: Marc-André Lureau <[email protected]> Denis V. Lunev (6): io/channel-socket: do not treat a zero length write as an error io/channel-websock: send an HTTP 400 when the greeting has no space io/channel-websock: handle a blocked write during the handshake tests/unit: add websock handshake test io/channel-websock: do not lose QIO_CHANNEL_ERR_BLOCK while reading tests/unit: cover blocked IO during the websock handshake io/channel-socket.c | 2 +- io/channel-websock.c | 10 +- tests/unit/meson.build | 1 + tests/unit/test-io-channel-websock.c | 249 +++++++++++++++++++++++++++ 4 files changed, 260 insertions(+), 2 deletions(-) create mode 100644 tests/unit/test-io-channel-websock.c -- 2.53.0
