chardev: disallow TLS/telnet/websocket with tcp_chr_wait_connected
In the previous commit
commit 1dc8a6695c
Author: Marc-André Lureau <marcandre.lureau@redhat.com>
Date: Tue Aug 16 12:33:32 2016 +0400
char: fix waiting for TLS and telnet connection
the tcp_chr_wait_connected() method was changed to check for a non-NULL
's->ioc' as a sign that there is already a connection present, as
opposed to checking the "connected" flag to supposedly fix handling of
TLS/telnet connections.
The original code would repeatedly call tcp_chr_wait_connected creating
many connections as 'connected' would never become true. The changed
code would still repeatedly call tcp_chr_wait_connected busy waiting
because s->ioc is set but the chardev will never see CHR_EVENT_OPENED.
IOW, the code is still broken with TLS/telnet, but in a different way.
Checking for a non-NULL 's->ioc' does not mean that a CHR_EVENT_OPENED
will be ready for a TLS/telnet connection. These protocols (and the
websocket protocol) all require the main loop to be running in order
to complete the protocol handshake before emitting CHR_EVENT_OPENED.
The tcp_chr_wait_connected() method is only used during early startup
before a main loop is running, so TLS/telnet/websock connections can
never complete initialization.
Making this work would require changing tcp_chr_wait_connected to run
a main loop. This is quite complex since we must not allow GSource's
that other parts of QEMU have registered to run yet. The current callers
of tcp_chr_wait_connected do not require use of the TLS/telnet/websocket
protocols, so the simplest option is to just forbid this combination
completely for now.
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Message-Id: <20190211182442.8542-14-berrange@redhat.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This commit is contained in:
parent
25d93b6a11
commit
d1885e549d
@ -951,8 +951,20 @@ static void tcp_chr_accept_server_sync(Chardev *chr)
|
|||||||
static int tcp_chr_wait_connected(Chardev *chr, Error **errp)
|
static int tcp_chr_wait_connected(Chardev *chr, Error **errp)
|
||||||
{
|
{
|
||||||
SocketChardev *s = SOCKET_CHARDEV(chr);
|
SocketChardev *s = SOCKET_CHARDEV(chr);
|
||||||
/* It can't wait on s->connected, since it is set asynchronously
|
const char *opts[] = { "telnet", "tn3270", "websock", "tls-creds" };
|
||||||
* in TLS and telnet cases, only wait for an accepted socket */
|
bool optset[] = { s->is_telnet, s->is_tn3270, s->is_websock, s->tls_creds };
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
QEMU_BUILD_BUG_ON(G_N_ELEMENTS(opts) != G_N_ELEMENTS(optset));
|
||||||
|
for (i = 0; i < G_N_ELEMENTS(opts); i++) {
|
||||||
|
if (optset[i]) {
|
||||||
|
error_setg(errp,
|
||||||
|
"'%s' option is incompatible with waiting for "
|
||||||
|
"connection completion", opts[i]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while (!s->ioc) {
|
while (!s->ioc) {
|
||||||
if (s->is_listen) {
|
if (s->is_listen) {
|
||||||
tcp_chr_accept_server_sync(chr);
|
tcp_chr_accept_server_sync(chr);
|
||||||
|
Loading…
Reference in New Issue
Block a user