038b4217 | 18-Mar-2024 |
Daniel P. Berrangé <berrange@redhat.com> |
Revert "chardev: use a child source for qio input source"
This reverts commit a7077b8e354d90fec26c2921aa2dea85b90dff90, and add comments to explain why child sources cannot be used.
When a GSource
Revert "chardev: use a child source for qio input source"
This reverts commit a7077b8e354d90fec26c2921aa2dea85b90dff90, and add comments to explain why child sources cannot be used.
When a GSource is added as a child of another GSource, if its 'prepare' function indicates readiness, then the parent's 'prepare' function will never be run. The io_watch_poll_prepare absolutely *must* be run on every iteration of the main loop, to ensure that the chardev backend doesn't feed data to the frontend that it is unable to consume.
At the time a7077b8e354d90fec26c2921aa2dea85b90dff90 was made, all the child GSource impls were relying on poll'ing an FD, so their 'prepare' functions would never indicate readiness ahead of poll() being invoked. So the buggy behaviour was not noticed and lay dormant.
Relatively recently the QIOChannelTLS impl introduced a level 2 child GSource, which checks with GNUTLS whether it has cached any data that was decoded but not yet consumed:
commit ffda5db65aef42266a5053a4be34515106c4c7ee Author: Antoine Damhet <antoine.damhet@shadow.tech> Date: Tue Nov 15 15:23:29 2022 +0100
io/channel-tls: fix handling of bigger read buffers
Since the TLS backend can read more data from the underlying QIOChannel we introduce a minimal child GSource to notify if we still have more data available to be read.
Signed-off-by: Antoine Damhet <antoine.damhet@shadow.tech> Signed-off-by: Charles Frey <charles.frey@shadow.tech> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
With this, it is now quite common for the 'prepare' function on a QIOChannelTLS GSource to indicate immediate readiness, bypassing the parent GSource 'prepare' function. IOW, the critical 'io_watch_poll_prepare' is being skipped on some iterations of the main loop. As a result chardev frontend asserts are now being triggered as they are fed data they are not ready to consume.
A reproducer is as follows:
* In terminal 1 run a GNUTLS *echo* server
$ gnutls-serv --echo \ --x509cafile ca-cert.pem \ --x509keyfile server-key.pem \ --x509certfile server-cert.pem \ -p 9000
* In terminal 2 run a QEMU guest
$ qemu-system-s390x \ -nodefaults \ -display none \ -object tls-creds-x509,id=tls0,dir=$PWD,endpoint=client \ -chardev socket,id=con0,host=localhost,port=9000,tls-creds=tls0 \ -device sclpconsole,chardev=con0 \ -hda Fedora-Cloud-Base-39-1.5.s390x.qcow2
After the previous patch revert, but before this patch revert, this scenario will crash:
qemu-system-s390x: ../hw/char/sclpconsole.c:73: chr_read: Assertion `size <= SIZE_BUFFER_VT220 - scon->iov_data_len' failed.
This assert indicates that 'tcp_chr_read' was called without 'tcp_chr_read_poll' having first been checked for ability to receive more data
QEMU's use of a 'prepare' function to create/delete another GSource is rather a hack and not normally the kind of thing that is expected to be done by a GSource. There is no mechanism to force GLib to always run the 'prepare' function of a parent GSource. The best option is to simply not use the child source concept, and go back to the functional approach previously relied on.
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> Reviewed-by: Thomas Huth <thuth@redhat.com> Tested-by: Thomas Huth <thuth@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
show more ...
|
e8ee827f | 18-Mar-2024 |
Daniel P. Berrangé <berrange@redhat.com> |
Revert "chardev/char-socket: Fix TLS io channels sending too much data to the backend"
This commit results in unexpected termination of the TLS connection. When 'fd_can_read' returns 0, the code goe
Revert "chardev/char-socket: Fix TLS io channels sending too much data to the backend"
This commit results in unexpected termination of the TLS connection. When 'fd_can_read' returns 0, the code goes on to pass a zero length buffer to qio_channel_read. The TLS impl calls into gnutls_recv() with this zero length buffer, at which point GNUTLS returns an error GNUTLS_E_INVALID_REQUEST. This is treated as fatal by QEMU's TLS code resulting in the connection being torn down by the chardev.
Simply skipping the qio_channel_read when the buffer length is zero is also not satisfactory, as it results in a high CPU burn busy loop massively slowing QEMU's functionality.
The proper solution is to avoid tcp_chr_read being called at all unless the frontend is able to accept more data. This will be done in a followup commit.
This reverts commit 462945cd22d2bcd233401ed3aa167d83a8e35b05
Reviewed-by: Thomas Huth <thuth@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
show more ...
|
1220f581 | 30-Aug-2023 |
Paolo Bonzini <pbonzini@redhat.com> |
meson: remove config_targetos
config_targetos is now empty and can be removed; its use in sourcesets that do not involve target-specific files can be replaced with an empty dictionary.
In fact, at
meson: remove config_targetos
config_targetos is now empty and can be removed; its use in sourcesets that do not involve target-specific files can be replaced with an empty dictionary.
In fact, at this point *all* sourcesets that do not involve target-specific files are just glorified mutable arrays. Enforce that they never test for symbols in "when:" by computing the set of files without "strict: false".
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
show more ...
|