summaryrefslogtreecommitdiffstats
path: root/debian/patches/80_02-GnuTLS-tls_write-wait-after-uncorking-the-session.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/80_02-GnuTLS-tls_write-wait-after-uncorking-the-session.patch')
-rw-r--r--debian/patches/80_02-GnuTLS-tls_write-wait-after-uncorking-the-session.patch73
1 files changed, 73 insertions, 0 deletions
diff --git a/debian/patches/80_02-GnuTLS-tls_write-wait-after-uncorking-the-session.patch b/debian/patches/80_02-GnuTLS-tls_write-wait-after-uncorking-the-session.patch
new file mode 100644
index 0000000..9998618
--- /dev/null
+++ b/debian/patches/80_02-GnuTLS-tls_write-wait-after-uncorking-the-session.patch
@@ -0,0 +1,73 @@
+From 783cb0301d9ceef2748956c3f91762275b7b45e5 Mon Sep 17 00:00:00 2001
+From: "Heiko Schlittermann (HS12-RIPE)" <hs@schlittermann.de>
+Date: Tue, 18 Feb 2020 18:59:49 +0100
+Subject: [PATCH 5/6] GnuTLS: tls_write(): wait after uncorking the session
+
+(cherry picked from commit 8f9adfd36222d4e9e730734e00dffe874073e5b4)
+---
+ src/tls-gnu.c | 34 ++++++++++++++++++++++++++++------
+ 1 file changed, 28 insertions(+), 6 deletions(-)
+
+diff --git a/src/tls-gnu.c b/src/tls-gnu.c
+index 822ad89c6..94a718673 100644
+--- a/src/tls-gnu.c
++++ b/src/tls-gnu.c
+@@ -2835,9 +2835,14 @@ tls_write(void * ct_ctx, const uschar * buff, size_t len, BOOL more)
+ ssize_t outbytes;
+ size_t left = len;
+ exim_gnutls_state_st * state = ct_ctx ? ct_ctx : &state_server;
+-#ifdef SUPPORT_CORK
+
+-if (more && !state->corked) gnutls_record_cork(state->session);
++#ifdef SUPPORT_CORK
++if (more && !state->corked)
++ {
++ DEBUG(D_tls) debug_printf("gnutls_record_cork(session=%p)\n", state->session);
++ gnutls_record_cork(state->session);
++ state->corked = TRUE;
++ }
+ #endif
+
+ DEBUG(D_tls) debug_printf("%s(%p, " SIZE_T_FMT "%s)\n", __FUNCTION__,
+@@ -2853,6 +2858,7 @@ while (left > 0)
+ while (outbytes == GNUTLS_E_AGAIN);
+
+ DEBUG(D_tls) debug_printf("outbytes=" SSIZE_T_FMT "\n", outbytes);
++
+ if (outbytes < 0)
+ {
+ DEBUG(D_tls) debug_printf("%s: gnutls_record_send err\n", __FUNCTION__);
+@@ -2878,10 +2884,26 @@ if (len > INT_MAX)
+ }
+
+ #ifdef SUPPORT_CORK
+-if (more != state->corked)
+- {
+- if (!more) (void) gnutls_record_uncork(state->session, 0);
+- state->corked = more;
++if (!more && state->corked)
++ {
++ DEBUG(D_tls) debug_printf("gnutls_record_uncork(session=%p)\n", state->session);
++ do {
++ do
++ /* We can't use GNUTLS_RECORD_WAIT here, as it retries on
++ GNUTLS_E_AGAIN || GNUTLS_E_INTR, which would break our timeout set by alarm().
++ The GNUTLS_E_AGAIN should not happen ever, as our sockets are blocking anyway.
++ But who knows. (That all relies on the fact that GNUTLS_E_INTR and GNUTLS_E_AGAIN
++ match the EINTR and EAGAIN errno values.) */
++ outbytes = gnutls_record_uncork(state->session, 0);
++ while (outbytes == GNUTLS_E_AGAIN);
++
++ if (outbytes < 0)
++ {
++ record_io_error(state, len, US"uncork", NULL);
++ return -1;
++ }
++ } while (gnutls_record_check_corked(state->session) > 0);
++ state->corked = FALSE;
+ }
+ #endif
+
+--
+2.28.0
+