From 61840e715f37b71c4b30d68b8b2e79106a3799dc Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Mon, 15 Apr 2019 09:33:32 +0200 Subject: [PATCH] BUG/MEDIUM: muxes: Don't dereference mux context if null in release functions When a mux context is released, we must be sure it exists before dereferencing it. The bug was introduced in the commit 39a96ee16 ("MEDIUM: muxes: Be prepared to don't own connection during the release"). No need to backport this patch, expect if the commit 39a96ee16 is backported too. --- src/mux_h1.c | 13 +++++++------ src/mux_h2.c | 11 +++++------ src/mux_pt.c | 9 +++------ 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/src/mux_h1.c b/src/mux_h1.c index 5ea5f3c03..3a031e04f 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -445,14 +445,14 @@ static int h1_init(struct connection *conn, struct proxy *proxy, struct session */ static void h1_release(struct h1c *h1c) { - struct connection *conn = h1c->conn; - - /* The connection was attached to another mux */ - if (conn && conn->ctx != h1c) - conn = NULL; + struct connection *conn = NULL; if (h1c) { - if (h1c->flags & H1C_F_UPG_H2C) { + /* The connection must be aattached to this mux to be released */ + if (h1c->conn && h1c->conn->ctx == h1c) + conn = h1c->conn; + + if (conn && h1c->flags & H1C_F_UPG_H2C) { h1c->flags &= ~H1C_F_UPG_H2C; if (conn_upgrade_mux_fe(conn, NULL, &h1c->ibuf, ist("h2"), PROTO_MODE_HTX) != -1) { /* connection successfully upgraded to H2, this @@ -462,6 +462,7 @@ static void h1_release(struct h1c *h1c) sess_log(conn->owner); /* Log if the upgrade failed */ } + if (!LIST_ISEMPTY(&h1c->buf_wait.list)) { HA_SPIN_LOCK(BUF_WQ_LOCK, &buffer_wq_lock); LIST_DEL(&h1c->buf_wait.list); diff --git a/src/mux_h2.c b/src/mux_h2.c index 48876ee20..894c4bdbb 100644 --- a/src/mux_h2.c +++ b/src/mux_h2.c @@ -619,14 +619,13 @@ static inline struct h2s *h2c_st_by_id(struct h2c *h2c, int id) */ static void h2_release(struct h2c *h2c) { - struct connection *conn = h2c->conn; - - /* The connection was attached to another mux (unexpected but safer to - * check) */ - if (conn && conn->ctx != h2c) - conn = NULL; + struct connection *conn = NULL;; if (h2c) { + /* The connection must be aattached to this mux to be released */ + if (h2c->conn && h2c->conn->ctx == h2c) + conn = h2c->conn; + hpack_dht_free(h2c->ddht); HA_SPIN_LOCK(BUF_WQ_LOCK, &buffer_wq_lock); diff --git a/src/mux_pt.c b/src/mux_pt.c index 82ba124b1..278a8f55d 100644 --- a/src/mux_pt.c +++ b/src/mux_pt.c @@ -26,13 +26,10 @@ DECLARE_STATIC_POOL(pool_head_pt_ctx, "mux_pt", sizeof(struct mux_pt_ctx)); static void mux_pt_destroy(struct mux_pt_ctx *ctx) { - struct connection *conn = ctx->conn; + /* The connection must be aattached to this mux to be released */ + if (ctx && ctx->conn && ctx->conn->ctx == ctx) { + struct connection *conn = ctx->conn; - /* The connection was attached to another mux */ - if (conn && conn->ctx != ctx) - conn = NULL; - - if (conn) { conn_stop_tracking(conn); conn_full_close(conn); tasklet_free(ctx->wait_event.task);