[Libguestfs] [PATCH libnbd v2 1/3] lib/crypto: Use GNUTLS_NO_SIGNAL if available

Richard W.M. Jones rjones at redhat.com
Thu Jul 28 14:19:08 UTC 2022


libnbd has long used MSG_NOSIGNAL to avoid receiving SIGPIPE if we
accidentally write on a closed socket, which is a nice alternative to
using a SIGPIPE signal handler.  However with TLS connections, gnutls
did not use this flag and so programs using libnbd + TLS would receive
SIGPIPE in some situations, notably if the server closed the
connection abruptly while we were trying to write something.

GnuTLS 3.4.2 introduces GNUTLS_NO_SIGNAL which does the same thing.
Use this flag if available.

RHEL 7 has an older gnutls which lacks this flag.  To avoid qemu-nbd
interop tests failing (rarely, but more often with a forthcoming
change to TLS shutdown behaviour), register a SIGPIPE signal handler
in the test if the flag is missing.
---
 interop/interop.c | 8 ++++++++
 lib/crypto.c      | 7 ++++++-
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/interop/interop.c b/interop/interop.c
index f3437d7dea..bd5dc2e196 100644
--- a/interop/interop.c
+++ b/interop/interop.c
@@ -84,6 +84,14 @@ main (int argc, char *argv[])
   REQUIRES
 #endif
 
+  /* Ignore SIGPIPE.  We only need this for GnuTLS that lacks the
+   * GNUTLS_NO_SIGNAL flag, either because it predates GnuTLS 3.4.2 or
+   * because the OS lacks MSG_NOSIGNAL support.
+   */
+#if TLS && !defined(HAVE_GNUTLS_NO_SIGNAL)
+  signal (SIGPIPE, SIG_IGN);
+#endif
+
   /* Create a large sparse temporary file. */
 #ifdef NEEDS_TMPFILE
   int fd = mkstemp (TMPFILE);
diff --git a/lib/crypto.c b/lib/crypto.c
index 9d6332c6c9..7ff83c2314 100644
--- a/lib/crypto.c
+++ b/lib/crypto.c
@@ -606,8 +606,13 @@ nbd_internal_crypto_create_session (struct nbd_handle *h,
   gnutls_session_t session;
   gnutls_psk_client_credentials_t pskcreds = NULL;
   gnutls_certificate_credentials_t xcreds = NULL;
+  gnutls_init_flags_t init_flags;
 
-  err = gnutls_init (&session, GNUTLS_CLIENT|GNUTLS_NONBLOCK);
+  init_flags = GNUTLS_CLIENT | GNUTLS_NONBLOCK;
+#ifdef GNUTLS_NO_SIGNAL
+  init_flags |= GNUTLS_NO_SIGNAL;
+#endif
+  err = gnutls_init (&session, init_flags);
   if (err < 0) {
     set_error (errno, "gnutls_init: %s", gnutls_strerror (err));
     return NULL;
-- 
2.37.0.rc2



More information about the Libguestfs mailing list