qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Thomas Huth <thuth@redhat.com>
To: "Daniel P. Berrangé" <berrange@redhat.com>, qemu-devel@nongnu.org
Cc: "Paolo Bonzini" <pbonzini@redhat.com>,
	"Laurent Vivier" <lvivier@redhat.com>,
	"Markus Armbruster" <armbru@redhat.com>,
	"Philippe Mathieu-Daudé" <philmd@linaro.org>,
	"Eric Blake" <eblake@redhat.com>,
	"Marc-André Lureau" <marcandre.lureau@redhat.com>,
	"Hyman Huang" <yong.huang@smartx.com>,
	Qemu-block <qemu-block@nongnu.org>,
	"Kevin Wolf" <kwolf@redhat.com>,
	"Hanna Reitz" <hreitz@redhat.com>
Subject: Re: [PULL 10/11] crypto: push error reporting into TLS session I/O APIs
Date: Mon, 12 Aug 2024 17:38:41 +0200	[thread overview]
Message-ID: <25ea7357-99e1-4fdf-9ef8-885cb7e75f47@redhat.com> (raw)
In-Reply-To: <20240724094706.30396-11-berrange@redhat.com>

On 24/07/2024 11.47, Daniel P. Berrangé wrote:
> The current TLS session I/O APIs just return a synthetic errno
> value on error, which has been translated from a gnutls error
> value. This looses a large amount of valuable information that
> distinguishes different scenarios.
> 
> Pushing population of the "Error *errp" object into the TLS
> session I/O APIs gives more detailed error information.
> 
> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---

  Hi Daniel!

iotest 233 is failing for me with -raw now, and bisection
points to this commit. Output is:

--- .../qemu/tests/qemu-iotests/233.out
+++ /tmp/qemu/tests/qemu-iotests/scratch/raw-file-233/233.out.bad
@@ -69,8 +69,8 @@
  1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)

  == check TLS with authorization ==
-qemu-img: Could not open 'driver=nbd,host=127.0.0.1,port=PORT,tls-creds=tls0': Failed to read option reply: Cannot read from TLS channel: Software caused connection abort
-qemu-img: Could not open 'driver=nbd,host=127.0.0.1,port=PORT,tls-creds=tls0': Failed to read option reply: Cannot read from TLS channel: Software caused connection abort
+qemu-img: Could not open 'driver=nbd,host=127.0.0.1,port=PORT,tls-creds=tls0': Failed to read option reply: Cannot read from TLS channel: The TLS connection was non-properly terminated.
+qemu-img: Could not open 'driver=nbd,host=127.0.0.1,port=PORT,tls-creds=tls0': Failed to read option reply: Cannot read from TLS channel: The TLS connection was non-properly terminated.

  == check TLS fail over UNIX with no hostname ==
  qemu-img: Could not open 'driver=nbd,path=SOCK_DIR/qemu-nbd.sock,tls-creds=tls0': No hostname for certificate validation
@@ -103,14 +103,14 @@
  qemu-nbd: TLS handshake failed: The TLS connection was non-properly terminated.

  == final server log ==
-qemu-nbd: option negotiation failed: Failed to read opts magic: Cannot read from TLS channel: Software caused connection abort
-qemu-nbd: option negotiation failed: Failed to read opts magic: Cannot read from TLS channel: Software caused connection abort
+qemu-nbd: option negotiation failed: Failed to read opts magic: Cannot read from TLS channel: The TLS connection was non-properly terminated.
+qemu-nbd: option negotiation failed: Failed to read opts magic: Cannot read from TLS channel: The TLS connection was non-properly terminated.
  qemu-nbd: option negotiation failed: Verify failed: No certificate was found.
  qemu-nbd: option negotiation failed: Verify failed: No certificate was found.
  qemu-nbd: option negotiation failed: TLS x509 authz check for DISTINGUISHED-NAME is denied
  qemu-nbd: option negotiation failed: TLS x509 authz check for DISTINGUISHED-NAME is denied
