Blame SOURCES/0009-lib-crypto-Use-GNUTLS_NO_SIGNAL-if-available.patch

5893ea
From a432e773e0cdc24cb27ccdda4111744ea2c3b819 Mon Sep 17 00:00:00 2001
5893ea
From: "Richard W.M. Jones" <rjones@redhat.com>
5893ea
Date: Wed, 27 Jul 2022 17:08:14 +0100
5893ea
Subject: [PATCH] lib/crypto: Use GNUTLS_NO_SIGNAL if available
5893ea
5893ea
libnbd has long used MSG_NOSIGNAL to avoid receiving SIGPIPE if we
5893ea
accidentally write on a closed socket, which is a nice alternative to
5893ea
using a SIGPIPE signal handler.  However with TLS connections, gnutls
5893ea
did not use this flag and so programs using libnbd + TLS would receive
5893ea
SIGPIPE in some situations, notably if the server closed the
5893ea
connection abruptly while we were trying to write something.
5893ea
5893ea
GnuTLS 3.4.2 introduces GNUTLS_NO_SIGNAL which does the same thing.
5893ea
Use this flag if available.
5893ea
5893ea
RHEL 7 has an older gnutls which lacks this flag.  To avoid qemu-nbd
5893ea
interop tests failing (rarely, but more often with a forthcoming
5893ea
change to TLS shutdown behaviour), register a SIGPIPE signal handler
5893ea
in the test if the flag is missing.
5893ea
---
5893ea
 configure.ac      | 15 +++++++++++++++
5893ea
 interop/interop.c | 10 ++++++++++
5893ea
 lib/crypto.c      |  7 ++++++-
5893ea
 3 files changed, 31 insertions(+), 1 deletion(-)
5893ea
5893ea
diff --git a/configure.ac b/configure.ac
5893ea
index 49ca8ab..6bd9e1b 100644
5893ea
--- a/configure.ac
5893ea
+++ b/configure.ac
5893ea
@@ -179,6 +179,21 @@ AS_IF([test "$GNUTLS_LIBS" != ""],[
5893ea
         gnutls_session_set_verify_cert \
5893ea
         gnutls_transport_is_ktls_enabled \
5893ea
     ])
5893ea
+    AC_MSG_CHECKING([if gnutls has GNUTLS_NO_SIGNAL])
5893ea
+    AC_COMPILE_IFELSE(
5893ea
+        [AC_LANG_PROGRAM([
5893ea
+            #include <gnutls/gnutls.h>
5893ea
+            gnutls_session_t session;
5893ea
+         ], [
5893ea
+            gnutls_init(&session, GNUTLS_CLIENT|GNUTLS_NO_SIGNAL);
5893ea
+         ])
5893ea
+    ], [
5893ea
+        AC_MSG_RESULT([yes])
5893ea
+        AC_DEFINE([HAVE_GNUTLS_NO_SIGNAL], [1],
5893ea
+                  [GNUTLS_NO_SIGNAL found at compile time])
5893ea
+    ], [
5893ea
+        AC_MSG_RESULT([no])
5893ea
+    ])
5893ea
     LIBS="$old_LIBS"
5893ea
 ])
5893ea
 
5893ea
diff --git a/interop/interop.c b/interop/interop.c
5893ea
index b41f3ca..036545b 100644
5893ea
--- a/interop/interop.c
5893ea
+++ b/interop/interop.c
5893ea
@@ -84,6 +84,16 @@ main (int argc, char *argv[])
5893ea
   REQUIRES
5893ea
 #endif
5893ea
 
5893ea
+  /* Ignore SIGPIPE.  We only need this for GnuTLS < 3.4.2, since
5893ea
+   * newer GnuTLS has the GNUTLS_NO_SIGNAL flag which adds
5893ea
+   * MSG_NOSIGNAL to each write call.
5893ea
+   */
5893ea
+#if !HAVE_GNUTLS_NO_SIGNAL
5893ea
+#if TLS
5893ea
+  signal (SIGPIPE, SIG_IGN);
5893ea
+#endif
5893ea
+#endif
5893ea
+
5893ea
   /* Create a large sparse temporary file. */
5893ea
 #ifdef NEEDS_TMPFILE
5893ea
   int fd = mkstemp (TMPFILE);
5893ea
diff --git a/lib/crypto.c b/lib/crypto.c
5893ea
index 1272888..ca9520e 100644
5893ea
--- a/lib/crypto.c
5893ea
+++ b/lib/crypto.c
5893ea
@@ -588,7 +588,12 @@ nbd_internal_crypto_create_session (struct nbd_handle *h,
5893ea
   gnutls_psk_client_credentials_t pskcreds = NULL;
5893ea
   gnutls_certificate_credentials_t xcreds = NULL;
5893ea
 
5893ea
-  err = gnutls_init (&session, GNUTLS_CLIENT|GNUTLS_NONBLOCK);
5893ea
+  err = gnutls_init (&session,
5893ea
+                     GNUTLS_CLIENT | GNUTLS_NONBLOCK
5893ea
+#if HAVE_GNUTLS_NO_SIGNAL
5893ea
+                     | GNUTLS_NO_SIGNAL
5893ea
+#endif
5893ea
+                     );
5893ea
   if (err < 0) {
5893ea
     set_error (errno, "gnutls_init: %s", gnutls_strerror (err));
5893ea
     return NULL;
5893ea
-- 
5893ea
2.31.1
5893ea