Import Debian changes 4.92-8+deb10u6
[hcoop/debian/exim4.git] / debian / patches / 80_02-GnuTLS-tls_write-wait-after-uncorking-the-session.patch
1 From 783cb0301d9ceef2748956c3f91762275b7b45e5 Mon Sep 17 00:00:00 2001
2 From: "Heiko Schlittermann (HS12-RIPE)" <hs@schlittermann.de>
3 Date: Tue, 18 Feb 2020 18:59:49 +0100
4 Subject: [PATCH 5/6] GnuTLS: tls_write(): wait after uncorking the session
5
6 (cherry picked from commit 8f9adfd36222d4e9e730734e00dffe874073e5b4)
7 ---
8 src/tls-gnu.c | 34 ++++++++++++++++++++++++++++------
9 1 file changed, 28 insertions(+), 6 deletions(-)
10
11 diff --git a/src/tls-gnu.c b/src/tls-gnu.c
12 index 822ad89c6..94a718673 100644
13 --- a/src/tls-gnu.c
14 +++ b/src/tls-gnu.c
15 @@ -2835,9 +2835,14 @@ tls_write(void * ct_ctx, const uschar * buff, size_t len, BOOL more)
16 ssize_t outbytes;
17 size_t left = len;
18 exim_gnutls_state_st * state = ct_ctx ? ct_ctx : &state_server;
19 -#ifdef SUPPORT_CORK
20
21 -if (more && !state->corked) gnutls_record_cork(state->session);
22 +#ifdef SUPPORT_CORK
23 +if (more && !state->corked)
24 + {
25 + DEBUG(D_tls) debug_printf("gnutls_record_cork(session=%p)\n", state->session);
26 + gnutls_record_cork(state->session);
27 + state->corked = TRUE;
28 + }
29 #endif
30
31 DEBUG(D_tls) debug_printf("%s(%p, " SIZE_T_FMT "%s)\n", __FUNCTION__,
32 @@ -2853,6 +2858,7 @@ while (left > 0)
33 while (outbytes == GNUTLS_E_AGAIN);
34
35 DEBUG(D_tls) debug_printf("outbytes=" SSIZE_T_FMT "\n", outbytes);
36 +
37 if (outbytes < 0)
38 {
39 DEBUG(D_tls) debug_printf("%s: gnutls_record_send err\n", __FUNCTION__);
40 @@ -2878,10 +2884,26 @@ if (len > INT_MAX)
41 }
42
43 #ifdef SUPPORT_CORK
44 -if (more != state->corked)
45 - {
46 - if (!more) (void) gnutls_record_uncork(state->session, 0);
47 - state->corked = more;
48 +if (!more && state->corked)
49 + {
50 + DEBUG(D_tls) debug_printf("gnutls_record_uncork(session=%p)\n", state->session);
51 + do {
52 + do
53 + /* We can't use GNUTLS_RECORD_WAIT here, as it retries on
54 + GNUTLS_E_AGAIN || GNUTLS_E_INTR, which would break our timeout set by alarm().
55 + The GNUTLS_E_AGAIN should not happen ever, as our sockets are blocking anyway.
56 + But who knows. (That all relies on the fact that GNUTLS_E_INTR and GNUTLS_E_AGAIN
57 + match the EINTR and EAGAIN errno values.) */
58 + outbytes = gnutls_record_uncork(state->session, 0);
59 + while (outbytes == GNUTLS_E_AGAIN);
60 +
61 + if (outbytes < 0)
62 + {
63 + record_io_error(state, len, US"uncork", NULL);
64 + return -1;
65 + }
66 + } while (gnutls_record_check_corked(state->session) > 0);
67 + state->corked = FALSE;
68 }
69 #endif
70
71 --
72 2.28.0
73