char: don't skip client cleanup if 'connected' flag is unset
PATCH v2 1/1 char: don't skip client cleanup if 'connected' flag is unset
The tcp_chr_free_connection & tcp_chr_disconnect methods both skip all of their cleanup work unless the 's->connected' flag is set. This flag is set when the incoming client connection is ready to use. Crucially this is *after* the TLS handshake has been completed. So if the TLS handshake fails and we try to cleanup the failed client, all the cleanup is skipped as 's->connected' is still false.
The only important thing that should be skipped in this case is sending of the CHR_EVENT_CLOSED, because we never got as far as sending the corresponding CHR_EVENT_OPENED. Every other bit of cleanup can be robust against being called even when s->connected is false.
---
Changed in v2:
- Remove conditional checks for NULL (Marc-André)
- Don't use camelCase variable name (Marc-André)
chardev/char-socket.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-)
chardev/char-socket.c +9 -10
@@ -332,10 +332,6 @@ static void tcp_chr_free_connection(Chardev *chr)SocketChardev *s =SOCKET_CHARDEV (chr);int i; -if (!s->connected) { -return ; - } -if (s->read_msgfds_num) {for (i =0 ; i < s->read_msgfds_num; i++) {close (s->read_msgfds[i]);
@@ -394,22 +390,25 @@ static void update_disconnected_filename(SocketChardev *s) s->is_listen, s->is_telnet); } +/* NB may be called even if tcp_chr_connect has not been +* reached, due to TLS or telnet initialization failure, +* so can *not* assume s->connected == true +*/ static void tcp_chr_disconnect (Chardev *chr) {SocketChardev *s =SOCKET_CHARDEV (chr); - -if (!s->connected) { -return ; - } +bool emit_close = s->connected;tcp_chr_free_connection (chr); -if (s->listen_ioc) { +if (s->listen_ioc && s->listen_tag ==0 ) { s->listen_tag =qio_channel_add_watch (QIO_CHANNEL (s->listen_ioc),G_IO_IN , tcp_chr_accept, chr,NULL ); }update_disconnected_filename (s); -qemu_chr_be_event (chr,CHR_EVENT_CLOSED ); +if (emit_close) { +qemu_chr_be_event (chr,CHR_EVENT_CLOSED ); + }if (s->reconnect_time) {qemu_chr_socket_restart_timer (chr); }
Signature · 1 line
2.13.5
Quoted 14 lines · Daniel P. Berrange
The
tcp_chr_free_connection&tcp_chr_disconnectmethods both skip all of their cleanup work unless the 's->connected' flag is set. This flag is set when the incoming client connection is ready to use. Crucially this is *after* the TLS handshake has been completed. So if the TLS handshake fails and we try to cleanup the failed client, all the cleanup is skipped as 's->connected' is still false.The only important thing that should be skipped in this case is sending of the
CHR_EVENT_CLOSED, because we never got as far as sending the correspondingCHR_EVENT_OPENED. Every other bit of cleanup can be robust against being called even whens->connectedis false.
Quoted 7 lines
Signed-off-by Daniel P. Berrange <[email protected]>---
Changed in v2:
- Remove conditional checks for NULL (Marc-André)
- Don't use camelCase variable name (Marc-André)
Signature · 3 lines
Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org
Quoted 8 lines · Daniel P. Berrange
The
tcp_chr_free_connection&tcp_chr_disconnectmethods both skip all of their cleanup work unless the 's->connected' flag is set. This flag is set when the incoming client connection is ready to use. Crucially this is *after* the TLS handshake has been completed. So if the TLS handshake fails and we try to cleanup the failed client, all the cleanup is skipped as 's->connected' is still false.
Quoted 7 lines
The only important thing that should be skipped in this case is sending of the
CHR_EVENT_CLOSED, because we never got as far as sending the correspondingCHR_EVENT_OPENED. Every other bit of cleanup can be robust against being called even whens->connectedis false.Signed-off-by Daniel P. Berrange <[email protected]>
Quoted 61 lines
---
Changed in v2:
- Remove conditional checks for NULL (Marc-André)
- Don't use camelCase variable name (Marc-André)chardev/char-socket.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-)chardev/char-socket.c +9
-11@@ -332,10 +332,6 @@ static void tcp_chr_free_connection(Chardev *chr)SocketChardev *s =SOCKET_CHARDEV (chr);int i; -if (!s->connected) { -return ; - } -if (s->read_msgfds_num) {for (i =0 ; i < s->read_msgfds_num; i++) {close (s->read_msgfds[i]);@@ -394,22 +390,25 @@ static void update_disconnected_filename(SocketChardev *s) s->is_listen, s->is_telnet); } +/* NB may be called even if tcp_chr_connect has not been +* reached, due to TLS or telnet initialization failure, +* so can *not* assume s->connected == true +*/ static void tcp_chr_disconnect (Chardev *chr) {SocketChardev *s =SOCKET_CHARDEV (chr); - -if (!s->connected) { -return ; - } +bool emit_close = s->connected;tcp_chr_free_connection (chr); -if (s->listen_ioc) { +if (s->listen_ioc && s->listen_tag ==0 ) { s->listen_tag =qio_channel_add_watch (QIO_CHANNEL (s->listen_ioc),G_IO_IN , tcp_chr_accept, chr,NULL ); }update_disconnected_filename (s); -qemu_chr_be_event (chr,CHR_EVENT_CLOSED ); +if (emit_close) { +qemu_chr_be_event (chr,CHR_EVENT_CLOSED ); + }if (s->reconnect_time) {qemu_chr_socket_restart_timer (chr); } --2.13.5
Signature · 1 line
Marc-André Lureau
Paolo Bonzini
AppliedQuoted 63 lines · Daniel P. Berrange
The
tcp_chr_free_connection&tcp_chr_disconnectmethods both skip all of their cleanup work unless the 's->connected' flag is set. This flag is set when the incoming client connection is ready to use. Crucially this is *after* the TLS handshake has been completed. So if the TLS handshake fails and we try to cleanup the failed client, all the cleanup is skipped as 's->connected' is still false.The only important thing that should be skipped in this case is sending of the
CHR_EVENT_CLOSED, because we never got as far as sending the correspondingCHR_EVENT_OPENED. Every other bit of cleanup can be robust against being called even whens->connectedis false.Signed-off-by Daniel P. Berrange <[email protected]>---
Changed in v2:
- Remove conditional checks for NULL (Marc-André)
- Don't use camelCase variable name (Marc-André)chardev/char-socket.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-)chardev/char-socket.c +6
-9@@ -332,10 +332,6 @@ static void tcp_chr_free_connection(Chardev *chr)SocketChardev *s =SOCKET_CHARDEV (chr);int i; -if (!s->connected) { -return ; - } -if (s->read_msgfds_num) {for (i =0 ; i < s->read_msgfds_num; i++) {close (s->read_msgfds[i]);@@ -394,22 +390,25 @@ static void update_disconnected_filename(SocketChardev *s) s->is_listen, s->is_telnet); } +/* NB may be called even if tcp_chr_connect has not been +* reached, due to TLS or telnet initialization failure, +* so can *not* assume s->connected == true +*/ static void tcp_chr_disconnect (Chardev *chr) {SocketChardev *s =SOCKET_CHARDEV (chr); - -if (!s->connected) { -return ; - } +bool emit_close = s->connected;tcp_chr_free_connection (chr); -if (s->listen_ioc) { +if (s->listen_ioc && s->listen_tag ==0 ) { s->listen_tag = qio_channel_add_watch(
chardev/char-socket.c static void update_disconnected_filename(SocketChardev *s) · line 414
Quoted 10 lines
chardev/char-socket.c +3
-1QIO_CHANNEL(s->listen_ioc), G_IO_IN, tcp_chr_accept, chr, NULL); }update_disconnected_filename (s); -qemu_chr_be_event (chr,CHR_EVENT_CLOSED ); +if (emit_close) { +qemu_chr_be_event (chr,CHR_EVENT_CLOSED ); + }if (s->reconnect_time) {qemu_chr_socket_restart_timer (chr); }
Queued, thanks.
Paolo