]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
crypto: propagate Error object on premature termination
authorDaniel P. Berrangé <berrange@redhat.com>
Mon, 6 Oct 2025 18:46:21 +0000 (19:46 +0100)
committerDaniel P. Berrangé <berrange@redhat.com>
Fri, 24 Oct 2025 12:04:31 +0000 (13:04 +0100)
The way that premature termination was handled in TLS connections was
changed to handle an ordering problem during graceful shutdown in the
migration code.

Unfortunately one of the codepaths returned -1 to indicate an error
condition, but failed to set the 'errp' parameter.

This broke error handling in the qio_channel_tls_handshake function,
as the QTask callback would no longer see that an error was raised.
As a result, the client will go on to try to use the already closed
TLS connection, resulting in misleading errors.

This was evidenced in the I/O test 233 which showed changes such as

-qemu-nbd: Certificate does not match the hostname localhost
+qemu-nbd: Failed to read initial magic: Unable to read from socket: Connection reset by peer

Fixes: 7e0c22d585581b8083ffdeb332ea497218665daf
Acked-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
crypto/tlssession.c
io/channel-tls.c

index ac38c2121dbd38eeeeae03a06034b3230ed584fc..8c0bf457ad7d1ed6eda0bceb70d3d208f6ec51f5 100644 (file)
@@ -569,8 +569,6 @@ qcrypto_tls_session_read(QCryptoTLSSession *session,
     if (ret < 0) {
         if (ret == GNUTLS_E_AGAIN) {
             return QCRYPTO_TLS_SESSION_ERR_BLOCK;
-        } else if (ret == GNUTLS_E_PREMATURE_TERMINATION) {
-            return QCRYPTO_TLS_SESSION_PREMATURE_TERMINATION;
         } else {
             if (session->rerr) {
                 error_propagate(errp, session->rerr);
@@ -580,7 +578,11 @@ qcrypto_tls_session_read(QCryptoTLSSession *session,
                            "Cannot read from TLS channel: %s",
                            gnutls_strerror(ret));
             }
-            return -1;
+            if (ret == GNUTLS_E_PREMATURE_TERMINATION) {
+                return QCRYPTO_TLS_SESSION_PREMATURE_TERMINATION;
+            } else {
+                return -1;
+            }
         }
     }
 
index 1fbed4be0c670a72dd0ba14381671e0be7610447..70fad38d18c828b8e78d310f97132f039b704f3b 100644 (file)
@@ -368,6 +368,7 @@ static ssize_t qio_channel_tls_readv(QIOChannel *ioc,
                                      int flags,
                                      Error **errp)
 {
+    ERRP_GUARD();
     QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
     size_t i;
     ssize_t got = 0;
@@ -384,13 +385,13 @@ static ssize_t qio_channel_tls_readv(QIOChannel *ioc,
             } else {
                 return QIO_CHANNEL_ERR_BLOCK;
             }
-        } else if (ret == QCRYPTO_TLS_SESSION_PREMATURE_TERMINATION) {
-            if (qio_channel_tls_allow_premature_termination(tioc, flags)) {
-                ret = 0;
-            } else {
-                return -1;
-            }
         } else if (ret < 0) {
+            if (ret == QCRYPTO_TLS_SESSION_PREMATURE_TERMINATION &&
+                qio_channel_tls_allow_premature_termination(tioc, flags)) {
+                error_free(*errp);
+                *errp = NULL;
+                return got;
+            }
             return -1;
         }
         got += ret;