[libvirt] [PATCH] Fix up a bogus TLS message.
Daniel P. Berrange
berrange at redhat.com
Fri Oct 30 14:49:08 UTC 2009
On Fri, Oct 23, 2009 at 01:01:32PM +0200, Chris Lalancette wrote:
> When working with the TLS transport, I noticed that every single time
> a remote stream was closed, I would get a message like:
>
> 09:09:40.793: error : remoteIOReadBuffer:7328 : failed to read from TLS socket A TLS packet with unexpected length was received.
> libvir: QEMU error : failed to read from TLS socket A TLS packet with unexpected length was received.
>
> in the logs. This happens because of a race in libvirtd; one thread
> handles the doRemoteClose(), which calls gnutls_bye() followed by close()
> while another thread is poll()'ing on the same fd. Once the close()
> happens, the poll returns with revents set to POLLIN, and we would poll
> one more time for data from the now-closed fd. Fix this situation by
> setting poll->session to NULL when we clean up, and check for that in
> remoteIOHandleInput().
I'm not sure that this is correct. If the connection is being closed
while another thread is still using it, that sounds like a bug that
should be fixed, because whatever just called doRemoteClose() has
also free'd 'priv', and so whatever other thread is in remoteIOReadBuffer()
is now accessing free'd memory.
>
> Signed-off-by: Chris Lalancette <clalance at redhat.com>
> ---
> src/remote/remote_driver.c | 7 +++++++
> 1 files changed, 7 insertions(+), 0 deletions(-)
>
> diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
> index bf001eb..335f44b 100644
> --- a/src/remote/remote_driver.c
> +++ b/src/remote/remote_driver.c
> @@ -1389,6 +1389,7 @@ doRemoteClose (virConnectPtr conn, struct private_data *priv)
> if (priv->uses_tls && priv->session) {
> gnutls_bye (priv->session, GNUTLS_SHUT_RDWR);
> gnutls_deinit (priv->session);
> + priv->session = NULL;
> }
> #if HAVE_SASL
> if (priv->saslconn)
> @@ -7223,6 +7224,12 @@ remoteIOReadBuffer(virConnectPtr conn,
> int ret;
>
> if (priv->uses_tls) {
> + if (!priv->session) {
> + /* we may have reached here one more time after gnutls_bye()
> + * was called, so just return here
> + */
> + return 0;
> + }
If gnutls_bye() was just called, then 'priv' has also just been
freed. So this must surely be accessing freed memory.
> tls_resend:
> ret = gnutls_record_recv (priv->session, bytes, len);
> if (ret == GNUTLS_E_INTERRUPTED)
> --
> 1.6.0.6
Daniel
--
|: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
More information about the libvir-list
mailing list