diff --git a/backport-BUG-MEDIUM-connection-Clear-flags-when-a-conn-is-rem.patch b/backport-BUG-MEDIUM-connection-Clear-flags-when-a-conn-is-rem.patch new file mode 100644 index 0000000000000000000000000000000000000000..f0446d4bb951c027927f7c9d5355a08bf1eced18 --- /dev/null +++ b/backport-BUG-MEDIUM-connection-Clear-flags-when-a-conn-is-rem.patch @@ -0,0 +1,134 @@ +From d7be206d3570138cfadca87bb768293804629bc7 Mon Sep 17 00:00:00 2001 +From: Christopher Faulet +Date: Tue, 28 Feb 2023 15:39:38 +0100 +Subject: [PATCH] BUG/MEDIUM: connection: Clear flags when a conn is removed + from an idle list + +When a connection is removed from the safe list or the idle list, +CO_FL_SAFE_LIST and CO_FL_IDLE_LIST flags must be cleared. It is performed +when the connection is reused. But not when it is moved into the +toremove_conns list. It may be an issue because the multiplexer owning the +connection may be woken up before the connection is really removed. If the +connection flags are not sanitized, it may think the connection is idle and +reinsert it in the corresponding list. From this point, we can imagine +several bugs. An UAF or a connection reused with an invalid state for +instance. + +To avoid any issue, the connection flags are sanitized when an idle +connection is moved into the toremove_conns list. The same is performed at +right places in the multiplexers. Especially because the connection release +may be delayed (for h2 and fcgi connections). + +This patch shoudld fix the issue #2057. It must carefully be backported as +far as 2.2. Especially on the 2.2 where the code is really different. But +some conflicts should be expected on the 2.4 too. + +(cherry picked from commit 5e1b0e7bf86a300def07388df0ea7f4b3f9e68b9) +Signed-off-by: Christopher Faulet +(cherry picked from commit 7902ebadb1ffbe0237ce974b950ca595894f3774) +Signed-off-by: Willy Tarreau + +Conflict: NA +Reference: https://git.haproxy.org/?p=haproxy-2.6.git;a=commit;h=d7be206d3570138cfadca87bb768293804629bc7 +--- + src/mux_fcgi.c | 4 +++- + src/mux_h1.c | 4 +++- + src/mux_h2.c | 7 ++++++- + src/server.c | 2 ++ + 4 files changed, 14 insertions(+), 3 deletions(-) + +diff --git a/src/mux_fcgi.c b/src/mux_fcgi.c +index c93ddd4..5a040bf 100644 +--- a/src/mux_fcgi.c ++++ b/src/mux_fcgi.c +@@ -3221,8 +3221,10 @@ struct task *fcgi_timeout_task(struct task *t, void *context, unsigned int state + /* We're about to destroy the connection, so make sure nobody attempts + * to steal it from us. + */ +- if (fconn->conn->flags & CO_FL_LIST_MASK) ++ if (fconn->conn->flags & CO_FL_LIST_MASK) { + conn_delete_from_tree(&fconn->conn->hash_node->node); ++ fconn->conn->flags &= ~CO_FL_LIST_MASK; ++ } + + HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock); + } +diff --git a/src/mux_h1.c b/src/mux_h1.c +index 67d4234..a26e99c 100644 +--- a/src/mux_h1.c ++++ b/src/mux_h1.c +@@ -3281,8 +3281,10 @@ struct task *h1_timeout_task(struct task *t, void *context, unsigned int state) + /* We're about to destroy the connection, so make sure nobody attempts + * to steal it from us. + */ +- if (h1c->conn->flags & CO_FL_LIST_MASK) ++ if (h1c->conn->flags & CO_FL_LIST_MASK) { + conn_delete_from_tree(&h1c->conn->hash_node->node); ++ h1c->conn->flags &= ~CO_FL_LIST_MASK; ++ } + + HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock); + } +diff --git a/src/mux_h2.c b/src/mux_h2.c +index 2215c8b..9b319c6 100644 +--- a/src/mux_h2.c ++++ b/src/mux_h2.c +@@ -4147,6 +4147,7 @@ static int h2_process(struct h2c *h2c) + if (conn->flags & CO_FL_LIST_MASK) { + HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock); + conn_delete_from_tree(&conn->hash_node->node); ++ conn->flags &= ~CO_FL_LIST_MASK; + HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock); + } + } +@@ -4155,6 +4156,7 @@ static int h2_process(struct h2c *h2c) + if (conn->flags & CO_FL_LIST_MASK) { + HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock); + conn_delete_from_tree(&conn->hash_node->node); ++ conn->flags &= ~CO_FL_LIST_MASK; + HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock); + } + } +@@ -4235,8 +4237,10 @@ struct task *h2_timeout_task(struct task *t, void *context, unsigned int state) + /* We're about to destroy the connection, so make sure nobody attempts + * to steal it from us. + */ +- if (h2c->conn->flags & CO_FL_LIST_MASK) ++ if (h2c->conn->flags & CO_FL_LIST_MASK) { + conn_delete_from_tree(&h2c->conn->hash_node->node); ++ h2c->conn->flags &= ~CO_FL_LIST_MASK; ++ } + + HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock); + } +@@ -4289,6 +4293,7 @@ struct task *h2_timeout_task(struct task *t, void *context, unsigned int state) + if (h2c->conn->flags & CO_FL_LIST_MASK) { + HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock); + conn_delete_from_tree(&h2c->conn->hash_node->node); ++ h2c->conn->flags &= ~CO_FL_LIST_MASK; + HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock); + } + +diff --git a/src/server.c b/src/server.c +index f35190d..b8e1f0a 100644 +--- a/src/server.c ++++ b/src/server.c +@@ -5714,6 +5714,7 @@ static int srv_migrate_conns_to_remove(struct eb_root *idle_tree, struct mt_list + + hash_node = ebmb_entry(node, struct conn_hash_node, node); + eb_delete(node); ++ hash_node->conn->flags &= ~CO_FL_LIST_MASK; + MT_LIST_APPEND(toremove_list, &hash_node->conn->toremove_list); + i++; + +@@ -5771,6 +5772,7 @@ void srv_release_conn(struct server *srv, struct connection *conn) + /* Remove the connection from any tree (safe, idle or available) */ + HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock); + conn_delete_from_tree(&conn->hash_node->node); ++ conn->flags &= ~CO_FL_LIST_MASK; + HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock); + } + +-- +2.33.0 + diff --git a/backport-BUG-MEDIUM-connection-Preserve-flags-when-a-conn-is-.patch b/backport-BUG-MEDIUM-connection-Preserve-flags-when-a-conn-is-.patch new file mode 100644 index 0000000000000000000000000000000000000000..c18468375c73aa1e0d7d930b3135154c3123db4f --- /dev/null +++ b/backport-BUG-MEDIUM-connection-Preserve-flags-when-a-conn-is-.patch @@ -0,0 +1,212 @@ +From a53fdaf7203e45f67c44d7e250cec36875ea8e01 Mon Sep 17 00:00:00 2001 +From: Christopher Faulet +Date: Thu, 16 Mar 2023 11:43:05 +0100 +Subject: [PATCH] BUG/MEDIUM: connection: Preserve flags when a conn is removed + from an idle list + +The commit 5e1b0e7bf ("BUG/MEDIUM: connection: Clear flags when a conn is +removed from an idle list") introduced a regression. CO_FL_SAFE_LIST and +CO_FL_IDLE_LIST flags are used when the connection is released to properly +decrement used/idle connection counters. if a connection is idle, these +flags must be preserved till the connection is really released. It may be +removed from the list but not immediately released. If these flags are lost +when it is finally released, the current number of used connections is +erroneously decremented. If means this counter may become negative and the +counters tracking the number of idle connecitons is not decremented, +suggesting a leak. + +So, the above commit is reverted and instead we improve a bit the way to +detect an idle connection. The function conn_get_idle_flag() must now be +used to know if a connection is in an idle list. It returns the connection +flag corresponding to the idle list if the connection is idle +(CO_FL_SAFE_LIST or CO_FL_IDLE_LIST) or 0 otherwise. But if the connection +is scheduled to be removed, 0 is also returned, regardless the connection +flags. + +This new function is used when the connection is temporarily removed from +the list to be used, mainly in muxes. + +This patch should fix #2078 and #2057. It must be backported as far as 2.2. + +(cherry picked from commit 3a7b539b124bccaa57478e0a5a6d66338594615a) +Signed-off-by: Christopher Faulet +(cherry picked from commit a81a1e2aea0793aa624565a14cb7579b907f116a) +Signed-off-by: Christopher Faulet + +Conflict: NA +Reference: https://git.haproxy.org/?p=haproxy-2.6.git;a=commit;h=a53fdaf7203e45f67c44d7e250cec36875ea8e01 +--- + include/haproxy/connection.h | 10 ++++++++++ + src/connection.c | 2 +- + src/mux_fcgi.c | 6 ++---- + src/mux_h1.c | 6 ++---- + src/mux_h2.c | 10 ++-------- + src/server.c | 1 - + src/ssl_sock.c | 2 +- + 7 files changed, 18 insertions(+), 19 deletions(-) + +diff --git a/include/haproxy/connection.h b/include/haproxy/connection.h +index 4d289e7b3..8cf22ef4f 100644 +--- a/include/haproxy/connection.h ++++ b/include/haproxy/connection.h +@@ -316,6 +316,16 @@ static inline void conn_set_private(struct connection *conn) + } + } + ++/* Used to know if a connection is in an idle list. It returns connection flag ++ * corresponding to the idle list if the connection is idle (CO_FL_SAFE_LIST or ++ * CO_FL_IDLE_LIST) or 0 otherwise. Note that if the connection is scheduled to ++ * be removed, 0 is returned, regardless the connection flags. ++ */ ++static inline unsigned int conn_get_idle_flag(const struct connection *conn) ++{ ++ return (!MT_LIST_INLIST(&conn->toremove_list) ? conn->flags & CO_FL_LIST_MASK : 0); ++} ++ + static inline void conn_force_unsubscribe(struct connection *conn) + { + if (!conn->subs) +diff --git a/src/connection.c b/src/connection.c +index 4a73dbcc8..5a459fd98 100644 +--- a/src/connection.c ++++ b/src/connection.c +@@ -146,7 +146,7 @@ int conn_notify_mux(struct connection *conn, int old_flags, int forced_wake) + ((conn->flags ^ old_flags) & CO_FL_NOTIFY_DONE) || + ((old_flags & CO_FL_WAIT_XPRT) && !(conn->flags & CO_FL_WAIT_XPRT))) && + conn->mux && conn->mux->wake) { +- uint conn_in_list = conn->flags & CO_FL_LIST_MASK; ++ uint conn_in_list = conn_get_idle_flag(conn); + struct server *srv = objt_server(conn->target); + + if (conn_in_list) { +diff --git a/src/mux_fcgi.c b/src/mux_fcgi.c +index 4981f6bab..2c417dd1f 100644 +--- a/src/mux_fcgi.c ++++ b/src/mux_fcgi.c +@@ -3043,7 +3043,7 @@ struct task *fcgi_io_cb(struct task *t, void *ctx, unsigned int state) + conn = fconn->conn; + TRACE_POINT(FCGI_EV_FCONN_WAKE, conn); + +- conn_in_list = conn->flags & CO_FL_LIST_MASK; ++ conn_in_list = conn_get_idle_flag(conn); + if (conn_in_list) + conn_delete_from_tree(&conn->hash_node->node); + +@@ -3227,10 +3227,8 @@ struct task *fcgi_timeout_task(struct task *t, void *context, unsigned int state + /* We're about to destroy the connection, so make sure nobody attempts + * to steal it from us. + */ +- if (fconn->conn->flags & CO_FL_LIST_MASK) { ++ if (fconn->conn->flags & CO_FL_LIST_MASK) + conn_delete_from_tree(&fconn->conn->hash_node->node); +- fconn->conn->flags &= ~CO_FL_LIST_MASK; +- } + + HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock); + } +diff --git a/src/mux_h1.c b/src/mux_h1.c +index 56b08a77e..6f59b3112 100644 +--- a/src/mux_h1.c ++++ b/src/mux_h1.c +@@ -3158,7 +3158,7 @@ struct task *h1_io_cb(struct task *t, void *ctx, unsigned int state) + /* Remove the connection from the list, to be sure nobody attempts + * to use it while we handle the I/O events + */ +- conn_in_list = conn->flags & CO_FL_LIST_MASK; ++ conn_in_list = conn_get_idle_flag(conn); + if (conn_in_list) + conn_delete_from_tree(&conn->hash_node->node); + +@@ -3282,10 +3282,8 @@ struct task *h1_timeout_task(struct task *t, void *context, unsigned int state) + /* We're about to destroy the connection, so make sure nobody attempts + * to steal it from us. + */ +- if (h1c->conn->flags & CO_FL_LIST_MASK) { ++ if (h1c->conn->flags & CO_FL_LIST_MASK) + conn_delete_from_tree(&h1c->conn->hash_node->node); +- h1c->conn->flags &= ~CO_FL_LIST_MASK; +- } + + HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock); + } +diff --git a/src/mux_h2.c b/src/mux_h2.c +index f4cb5b188..b62a8f60e 100644 +--- a/src/mux_h2.c ++++ b/src/mux_h2.c +@@ -4027,11 +4027,10 @@ struct task *h2_io_cb(struct task *t, void *ctx, unsigned int state) + conn = h2c->conn; + TRACE_ENTER(H2_EV_H2C_WAKE, conn); + +- conn_in_list = conn->flags & CO_FL_LIST_MASK; +- + /* Remove the connection from the list, to be sure nobody attempts + * to use it while we handle the I/O events + */ ++ conn_in_list = conn_get_idle_flag(conn); + if (conn_in_list) + conn_delete_from_tree(&conn->hash_node->node); + +@@ -4163,7 +4162,6 @@ static int h2_process(struct h2c *h2c) + if (conn->flags & CO_FL_LIST_MASK) { + HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock); + conn_delete_from_tree(&conn->hash_node->node); +- conn->flags &= ~CO_FL_LIST_MASK; + HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock); + } + } +@@ -4172,7 +4170,6 @@ static int h2_process(struct h2c *h2c) + if (conn->flags & CO_FL_LIST_MASK) { + HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock); + conn_delete_from_tree(&conn->hash_node->node); +- conn->flags &= ~CO_FL_LIST_MASK; + HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock); + } + } +@@ -4253,10 +4250,8 @@ struct task *h2_timeout_task(struct task *t, void *context, unsigned int state) + /* We're about to destroy the connection, so make sure nobody attempts + * to steal it from us. + */ +- if (h2c->conn->flags & CO_FL_LIST_MASK) { ++ if (h2c->conn->flags & CO_FL_LIST_MASK) + conn_delete_from_tree(&h2c->conn->hash_node->node); +- h2c->conn->flags &= ~CO_FL_LIST_MASK; +- } + + HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock); + } +@@ -4309,7 +4304,6 @@ struct task *h2_timeout_task(struct task *t, void *context, unsigned int state) + if (h2c->conn->flags & CO_FL_LIST_MASK) { + HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock); + conn_delete_from_tree(&h2c->conn->hash_node->node); +- h2c->conn->flags &= ~CO_FL_LIST_MASK; + HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock); + } + +diff --git a/src/server.c b/src/server.c +index 8a282bcf9..d701eaeab 100644 +--- a/src/server.c ++++ b/src/server.c +@@ -5717,7 +5717,6 @@ static int srv_migrate_conns_to_remove(struct eb_root *idle_tree, struct mt_list + + hash_node = ebmb_entry(node, struct conn_hash_node, node); + eb_delete(node); +- hash_node->conn->flags &= ~CO_FL_LIST_MASK; + MT_LIST_APPEND(toremove_list, &hash_node->conn->toremove_list); + i++; + +diff --git a/src/ssl_sock.c b/src/ssl_sock.c +index 919a08a88..b2f937487 100644 +--- a/src/ssl_sock.c ++++ b/src/ssl_sock.c +@@ -6481,7 +6481,7 @@ struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned int state) + return NULL; + } + conn = ctx->conn; +- conn_in_list = conn->flags & CO_FL_LIST_MASK; ++ conn_in_list = conn_get_idle_flag(conn); + if (conn_in_list) + conn_delete_from_tree(&conn->hash_node->node); + HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock); +-- +2.33.0 + diff --git a/backport-BUG-MEDIUM-stream-do-not-try-to-free-a-failed-stream.patch b/backport-BUG-MEDIUM-stream-do-not-try-to-free-a-failed-stream.patch new file mode 100644 index 0000000000000000000000000000000000000000..cf8ae26ce76a7ff3b7f3bf7de1751a5a7d92bbfa --- /dev/null +++ b/backport-BUG-MEDIUM-stream-do-not-try-to-free-a-failed-stream.patch @@ -0,0 +1,40 @@ +From 3311c72eabc15fc3824cf09537785ccbb1c3b88f Mon Sep 17 00:00:00 2001 +From: Willy Tarreau +Date: Mon, 20 Mar 2023 19:11:08 +0100 +Subject: [PATCH] BUG/MEDIUM: stream: do not try to free a failed stream-conn + +In stream_free() if we fail to allocate s->scb() we go to the path where +we try to free it, and it doesn't like being called with a null at all. +It's easily reproducible with -dMfail,no-cache and "tune.fail-alloc 10" +in the global section. + +This must be backported to 2.6. + +(cherry picked from commit a45e7e81ec54fd0562d8ab4776b4c05584d6d180) +Signed-off-by: Amaury Denoyelle +(cherry picked from commit 8daac8191313b625efeaf2799a4c05b585a44474) +Signed-off-by: Amaury Denoyelle + +Conflict: NA +Reference: https://git.haproxy.org/?p=haproxy-2.6.git;a=commit;h=3311c72eabc15fc3824cf09537785ccbb1c3b88f +--- + src/stream.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/stream.c b/src/stream.c +index 7eaf03995..224b9b8a2 100644 +--- a/src/stream.c ++++ b/src/stream.c +@@ -575,8 +575,8 @@ struct stream *stream_new(struct session *sess, struct stconn *sc, struct buffer + out_fail_accept: + flt_stream_release(s, 0); + LIST_DELETE(&s->list); +- out_fail_alloc_scb: + sc_free(s->scb); ++ out_fail_alloc_scb: + out_fail_attach_scf: + task_destroy(t); + out_fail_alloc: +-- +2.33.0 + diff --git a/backport-BUG-MINOR-http_ana-txn-don-t-re-initialize-txn-and-r.patch b/backport-BUG-MINOR-http_ana-txn-don-t-re-initialize-txn-and-r.patch new file mode 100644 index 0000000000000000000000000000000000000000..90ba951c18021366838e4cd098b302817197f8de --- /dev/null +++ b/backport-BUG-MINOR-http_ana-txn-don-t-re-initialize-txn-and-r.patch @@ -0,0 +1,88 @@ +From 61882cc68c8336016f158f74c0944e1b047c6f5f Mon Sep 17 00:00:00 2001 +From: Aurelien DARRAGON +Date: Fri, 18 Nov 2022 09:17:29 +0100 +Subject: [PATCH] BUG/MINOR: http_ana/txn: don't re-initialize txn and req var + lists + +In http_create_txn(): vars_init_head() was performed on both s->vars_txn +and s->var_reqres lists. + +But this is wrong, these two lists are already initialized upon stream +creation in stream_new(). +Moreover, between stream_new() and http_create_txn(), some variable may +be defined (e.g.: by the frontend), resulting in lists not being empty. + +Because of this "extra" list initialization, already defined variables +can be lost. +This causes txn dependant code not being able to access previously defined +variables as well as memory leak because http_destroy_txn() relies on these +lists to perform the purge. + +This proved to be the case when a frontend sets variables and lua sample +fetch is used in backend section as described in GH #1935. +Many thanks to Darragh O'Toole for his detailed report. + +Removing extra var_init_head (x2) in http_create_txn() to fix the issue. +Adding somme comments in the code in an attempt to prevent future misuses +of s->var_reqres, and s->var_txn lists. + +It should be backported in every stable version. +(This is an old bug that seems to exist since 1.6-dev6) + +[cf: On 2.0 and 1.8, for the legacy HTTP code, vars_init() are used during + the TXN cleanup, when the stream is reused. So, these calls must be + moved from http_init_txn() to http_reset_txn() and not removed.] + +(cherry picked from commit 5ad2b642625b89cdf4f5fd26a598fc480abdc806) +Signed-off-by: Christopher Faulet + +Conflict: NA +Reference: https://git.haproxy.org/?p=haproxy-2.6.git;a=commit;h=61882cc68c8336016f158f74c0944e1b047c6f5f +--- + src/http_ana.c | 6 ++++-- + src/stream.c | 11 ++++++++++- + 2 files changed, 14 insertions(+), 3 deletions(-) + +diff --git a/src/http_ana.c b/src/http_ana.c +index 2b2cfdc56..379b480a8 100644 +--- a/src/http_ana.c ++++ b/src/http_ana.c +@@ -5224,8 +5224,10 @@ struct http_txn *http_create_txn(struct stream *s) + + txn->auth.method = HTTP_AUTH_UNKNOWN; + +- vars_init_head(&s->vars_txn, SCOPE_TXN); +- vars_init_head(&s->vars_reqres, SCOPE_REQ); ++ /* here we don't want to re-initialize s->vars_txn and s->vars_reqres ++ * variable lists, because they were already initialized upon stream ++ * creation in stream_new(), and thus may already contain some variables ++ */ + + return txn; + } +diff --git a/src/stream.c b/src/stream.c +index c04dd565c..7eaf03995 100644 +--- a/src/stream.c ++++ b/src/stream.c +@@ -435,8 +435,17 @@ struct stream *stream_new(struct session *sess, struct stconn *sc, struct buffer + s->req_cap = NULL; + s->res_cap = NULL; + +- /* Initialise all the variables contexts even if not used. ++ /* Initialize all the variables contexts even if not used. + * This permits to prune these contexts without errors. ++ * ++ * We need to make sure that those lists are not re-initialized ++ * by stream-dependant underlying code because we could lose ++ * track of already defined variables, leading to data inconsistency ++ * and memory leaks... ++ * ++ * For reference: we had a very old bug caused by vars_txn and ++ * vars_reqres being accidentally re-initialized in http_create_txn() ++ * (https://github.com/haproxy/haproxy/issues/1935) + */ + vars_init_head(&s->vars_txn, SCOPE_TXN); + vars_init_head(&s->vars_reqres, SCOPE_REQ); +-- +2.33.0 + diff --git a/backport-BUG-MINOR-mworker-prevent-incorrect-values-in-uptime.patch b/backport-BUG-MINOR-mworker-prevent-incorrect-values-in-uptime.patch new file mode 100644 index 0000000000000000000000000000000000000000..04391acea3d7444a32ca5f2eb436fea8ca30024a --- /dev/null +++ b/backport-BUG-MINOR-mworker-prevent-incorrect-values-in-uptime.patch @@ -0,0 +1,111 @@ +From cb9a8fdbaef4a642eeb84ac9feaf636720d18360 Mon Sep 17 00:00:00 2001 +From: William Lallemand +Date: Fri, 17 Feb 2023 16:23:52 +0100 +Subject: [PATCH] BUG/MINOR: mworker: prevent incorrect values in uptime + +Since the recent changes on the clocks, now.tv_sec is not to be used +between processes because it's a clock which is local to the process and +does not contain a real unix timestamp. This patch fixes the issue by +using "data.tv_sec" which is the wall clock instead of "now.tv_sec'. +It prevents having incoherent timestamps. + +It also introduces some checks on negatives values in order to never +displays a netative value if it was computed from a wrong value set by a +previous haproxy version. + +It must be backported as far as 2.0. + +(cherry picked from commit 5a7f83af84d2a08f69ce1629c7609c98f43411ab) +Signed-off-by: Christopher Faulet +(cherry picked from commit 7b8337e0cbaeebec26eab0062f0706f9388e3e2c) +Signed-off-by: Willy Tarreau + +Conflict: NA +Reference: https://git.haproxy.org/?p=haproxy-2.6.git;a=commit;h=cb9a8fdbaef4a642eeb84ac9feaf636720d18360 +--- + src/haproxy.c | 2 +- + src/mworker.c | 21 ++++++++++++++++----- + 2 files changed, 17 insertions(+), 6 deletions(-) + +diff --git a/src/haproxy.c b/src/haproxy.c +index 5a3f6c755..0cb0662d2 100644 +--- a/src/haproxy.c ++++ b/src/haproxy.c +@@ -3432,7 +3432,7 @@ int main(int argc, char **argv) + if (child->reloads == 0 && + child->options & PROC_O_TYPE_WORKER && + child->pid == -1) { +- child->timestamp = now.tv_sec; ++ child->timestamp = date.tv_sec; + child->pid = ret; + child->version = strdup(haproxy_version); + break; +diff --git a/src/mworker.c b/src/mworker.c +index 686fc755d..26b16cca4 100644 +--- a/src/mworker.c ++++ b/src/mworker.c +@@ -559,13 +559,16 @@ static int cli_io_handler_show_proc(struct appctx *appctx) + struct stconn *sc = appctx_sc(appctx); + struct mworker_proc *child; + int old = 0; +- int up = now.tv_sec - proc_self->timestamp; ++ int up = date.tv_sec - proc_self->timestamp; + char *uptime = NULL; + char *reloadtxt = NULL; + + if (unlikely(sc_ic(sc)->flags & (CF_WRITE_ERROR|CF_SHUTW))) + return 1; + ++ if (up < 0) /* must never be negative because of clock drift */ ++ up = 0; ++ + chunk_reset(&trash); + + memprintf(&reloadtxt, "%d [failed: %d]", proc_self->reloads, proc_self->failedreloads); +@@ -579,7 +582,9 @@ static int cli_io_handler_show_proc(struct appctx *appctx) + + chunk_appendf(&trash, "# workers\n"); + list_for_each_entry(child, &proc_list, list) { +- up = now.tv_sec - child->timestamp; ++ up = date.tv_sec - child->timestamp; ++ if (up < 0) /* must never be negative because of clock drift */ ++ up = 0; + + if (!(child->options & PROC_O_TYPE_WORKER)) + continue; +@@ -600,7 +605,9 @@ static int cli_io_handler_show_proc(struct appctx *appctx) + + chunk_appendf(&trash, "# old workers\n"); + list_for_each_entry(child, &proc_list, list) { +- up = now.tv_sec - child->timestamp; ++ up = date.tv_sec - child->timestamp; ++ if (up <= 0) /* must never be negative because of clock drift */ ++ up = 0; + + if (!(child->options & PROC_O_TYPE_WORKER)) + continue; +@@ -618,7 +625,9 @@ static int cli_io_handler_show_proc(struct appctx *appctx) + chunk_appendf(&trash, "# programs\n"); + old = 0; + list_for_each_entry(child, &proc_list, list) { +- up = now.tv_sec - child->timestamp; ++ up = date.tv_sec - child->timestamp; ++ if (up < 0) /* must never be negative because of clock drift */ ++ up = 0; + + if (!(child->options & PROC_O_TYPE_PROG)) + continue; +@@ -635,7 +644,9 @@ static int cli_io_handler_show_proc(struct appctx *appctx) + if (old) { + chunk_appendf(&trash, "# old programs\n"); + list_for_each_entry(child, &proc_list, list) { +- up = now.tv_sec - child->timestamp; ++ up = date.tv_sec - child->timestamp; ++ if (up < 0) /* must never be negative because of clock drift */ ++ up = 0; + + if (!(child->options & PROC_O_TYPE_PROG)) + continue; +-- +2.33.0 + diff --git a/backport-BUG-MINOR-protocol-fix-minor-memory-leak-in-protocol.patch b/backport-BUG-MINOR-protocol-fix-minor-memory-leak-in-protocol.patch new file mode 100644 index 0000000000000000000000000000000000000000..826d382e04aa76bf1520e49b47d1ace784d62edb --- /dev/null +++ b/backport-BUG-MINOR-protocol-fix-minor-memory-leak-in-protocol.patch @@ -0,0 +1,65 @@ +From 44eef1b3b566ec73a6d242ca347e6b6111dfabaa Mon Sep 17 00:00:00 2001 +From: Aurelien DARRAGON +Date: Tue, 7 Feb 2023 15:51:58 +0100 +Subject: [PATCH] BUG/MINOR: protocol: fix minor memory leak in + protocol_bind_all() + +In protocol_bind_all() (involved in startup sequence): +We only free errmsg (set by fam->bind() attempt) when we make use of it. +But this could lead to some memory leaks because there are some cases +where we ignore the error message (e.g: verbose=0 with ERR_WARN messages). + +As long as errmsg is set, we should always free it. + +As mentioned earlier, this really is a minor leak because it can only occur on +specific conditions (error paths) during the startup phase. + +This may be backported up to 2.4. + +-- +Backport notes: + +-> 2.4 only: + +Replace this: + + | ha_warning("Binding [%s:%d] for %s %s: %s\n", + | listener->bind_conf->file, listener->bind_conf->line, + | proxy_type_str(px), px->id, errmsg); + +By this: + + | else if (lerr & ERR_WARN) + | ha_warning("Starting %s %s: %s\n", + | proxy_type_str(px), px->id, errmsg); + +(cherry picked from commit 8429627e3c2eb472dc94ec8d3d7275ef68a79128) +Signed-off-by: Willy Tarreau +(cherry picked from commit da9a15ff0326d59ba38f5a1b258820d91c7df649) +Signed-off-by: Christopher Faulet + +Conflict: NA +Reference: https://git.haproxy.org/?p=haproxy-2.6.git;a=commit;h=44eef1b3b566ec73a6d242ca347e6b6111dfabaa +--- + src/protocol.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/protocol.c b/src/protocol.c +index 03f708591..146733a3f 100644 +--- a/src/protocol.c ++++ b/src/protocol.c +@@ -92,8 +92,10 @@ int protocol_bind_all(int verbose) + ha_warning("Binding [%s:%d] for %s %s: %s\n", + listener->bind_conf->file, listener->bind_conf->line, + proxy_type_str(px), px->id, errmsg); +- ha_free(&errmsg); + } ++ if (lerr != ERR_NONE) ++ ha_free(&errmsg); ++ + if (lerr & ERR_ABORT) + break; + +-- +2.33.0 + diff --git a/backport-BUG-MINOR-server-inherit-from-netns-in-srv_settings_.patch b/backport-BUG-MINOR-server-inherit-from-netns-in-srv_settings_.patch new file mode 100644 index 0000000000000000000000000000000000000000..99f14d3941bf7fd574331ed0a592d143413ff490 --- /dev/null +++ b/backport-BUG-MINOR-server-inherit-from-netns-in-srv_settings_.patch @@ -0,0 +1,48 @@ +From f233b187f5f101a724c6fdde5b0a9e4fb6d6d50e Mon Sep 17 00:00:00 2001 +From: Aurelien DARRAGON +Date: Wed, 14 Jun 2023 09:53:32 +0200 +Subject: [PATCH] BUG/MINOR: server: inherit from netns in srv_settings_cpy() + +When support for 'namespace' keyword was added for the 'default-server' +directive in 22f41a2 ("MINOR: server: Make 'default-server' support +'namespace' keyword."), we forgot to copy the attribute from the parent +to the newly created server. + +This resulted in the 'namespace' keyword being parsed without errors when +used from a 'default-server' directive, but in practise the option was +simply ignored. + +There's no need to duplicate the netns struct because it is stored in +a shared list, so copying the pointer does the job. + +This patch partially fixes GH #2038 and should be backported to all +stable versions. + +(cherry picked from commit 19b5a7c7a5b4b01970e06d20928ed1d87ca6efcd) +Signed-off-by: William Lallemand +(cherry picked from commit 60d185d9320ae1293c466e004b059b0310dcb13c) +Signed-off-by: William Lallemand +(cherry picked from commit 20e6fa6abf259c20ad471f44d646d0f0ee28f3ec) +Signed-off-by: William Lallemand + +Conflict: NA +Reference: https://git.haproxy.org/?p=haproxy-2.6.git;a=commit;h=f233b187f5f101a724c6fdde5b0a9e4fb6d6d50e +--- + src/server.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/server.c b/src/server.c +index e9e09dd6d..7935668b1 100644 +--- a/src/server.c ++++ b/src/server.c +@@ -2280,6 +2280,7 @@ void srv_settings_cpy(struct server *srv, const struct server *src, int srv_tmpl + if (srv_tmpl) + srv->srvrq = src->srvrq; + ++ srv->netns = src->netns; + srv->check.via_socks4 = src->check.via_socks4; + srv->socks4_addr = src->socks4_addr; + } +-- +2.33.0 + diff --git a/backport-BUG-MINOR-stream-Perform-errors-handling-in-right-or.patch b/backport-BUG-MINOR-stream-Perform-errors-handling-in-right-or.patch new file mode 100644 index 0000000000000000000000000000000000000000..cff7f2c9a5b11edd307ed7a10734272f996017a6 --- /dev/null +++ b/backport-BUG-MINOR-stream-Perform-errors-handling-in-right-or.patch @@ -0,0 +1,40 @@ +From b3dc43ddadfd98b745823deaed6e7743b59442eb Mon Sep 17 00:00:00 2001 +From: Christopher Faulet +Date: Tue, 27 Sep 2022 09:14:47 +0200 +Subject: [PATCH] BUG/MINOR: stream: Perform errors handling in right order in + stream_new() + +The frontend SC is attached before the backend one is allocated. Thus an +allocation error on backend SC must be handled before an error on the +frontend SC. + +This patch must be backported to 2.6. + +(cherry picked from commit 4cfc038cb19996f5d2fe60284fdb556503a5f9ef) +Signed-off-by: Christopher Faulet + +Conflict: NA +Reference: https://git.haproxy.org/?p=haproxy-2.6.git;a=commit;h=b3dc43ddadfd98b745823deaed6e7743b59442eb +--- + src/stream.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/stream.c b/src/stream.c +index 0cbbb70b7..fc8b82af0 100644 +--- a/src/stream.c ++++ b/src/stream.c +@@ -566,9 +566,9 @@ struct stream *stream_new(struct session *sess, struct stconn *sc, struct buffer + out_fail_accept: + flt_stream_release(s, 0); + LIST_DELETE(&s->list); +- out_fail_attach_scf: +- sc_free(s->scb); + out_fail_alloc_scb: ++ sc_free(s->scb); ++ out_fail_attach_scf: + task_destroy(t); + out_fail_alloc: + pool_free(pool_head_stream, s); +-- +2.33.0 + diff --git a/haproxy.spec b/haproxy.spec index 32983ab7dcf292db20a5803b9dc4aaae0e2529d9..19ed43768337e7f527c1fe4b9230044bd226937e 100644 --- a/haproxy.spec +++ b/haproxy.spec @@ -5,7 +5,7 @@ Name: haproxy Version: 2.6.6 -Release: 4 +Release: 5 Summary: The Reliable, High Performance TCP/HTTP Load Balancer License: GPLv2+ @@ -20,6 +20,14 @@ Patch0: CVE-2023-25725.patch Patch1: CVE-2023-0056.patch Patch2: CVE-2023-25950.patch Patch3: CVE-2023-40225.patch +Patch4: backport-BUG-MINOR-stream-Perform-errors-handling-in-right-or.patch +Patch5: backport-BUG-MINOR-http_ana-txn-don-t-re-initialize-txn-and-r.patch +Patch6: backport-BUG-MEDIUM-connection-Clear-flags-when-a-conn-is-rem.patch +Patch7: backport-BUG-MINOR-mworker-prevent-incorrect-values-in-uptime.patch +Patch8: backport-BUG-MEDIUM-connection-Preserve-flags-when-a-conn-is-.patch +Patch9: backport-BUG-MINOR-protocol-fix-minor-memory-leak-in-protocol.patch +Patch10: backport-BUG-MEDIUM-stream-do-not-try-to-free-a-failed-stream.patch +Patch11: backport-BUG-MINOR-server-inherit-from-netns-in-srv_settings_.patch BuildRequires: gcc lua-devel pcre2-devel openssl-devel systemd-devel systemd libatomic Requires(pre): shadow-utils @@ -121,6 +129,18 @@ exit 0 %{_mandir}/man1/* %changelog +* Wed Sep 27 2023 xinghe - 2.6.6-5 +- Type:bugfix +- CVE:NA +- SUG:restart +- DESC:connection: Clear flags when a conn is removed + connection: Preserve flags when a conn is removed + stream: do not try to free a failed stream-conn + http_ana/txn: don't re-initialize txn and req var + mworker: prevent incorrect values in uptime + protocol: fix minor memory leak in protocol_bind_all() + stream: Perform errors handling in right order in stream_new() + * Mon Aug 21 2023 wangkai - 2.6.6-4 - Fix CVE-2023-40225