-qemu-nbd: option negotiation failed: Failed to read opts magic: Cannot read from TLS channel: Software caused connection abort
-qemu-nbd: option negotiation failed: Failed to read opts magic: Cannot read from TLS channel: Software caused connection abort
+qemu-nbd: option negotiation failed: Failed to read opts magic: Cannot read from TLS channel: The TLS connection was non-properly terminated.
+qemu-nbd: option negotiation failed: Failed to read opts magic: Cannot read from TLS channel: The TLS connection was non-properly terminated.
  qemu-nbd: option negotiation failed: TLS handshake failed: An illegal parameter has been received.
  qemu-nbd: option negotiation failed: TLS handshake failed: An illegal parameter has been received.
  *** done

Could you please have a look?

  Thanks,
   Thomas

> 
> diff --git a/crypto/tlssession.c b/crypto/tlssession.c
> index 1e98f44e0d..926f19c115 100644
> --- a/crypto/tlssession.c
> +++ b/crypto/tlssession.c
> @@ -441,23 +441,20 @@ qcrypto_tls_session_set_callbacks(QCryptoTLSSession *session,
>   ssize_t
>   qcrypto_tls_session_write(QCryptoTLSSession *session,
>                             const char *buf,
> -                          size_t len)
> +                          size_t len,
> +                          Error **errp)
>   {
>       ssize_t ret = gnutls_record_send(session->handle, buf, len);
>   
>       if (ret < 0) {
> -        switch (ret) {
> -        case GNUTLS_E_AGAIN:
> -            errno = EAGAIN;
> -            break;
> -        case GNUTLS_E_INTERRUPTED:
> -            errno = EINTR;
> -            break;
> -        default:
> -            errno = EIO;
> -            break;
> +        if (ret == GNUTLS_E_AGAIN) {
> +            return QCRYPTO_TLS_SESSION_ERR_BLOCK;
> +        } else {
> +            error_setg(errp,
> +                       "Cannot write to TLS channel: %s",
> +                       gnutls_strerror(ret));
> +            return -1;
>           }
> -        ret = -1;
>       }
>   
>       return ret;
> @@ -467,26 +464,24 @@ qcrypto_tls_session_write(QCryptoTLSSession *session,
>   ssize_t
>   qcrypto_tls_session_read(QCryptoTLSSession *session,
>                            char *buf,
> -                         size_t len)
> +                         size_t len,
> +                         bool gracefulTermination,
> +                         Error **errp)
>   {
>       ssize_t ret = gnutls_record_recv(session->handle, buf, len);
>   
>       if (ret < 0) {
> -        switch (ret) {
> -        case GNUTLS_E_AGAIN:
> -            errno = EAGAIN;
> -            break;
> -        case GNUTLS_E_INTERRUPTED:
> -            errno = EINTR;
> -            break;
> -        case GNUTLS_E_PREMATURE_TERMINATION:
> -            errno = ECONNABORTED;
> -            break;
> -        default:
> -            errno = EIO;
> -            break;
> +        if (ret == GNUTLS_E_AGAIN) {
> +            return QCRYPTO_TLS_SESSION_ERR_BLOCK;
> +        } else if ((ret == GNUTLS_E_PREMATURE_TERMINATION) &&
> +                   gracefulTermination){
> +            return 0;
> +        } else {
> +            error_setg(errp,
> +                       "Cannot read from TLS channel: %s",
> +                       gnutls_strerror(ret));
> +            return -1;
>           }
> -        ret = -1;
>       }
>   
>       return ret;
> @@ -605,9 +600,10 @@ qcrypto_tls_session_set_callbacks(
>   ssize_t
>   qcrypto_tls_session_write(QCryptoTLSSession *sess,
>                             const char *buf,
> -                          size_t len)
> +                          size_t len,
> +                          Error **errp)
>   {
> -    errno = -EIO;
> +    error_setg(errp, "TLS requires GNUTLS support");
>       return -1;
>   }
>   
> @@ -615,9 +611,11 @@ qcrypto_tls_session_write(QCryptoTLSSession *sess,
>   ssize_t
>   qcrypto_tls_session_read(QCryptoTLSSession *sess,
>                            char *buf,
> -                         size_t len)
> +                         size_t len,
> +                         bool gracefulTermination,
> +                         Error **errp)
>   {
> -    errno = -EIO;
> +    error_setg(errp, "TLS requires GNUTLS support");
>       return -1;
>   }
>   
> diff --git a/include/crypto/tlssession.h b/include/crypto/tlssession.h
> index 571049bd0e..291e602540 100644
> --- a/include/crypto/tlssession.h
> +++ b/include/crypto/tlssession.h
> @@ -107,6 +107,7 @@
>   
>   typedef struct QCryptoTLSSession QCryptoTLSSession;
>   
> +#define QCRYPTO_TLS_SESSION_ERR_BLOCK -2
>   
>   /**
>    * qcrypto_tls_session_new:
> @@ -212,6 +213,7 @@ void qcrypto_tls_session_set_callbacks(QCryptoTLSSession *sess,
>    * @sess: the TLS session object
>    * @buf: the plain text to send
>    * @len: the length of @buf
> + * @errp: pointer to hold returned error object
>    *
>    * Encrypt @len bytes of the data in @buf and send
>    * it to the remote peer using the callback previously
> @@ -221,32 +223,45 @@ void qcrypto_tls_session_set_callbacks(QCryptoTLSSession *sess,
>    * qcrypto_tls_session_get_handshake_status() returns
>    * QCRYPTO_TLS_HANDSHAKE_COMPLETE
>    *
> - * Returns: the number of bytes sent, or -1 on error
> + * Returns: the number of bytes sent,
> + * or QCRYPTO_TLS_SESSION_ERR_BLOCK if the write would block,
> + * or -1 on error.
>    */
>   ssize_t qcrypto_tls_session_write(QCryptoTLSSession *sess,
>                                     const char *buf,
> -                                  size_t len);
> +                                  size_t len,
> +                                  Error **errp);
>   
>   /**
>    * qcrypto_tls_session_read:
>    * @sess: the TLS session object
>    * @buf: to fill with plain text received
>    * @len: the length of @buf
> + * @gracefulTermination: treat premature termination as graceful EOF
> + * @errp: pointer to hold returned error object
>    *
>    * Receive up to @len bytes of data from the remote peer
>    * using the callback previously registered with
>    * qcrypto_tls_session_set_callbacks(), decrypt it and
>    * store it in @buf.
>    *
> + * If @gracefulTermination is true, then a premature termination
> + * of the TLS session will be treated as indicating EOF, as
> + * opposed to an error.
> + *
>    * It is an error to call this before
>    * qcrypto_tls_session_get_handshake_status() returns
>    * QCRYPTO_TLS_HANDSHAKE_COMPLETE
>    *
> - * Returns: the number of bytes received, or -1 on error
> + * Returns: the number of bytes received,
> + * or QCRYPTO_TLS_SESSION_ERR_BLOCK if the receive would block,
> + * or -1 on error.
>    */
>   ssize_t qcrypto_tls_session_read(QCryptoTLSSession *sess,
>                                    char *buf,
> -                                 size_t len);
> +                                 size_t len,
> +                                 bool gracefulTermination,
> +                                 Error **errp);
>   
>   /**
>    * qcrypto_tls_session_check_pending:
> diff --git a/io/channel-tls.c b/io/channel-tls.c
> index 67b9700006..9d8bb158d1 100644
> --- a/io/channel-tls.c
> +++ b/io/channel-tls.c
> @@ -277,24 +277,19 @@ static ssize_t qio_channel_tls_readv(QIOChannel *ioc,
>       ssize_t got = 0;
>   
>       for (i = 0 ; i < niov ; i++) {
> -        ssize_t ret = qcrypto_tls_session_read(tioc->session,
> -                                               iov[i].iov_base,
> -                                               iov[i].iov_len);
> -        if (ret < 0) {
> -            if (errno == EAGAIN) {
> -                if (got) {
> -                    return got;
> -                } else {
> -                    return QIO_CHANNEL_ERR_BLOCK;
> -                }
> -            } else if (errno == ECONNABORTED &&
> -                       (qatomic_load_acquire(&tioc->shutdown) &
> -                        QIO_CHANNEL_SHUTDOWN_READ)) {
> -                return 0;
> +        ssize_t ret = qcrypto_tls_session_read(
> +            tioc->session,
> +            iov[i].iov_base,
> +            iov[i].iov_len,
> +            qatomic_load_acquire(&tioc->shutdown) & QIO_CHANNEL_SHUTDOWN_READ,
> +            errp);
> +        if (ret == QCRYPTO_TLS_SESSION_ERR_BLOCK) {
> +            if (got) {
> +                return got;
> +            } else {
> +                return QIO_CHANNEL_ERR_BLOCK;
>               }
> -
> -            error_setg_errno(errp, errno,
> -                             "Cannot read from TLS channel");
> +        } else if (ret < 0) {
>               return -1;
>           }
>           got += ret;
> @@ -321,18 +316,15 @@ static ssize_t qio_channel_tls_writev(QIOChannel *ioc,
>       for (i = 0 ; i < niov ; i++) {
>           ssize_t ret = qcrypto_tls_session_write(tioc->session,
>                                                   iov[i].iov_base,
> -                                                iov[i].iov_len);
> -        if (ret <= 0) {
> -            if (errno == EAGAIN) {
> -                if (done) {
> -                    return done;
> -                } else {
> -                    return QIO_CHANNEL_ERR_BLOCK;
> -                }
> +                                                iov[i].iov_len,
> +                                                errp);
> +        if (ret == QCRYPTO_TLS_SESSION_ERR_BLOCK) {
> +            if (done) {
> +                return done;
> +            } else {
> +                return QIO_CHANNEL_ERR_BLOCK;
>               }
> -
> -            error_setg_errno(errp, errno,
> -                             "Cannot write to TLS channel");
> +        } else if (ret < 0) {
>               return -1;
>           }
>           done += ret;



  reply	other threads:[~2024-08-12 15:39 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-07-24  9:46 [PULL 00/11] Crypto patches Daniel P. Berrangé
2024-07-24  9:46 ` [PULL 01/11] crypto: Remove 'crypto-tls-x509-helpers.h' from crypto-tls-psk-helpers.c Daniel P. Berrangé
2024-07-24  9:46 ` [PULL 02/11] crypto: Restrict pkix_asn1_tab[] to crypto-tls-x509-helpers.c Daniel P. Berrangé
2024-07-24  9:46 ` [PULL 03/11] crypto: Allow building with GnuTLS but without Libtasn1 Daniel P. Berrangé
2024-07-24  9:46 ` [PULL 04/11] docs/devel: Add introduction to LUKS volume with detached header Daniel P. Berrangé
2024-07-24  9:47 ` [PULL 05/11] meson.build: fix libgcrypt detection on system without libgcrypt-config Daniel P. Berrangé
2024-07-24  9:47 ` [PULL 06/11] qapi: drop unused QCryptoBlockCreateOptionsLUKS.detached-header Daniel P. Berrangé
2024-07-24  9:47 ` [PULL 07/11] meson: build chardev trace files when have_block Daniel P. Berrangé
2024-07-24  9:47 ` [PULL 08/11] chardev: add tracing of socket error conditions Daniel P. Berrangé
2024-07-24  9:47 ` [PULL 09/11] crypto: drop gnutls debug logging support Daniel P. Berrangé
2024-07-24  9:47 ` [PULL 10/11] crypto: push error reporting into TLS session I/O APIs Daniel P. Berrangé
2024-08-12 15:38   ` Thomas Huth [this message]
2024-08-12 15:42     ` Daniel P. Berrangé
2024-08-27  7:05       ` Markus Armbruster
2024-08-28  8:32         ` Thomas Huth
2024-08-29 11:03           ` Daniel P. Berrangé
2024-07-24  9:47 ` [PULL 11/11] crypto: propagate errors from TLS session I/O callbacks Daniel P. Berrangé
2024-07-24 23:53 ` [PULL 00/11] Crypto patches Richard Henderson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=25ea7357-99e1-4fdf-9ef8-885cb7e75f47@redhat.com \
    --to=thuth@redhat.com \
    --cc=armbru@redhat.com \
    --cc=berrange@redhat.com \
    --cc=eblake@redhat.com \
    --cc=hreitz@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=lvivier@redhat.com \
    --cc=marcandre.lureau@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=philmd@linaro.org \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=yong.huang@smartx.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).