diff options
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.patch | 73 |
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 + |