[Libguestfs] [PATCH libnbd 2/2] lib/crypto.c: Ignore TLS premature termination after write shutdown
Laszlo Ersek
lersek at redhat.com
Thu Jul 28 12:59:33 UTC 2022
On 07/27/22 18:30, Richard W.M. Jones wrote:
> qemu-nbd doesn't call gnutls_bye to cleanly shut down the connection
> after we send NBD_CMD_DISC. When copying from a qemu-nbd server (or
> any operation which calls nbd_shutdown) you will see errors like this:
>
> $ nbdcopy nbds://foo?tls-certificates=/var/tmp/pki null:
> nbds://foo?tls-certificates=/var/tmp/pki: nbd_shutdown: gnutls_record_recv: The TLS connection was non-properly terminated.
>
> Relatedly you may also see:
>
> nbd_shutdown: gnutls_record_recv: Error in the pull function.
>
> This commit suppresses the error in the case where we know that we
> have shut down writes (which happens after NBD_CMD_DISC has been sent
> on the wire).
> ---
> interop/interop.c | 9 ---------
> lib/crypto.c | 17 +++++++++++++++++
> lib/internal.h | 1 +
> 3 files changed, 18 insertions(+), 9 deletions(-)
>
> diff --git a/interop/interop.c b/interop/interop.c
> index 036545bd82..cce9407aa1 100644
> --- a/interop/interop.c
> +++ b/interop/interop.c
> @@ -226,19 +226,10 @@ main (int argc, char *argv[])
>
> /* XXX In future test more operations here. */
>
> -#if !TLS
> - /* XXX qemu doesn't shut down the connection nicely (using
> - * gnutls_bye) and because of this the following call will fail
> - * with:
> - *
> - * nbd_shutdown: gnutls_record_recv: The TLS connection was
> - * non-properly terminated.
> - */
> if (nbd_shutdown (nbd, 0) == -1) {
> fprintf (stderr, "%s\n", nbd_get_error ());
> exit (EXIT_FAILURE);
> }
> -#endif
>
> nbd_close (nbd);
>
> diff --git a/lib/crypto.c b/lib/crypto.c
> index ffba4bda9b..a2832b1585 100644
> --- a/lib/crypto.c
> +++ b/lib/crypto.c
> @@ -189,6 +189,22 @@ tls_recv (struct nbd_handle *h, struct socket *sock, void *buf, size_t len)
> errno = EAGAIN;
> return -1;
> }
> + if (h->tls_shut_writes &&
> + (r == GNUTLS_E_PULL_ERROR || r == GNUTLS_E_PREMATURE_TERMINATION)) {
> + /* qemu-nbd doesn't call gnutls_bye to cleanly shut down the
> + * connection after we send NBD_CMD_DISC, instead it simply
> + * closes the connection. On the client side we see
> + * "gnutls_record_recv: The TLS connection was non-properly
> + * terminated" or "gnutls_record_recv: Error in the pull
> + * function.".
> + *
> + * If we see these errors after we shut down the write side
> + * (h->tls_shut_writes), which happens after we have sent
> + * NBD_CMD_DISC on the wire, downgrade them to a debug message.
> + */
> + debug (h, "gnutls_record_recv: %s", gnutls_strerror (r));
> + return 0; /* EOF */
> + }
> set_error (0, "gnutls_record_recv: %s", gnutls_strerror (r));
> errno = EIO;
> return -1;
> @@ -236,6 +252,7 @@ tls_shut_writes (struct nbd_handle *h, struct socket *sock)
> return false;
> if (r != 0)
> debug (h, "ignoring gnutls_bye failure: %s", gnutls_strerror (r));
> + h->tls_shut_writes = true;
> return sock->u.tls.oldsock->ops->shut_writes (h, sock->u.tls.oldsock);
> }
>
> diff --git a/lib/internal.h b/lib/internal.h
> index 4121a5cdaa..8dbe2e4568 100644
> --- a/lib/internal.h
> +++ b/lib/internal.h
> @@ -307,6 +307,7 @@ struct nbd_handle {
> struct command *reply_cmd;
>
> bool disconnect_request; /* True if we've queued NBD_CMD_DISC */
> + bool tls_shut_writes; /* Used by lib/crypto.c to track disconnect. */
> };
>
> struct meta_context {
>
Looks reasonable.
Acked-by: Laszlo Ersek <lersek at redhat.com>
More information about the Libguestfs
mailing list