haproxy: Update HAProxy to v1.8.4 (+patches)lilik-openwrt-22.03
@ -1,158 +0,0 @@ | |||
From 912e8f18ef274fdda0a522b2aa8255bddd00fb7b Mon Sep 17 00:00:00 2001 | |||
From: Willy Tarreau <w@1wt.eu> | |||
Date: Wed, 30 Aug 2017 07:35:35 +0200 | |||
Subject: [PATCH] BUG/MEDIUM: connection: remove useless flag CO_FL_DATA_RD_SH | |||
This flag is both confusing and wrong. It is supposed to report the | |||
fact that the data layer has received a shutdown, but in fact this is | |||
reported by CO_FL_SOCK_RD_SH which is set by the transport layer after | |||
this condition is detected. The only case where the flag above is set | |||
is in the stream interface where CF_SHUTR is also set on the receiving | |||
channel. | |||
In addition, it was checked in the health checks code (while never set) | |||
and was always test jointly with CO_FL_SOCK_RD_SH everywhere, except in | |||
conn_data_read0_pending() which incorrectly doesn't match the second | |||
time it's called and is fortunately protected by an extra check on | |||
(ic->flags & CF_SHUTR). | |||
This patch gets rid of the flag completely. Now conn_data_read0_pending() | |||
accurately reports the fact that the transport layer has detected the end | |||
of the stream, regardless of the fact that this state was already consumed, | |||
and the stream interface watches ic->flags&CF_SHUTR to know if the channel | |||
was already closed by the upper layer (which it already used to do). | |||
The now unused conn_data_read0() function was removed. | |||
(cherry picked from commit 54e917cfa1e7b0539550ae32c48c76da2f169041) | |||
[wt: this happens to fix a real bug which occasionally strikes when | |||
using http-reuse in the rare case where a server shuts down after | |||
providing its response but before the connection is put back into | |||
the idle pool, and it gets immediately recycled for another request, | |||
without first passing through the idle handler, and the already | |||
reported shutdown is never reported to the second transaction, | |||
causing a loop to last for as long as the server timeout] | |||
--- | |||
contrib/debug/flags.c | 1 - | |||
include/proto/connection.h | 8 +------- | |||
include/types/connection.h | 2 +- | |||
src/checks.c | 4 ++-- | |||
src/stream_interface.c | 11 +++++------ | |||
5 files changed, 9 insertions(+), 17 deletions(-) | |||
diff --git a/contrib/debug/flags.c b/contrib/debug/flags.c | |||
index bc71bde9..19327f34 100644 | |||
--- a/contrib/debug/flags.c | |||
+++ b/contrib/debug/flags.c | |||
@@ -117,7 +117,6 @@ void show_conn_flags(unsigned int f) | |||
SHOW_FLAG(f, CO_FL_SOCK_WR_SH); | |||
SHOW_FLAG(f, CO_FL_SOCK_RD_SH); | |||
SHOW_FLAG(f, CO_FL_DATA_WR_SH); | |||
- SHOW_FLAG(f, CO_FL_DATA_RD_SH); | |||
SHOW_FLAG(f, CO_FL_WAKE_DATA); | |||
SHOW_FLAG(f, CO_FL_INIT_DATA); | |||
SHOW_FLAG(f, CO_FL_ADDR_TO_SET); | |||
diff --git a/include/proto/connection.h b/include/proto/connection.h | |||
index fce60259..eb68322a 100644 | |||
--- a/include/proto/connection.h | |||
+++ b/include/proto/connection.h | |||
@@ -413,12 +413,6 @@ static inline void conn_sock_read0(struct connection *c) | |||
fdtab[c->t.sock.fd].linger_risk = 0; | |||
} | |||
-static inline void conn_data_read0(struct connection *c) | |||
-{ | |||
- c->flags |= CO_FL_DATA_RD_SH; | |||
- __conn_data_stop_recv(c); | |||
-} | |||
- | |||
static inline void conn_sock_shutw(struct connection *c) | |||
{ | |||
c->flags |= CO_FL_SOCK_WR_SH; | |||
@@ -450,7 +444,7 @@ static inline void conn_data_shutw_hard(struct connection *c) | |||
/* detect sock->data read0 transition */ | |||
static inline int conn_data_read0_pending(struct connection *c) | |||
{ | |||
- return (c->flags & (CO_FL_DATA_RD_SH | CO_FL_SOCK_RD_SH)) == CO_FL_SOCK_RD_SH; | |||
+ return (c->flags & CO_FL_SOCK_RD_SH) != 0; | |||
} | |||
/* detect data->sock shutw transition */ | |||
diff --git a/include/types/connection.h b/include/types/connection.h | |||
index 02eac932..90e8e073 100644 | |||
--- a/include/types/connection.h | |||
+++ b/include/types/connection.h | |||
@@ -90,7 +90,7 @@ enum { | |||
CO_FL_WAKE_DATA = 0x00008000, /* wake-up data layer upon activity at the transport layer */ | |||
/* flags used to remember what shutdown have been performed/reported */ | |||
- CO_FL_DATA_RD_SH = 0x00010000, /* DATA layer was notified about shutr/read0 */ | |||
+ /* unused : 0x00010000 */ | |||
CO_FL_DATA_WR_SH = 0x00020000, /* DATA layer asked for shutw */ | |||
CO_FL_SOCK_RD_SH = 0x00040000, /* SOCK layer was notified about shutr/read0 */ | |||
CO_FL_SOCK_WR_SH = 0x00080000, /* SOCK layer asked for shutw */ | |||
diff --git a/src/checks.c b/src/checks.c | |||
index ca3881a5..6c5e3cbc 100644 | |||
--- a/src/checks.c | |||
+++ b/src/checks.c | |||
@@ -839,7 +839,7 @@ static void event_srv_chk_r(struct connection *conn) | |||
done = 0; | |||
conn->xprt->rcv_buf(conn, check->bi, check->bi->size); | |||
- if (conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_DATA_RD_SH)) { | |||
+ if (conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH)) { | |||
done = 1; | |||
if ((conn->flags & CO_FL_ERROR) && !check->bi->i) { | |||
/* Report network errors only if we got no other data. Otherwise | |||
@@ -2892,7 +2892,7 @@ static void tcpcheck_main(struct connection *conn) | |||
goto out_end_tcpcheck; | |||
if (conn->xprt->rcv_buf(conn, check->bi, check->bi->size) <= 0) { | |||
- if (conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_DATA_RD_SH)) { | |||
+ if (conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH)) { | |||
done = 1; | |||
if ((conn->flags & CO_FL_ERROR) && !check->bi->i) { | |||
/* Report network errors only if we got no other data. Otherwise | |||
diff --git a/src/stream_interface.c b/src/stream_interface.c | |||
index 836487bd..aba49c94 100644 | |||
--- a/src/stream_interface.c | |||
+++ b/src/stream_interface.c | |||
@@ -1060,14 +1060,14 @@ static void si_conn_recv_cb(struct connection *conn) | |||
if (conn->flags & CO_FL_ERROR) | |||
return; | |||
- /* stop here if we reached the end of data */ | |||
- if (conn_data_read0_pending(conn)) | |||
- goto out_shutdown_r; | |||
- | |||
/* maybe we were called immediately after an asynchronous shutr */ | |||
if (ic->flags & CF_SHUTR) | |||
return; | |||
+ /* stop here if we reached the end of data */ | |||
+ if (conn_data_read0_pending(conn)) | |||
+ goto out_shutdown_r; | |||
+ | |||
cur_read = 0; | |||
if ((ic->flags & (CF_STREAMER | CF_STREAMER_FAST)) && !ic->buf->o && | |||
@@ -1153,7 +1153,7 @@ static void si_conn_recv_cb(struct connection *conn) | |||
* that if such an event is not handled above in splice, it will be handled here by | |||
* recv(). | |||
*/ | |||
- while (!(conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_DATA_RD_SH | CO_FL_WAIT_ROOM | CO_FL_HANDSHAKE))) { | |||
+ while (!(conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_WAIT_ROOM | CO_FL_HANDSHAKE)) && !(ic->flags & CF_SHUTR)) { | |||
max = channel_recv_max(ic); | |||
if (!max) { | |||
@@ -1267,7 +1267,6 @@ static void si_conn_recv_cb(struct connection *conn) | |||
if (ic->flags & CF_AUTO_CLOSE) | |||
channel_shutw_now(ic); | |||
stream_sock_read0(si); | |||
- conn_data_read0(conn); | |||
return; | |||
} | |||
-- | |||
2.13.5 | |||
@ -0,0 +1,61 @@ | |||
From 2fcd544272a5498ffa49544e9f06b51bc93e55d1 Mon Sep 17 00:00:00 2001 | |||
From: Olivier Houchard <ohouchard@haproxy.com> | |||
Date: Tue, 13 Feb 2018 15:17:23 +0100 | |||
Subject: [PATCH] BUG/MEDIUM: ssl: Don't always treat SSL_ERROR_SYSCALL as | |||
unrecovarable. | |||
Bart Geesink reported some random errors appearing under the form of | |||
termination flags SD in the logs for connections involving SSL traffic | |||
to reach the servers. | |||
Tomek Gacek and Mateusz Malek finally narrowed down the problem to commit | |||
c2aae74 ("MEDIUM: ssl: Handle early data with OpenSSL 1.1.1"). It happens | |||
that the special case of SSL_ERROR_SYSCALL isn't handled anymore since | |||
this commit. | |||
SSL_read() might return <= 0, and SSL_get_erro() return SSL_ERROR_SYSCALL, | |||
without meaning the connection is gone. Before flagging the connection | |||
as in error, check the errno value. | |||
This should be backported to 1.8. | |||
(cherry picked from commit 7e2e505006feb8f3b4a7f9e0ac5e89b5a8c4895e) | |||
Signed-off-by: Willy Tarreau <w@1wt.eu> | |||
--- | |||
src/ssl_sock.c | 9 ++++++++- | |||
1 file changed, 8 insertions(+), 1 deletion(-) | |||
diff --git a/src/ssl_sock.c b/src/ssl_sock.c | |||
index aecf3dd..f118724 100644 | |||
--- a/src/ssl_sock.c | |||
+++ b/src/ssl_sock.c | |||
@@ -5437,6 +5437,12 @@ static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int coun | |||
break; | |||
} else if (ret == SSL_ERROR_ZERO_RETURN) | |||
goto read0; | |||
+ /* For SSL_ERROR_SYSCALL, make sure the error is | |||
+ * unrecoverable before flagging the connection as | |||
+ * in error. | |||
+ */ | |||
+ if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN)) | |||
+ goto clear_ssl_error; | |||
/* otherwise it's a real error */ | |||
goto out_error; | |||
} | |||
@@ -5451,11 +5457,12 @@ static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int coun | |||
conn_sock_read0(conn); | |||
goto leave; | |||
out_error: | |||
+ conn->flags |= CO_FL_ERROR; | |||
+clear_ssl_error: | |||
/* Clear openssl global errors stack */ | |||
ssl_sock_dump_errors(conn); | |||
ERR_clear_error(); | |||
- conn->flags |= CO_FL_ERROR; | |||
goto leave; | |||
} | |||
-- | |||
1.7.10.4 | |||
@ -0,0 +1,63 @@ | |||
From f7fa1d461aa71bbc8a6c23fdcfc305f2e52ce5dd Mon Sep 17 00:00:00 2001 | |||
From: Christopher Faulet <cfaulet@haproxy.com> | |||
Date: Mon, 19 Feb 2018 14:25:15 +0100 | |||
Subject: [PATCH] BUG/MEDIUM: ssl: Shutdown the connection for reading on | |||
SSL_ERROR_SYSCALL | |||
When SSL_read returns SSL_ERROR_SYSCALL and errno is unset or set to EAGAIN, the | |||
connection must be shut down for reading. Else, the connection loops infinitly, | |||
consuming all the CPU. | |||
The bug was introduced in the commit 7e2e50500 ("BUG/MEDIUM: ssl: Don't always | |||
treat SSL_ERROR_SYSCALL as unrecovarable."). This patch must be backported in | |||
1.8 too. | |||
(cherry picked from commit 4ac77a98cda3d0f9b1d9de7bbbda2c91357f0767) | |||
Signed-off-by: Willy Tarreau <w@1wt.eu> | |||
--- | |||
src/ssl_sock.c | 14 ++++++++------ | |||
1 file changed, 8 insertions(+), 6 deletions(-) | |||
diff --git a/src/ssl_sock.c b/src/ssl_sock.c | |||
index f118724..a065bbb 100644 | |||
--- a/src/ssl_sock.c | |||
+++ b/src/ssl_sock.c | |||
@@ -5437,10 +5437,9 @@ static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int coun | |||
break; | |||
} else if (ret == SSL_ERROR_ZERO_RETURN) | |||
goto read0; | |||
- /* For SSL_ERROR_SYSCALL, make sure the error is | |||
- * unrecoverable before flagging the connection as | |||
- * in error. | |||
- */ | |||
+ /* For SSL_ERROR_SYSCALL, make sure to clear the error | |||
+ * stack before shutting down the connection for | |||
+ * reading. */ | |||
if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN)) | |||
goto clear_ssl_error; | |||
/* otherwise it's a real error */ | |||
@@ -5453,16 +5452,19 @@ static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int coun | |||
conn_cond_update_sock_polling(conn); | |||
return done; | |||
+ clear_ssl_error: | |||
+ /* Clear openssl global errors stack */ | |||
+ ssl_sock_dump_errors(conn); | |||
+ ERR_clear_error(); | |||
read0: | |||
conn_sock_read0(conn); | |||
goto leave; | |||
+ | |||
out_error: | |||
conn->flags |= CO_FL_ERROR; | |||
-clear_ssl_error: | |||
/* Clear openssl global errors stack */ | |||
ssl_sock_dump_errors(conn); | |||
ERR_clear_error(); | |||
- | |||
goto leave; | |||
} | |||
-- | |||
1.7.10.4 | |||
@ -0,0 +1,69 @@ | |||
From 8a5949f2d74c3a3a6c6da25449992c312b183ef3 Mon Sep 17 00:00:00 2001 | |||
From: Christopher Faulet <cfaulet@haproxy.com> | |||
Date: Fri, 2 Feb 2018 15:54:15 +0100 | |||
Subject: [PATCH] BUG/MEDIUM: http: Switch the HTTP response in tunnel mode as | |||
earlier as possible | |||
When the body length is undefined (no Content-Length or Transfer-Encoding | |||
headers), The reponse remains in ending mode, waiting the request is done. So, | |||
most of time this is not a problem because the resquest is done before the | |||
response. But when a client sends data to a server that replies without waiting | |||
all the data, it is really not desirable to wait the end of the request to | |||
finish the response. | |||
This bug was introduced when the tunneling of the request and the reponse was | |||
refactored, in commit 4be980391 ("MINOR: http: Switch requests/responses in | |||
TUNNEL mode only by checking txn flag"). | |||
This patch should be backported in 1.8 and 1.7. | |||
(cherry picked from commit fd04fcf5edb0a24cd29ce8f4d4dc2aa3a0e2e82c) | |||
Signed-off-by: Willy Tarreau <w@1wt.eu> | |||
--- | |||
src/proto_http.c | 15 +++++---------- | |||
1 file changed, 5 insertions(+), 10 deletions(-) | |||
diff --git a/src/proto_http.c b/src/proto_http.c | |||
index 64bd410..29880ea 100644 | |||
--- a/src/proto_http.c | |||
+++ b/src/proto_http.c | |||
@@ -4634,16 +4634,8 @@ int http_sync_res_state(struct stream *s) | |||
* let's enforce it now that we're not expecting any new | |||
* data to come. The caller knows the stream is complete | |||
* once both states are CLOSED. | |||
- * | |||
- * However, there is an exception if the response length | |||
- * is undefined. In this case, we switch in TUNNEL mode. | |||
*/ | |||
- if (!(txn->rsp.flags & HTTP_MSGF_XFER_LEN)) { | |||
- channel_auto_read(chn); | |||
- txn->rsp.msg_state = HTTP_MSG_TUNNEL; | |||
- chn->flags |= CF_NEVER_WAIT; | |||
- } | |||
- else if (!(chn->flags & (CF_SHUTW|CF_SHUTW_NOW))) { | |||
+ if (!(chn->flags & (CF_SHUTW|CF_SHUTW_NOW))) { | |||
channel_shutr_now(chn); | |||
channel_shutw_now(chn); | |||
} | |||
@@ -6241,6 +6233,8 @@ http_msg_forward_body(struct stream *s, struct http_msg *msg) | |||
/* The server still sending data that should be filtered */ | |||
if (!(chn->flags & CF_SHUTR) && HAS_DATA_FILTERS(s, chn)) | |||
goto missing_data_or_waiting; | |||
+ msg->msg_state = HTTP_MSG_TUNNEL; | |||
+ goto ending; | |||
} | |||
msg->msg_state = HTTP_MSG_ENDING; | |||
@@ -6262,7 +6256,8 @@ http_msg_forward_body(struct stream *s, struct http_msg *msg) | |||
/* default_ret */ 1, | |||
/* on_error */ goto error, | |||
/* on_wait */ goto waiting); | |||
- msg->msg_state = HTTP_MSG_DONE; | |||
+ if (msg->msg_state == HTTP_MSG_ENDING) | |||
+ msg->msg_state = HTTP_MSG_DONE; | |||
return 1; | |||
missing_data_or_waiting: | |||
-- | |||
1.7.10.4 | |||
@ -0,0 +1,103 @@ | |||
From 7ccf7c9791f2b2329f3940d1347618af3a77bebc Mon Sep 17 00:00:00 2001 | |||
From: Emeric Brun <ebrun@haproxy.com> | |||
Date: Mon, 19 Feb 2018 15:59:48 +0100 | |||
Subject: [PATCH] BUG/MEDIUM: ssl/sample: ssl_bc_* fetch keywords are broken. | |||
Since the split between connections and conn-stream objects, this | |||
keywords are broken. | |||
This patch must be backported in 1.8 | |||
(cherry picked from commit eb8def9f34c37537d56a69fcd211d4c4c8006bea) | |||
Signed-off-by: Willy Tarreau <w@1wt.eu> | |||
--- | |||
src/ssl_sock.c | 31 ++++++++++++++----------------- | |||
1 file changed, 14 insertions(+), 17 deletions(-) | |||
diff --git a/src/ssl_sock.c b/src/ssl_sock.c | |||
index 4d0d5db..d832d76 100644 | |||
--- a/src/ssl_sock.c | |||
+++ b/src/ssl_sock.c | |||
@@ -6580,8 +6580,8 @@ smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char * | |||
static int | |||
smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private) | |||
{ | |||
- struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin : | |||
- smp->strm ? smp->strm->si[1].end : NULL); | |||
+ struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) : | |||
+ smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL; | |||
smp->data.type = SMP_T_BOOL; | |||
smp->data.u.sint = (conn && conn->xprt == &ssl_sock); | |||
@@ -6625,8 +6625,8 @@ smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const ch | |||
static int | |||
smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private) | |||
{ | |||
- struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin : | |||
- smp->strm ? smp->strm->si[1].end : NULL); | |||
+ struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) : | |||
+ smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL; | |||
smp->flags = 0; | |||
if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock) | |||
@@ -6651,9 +6651,8 @@ smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char * | |||
static int | |||
smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private) | |||
{ | |||
- struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin : | |||
- smp->strm ? smp->strm->si[1].end : NULL); | |||
- | |||
+ struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) : | |||
+ smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL; | |||
int sint; | |||
smp->flags = 0; | |||
@@ -6676,8 +6675,8 @@ smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const c | |||
static int | |||
smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private) | |||
{ | |||
- struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin : | |||
- smp->strm ? smp->strm->si[1].end : NULL); | |||
+ struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) : | |||
+ smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL; | |||
smp->flags = 0; | |||
if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock) | |||
@@ -6747,8 +6746,8 @@ smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw | |||
static int | |||
smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private) | |||
{ | |||
- struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin : | |||
- smp->strm ? smp->strm->si[1].end : NULL); | |||
+ struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) : | |||
+ smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL; | |||
smp->flags = 0; | |||
if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock) | |||
@@ -6773,9 +6772,8 @@ static int | |||
smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private) | |||
{ | |||
#if OPENSSL_VERSION_NUMBER > 0x0090800fL | |||
- struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin : | |||
- smp->strm ? smp->strm->si[1].end : NULL); | |||
- | |||
+ struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) : | |||
+ smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL; | |||
SSL_SESSION *ssl_sess; | |||
smp->flags = SMP_F_CONST; | |||
@@ -6917,9 +6915,8 @@ static int | |||
smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private) | |||
{ | |||
#if OPENSSL_VERSION_NUMBER > 0x0090800fL | |||
- struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin : | |||
- smp->strm ? smp->strm->si[1].end : NULL); | |||
- | |||
+ struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) : | |||
+ smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL; | |||
int finished_len; | |||
struct chunk *finished_trash; | |||
-- | |||
1.7.10.4 | |||