]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: connections: Report connection closing in conn_create_mux()
authorOlivier Houchard <ohouchard@haproxy.com>
Wed, 30 Apr 2025 11:19:38 +0000 (13:19 +0200)
committerOlivier Houchard <cognet@ci0.org>
Wed, 30 Apr 2025 15:17:36 +0000 (17:17 +0200)
Add an extra parametre to conn_create_mux(), "closed_connection".
If a pointer is provided, then let it know if the connection was closed.
Callers have no way to determine that otherwise, and we need to know
that, at least in ssl_sock_io_cb(), as if the connection was closed we
need to return NULL, as the tasklet was free'd, otherwise that can lead
to memory corruption and crashes.
This should be backported if 9240cd4a2771245fae4d0d69ef025104b14bfc23
is backported too.

include/haproxy/connection.h
src/backend.c
src/connection.c
src/ssl_sock.c
src/xprt_handshake.c

index 2e79a129f88e045f647d9c5ac7af8c49d5e599ad..d759238b2a9d177355e28c6295a8d69d66d14458 100644 (file)
@@ -75,7 +75,7 @@ int conn_send_socks4_proxy_request(struct connection *conn);
 int conn_recv_socks4_proxy_response(struct connection *conn);
 
 /* If we delayed the mux creation because we were waiting for the handshake, do it now */
-int conn_create_mux(struct connection *conn);
+int conn_create_mux(struct connection *conn, int *closed_connection);
 int conn_notify_mux(struct connection *conn, int old_flags, int forced_wake);
 int conn_upgrade_mux_fe(struct connection *conn, void *ctx, struct buffer *buf,
                         struct ist mux_proto, int mode);
index 451686b6ad53cd638f763220e8fb4aafa97da68f..5cfa263115df6119526a5c769fae0bc6896f3551 100644 (file)
@@ -2217,8 +2217,11 @@ int connect_server(struct stream *s)
 
        /* catch all sync connect while the mux is not already installed */
        if (!srv_conn->mux && !(srv_conn->flags & CO_FL_WAIT_XPRT)) {
-               if (conn_create_mux(srv_conn) < 0) {
-                       conn_full_close(srv_conn);
+               int closed_connection;
+
+               if (conn_create_mux(srv_conn, &closed_connection) < 0) {
+                       if (closed_connection == 0)
+                               conn_full_close(srv_conn);
                        return SF_ERR_INTERNAL;
                }
        }
index 09ec41bb6ef8206ea868efff27daf70c01b91211..e8509fc2d3dd188c7328544d320442f2afdf7f92 100644 (file)
@@ -84,8 +84,11 @@ void conn_delete_from_tree(struct connection *conn)
        eb64_delete(&conn->hash_node->node);
 }
 
-int conn_create_mux(struct connection *conn)
+int conn_create_mux(struct connection *conn, int *closed_connection)
 {
+       if (closed_connection)
+               *closed_connection = 0;
+
        if (conn_is_back(conn)) {
                struct server *srv;
                struct stconn *sc = conn->ctx;
@@ -138,8 +141,13 @@ fail:
                        task_wakeup(l->rx.rhttp.task, TASK_WOKEN_RES);
                }
                return -1;
-       } else
-               return conn_complete_session(conn);
+       } else {
+
+               int ret = conn_complete_session(conn);
+               if (ret == -1 && closed_connection)
+                       *closed_connection = 1;
+               return ret;
+       }
 
 }
 
@@ -157,7 +165,7 @@ int conn_notify_mux(struct connection *conn, int old_flags, int forced_wake)
         * done with the handshake, attempt to create one.
         */
        if (unlikely(!conn->mux) && !(conn->flags & CO_FL_WAIT_XPRT)) {
-               ret = conn_create_mux(conn);
+               ret = conn_create_mux(conn, NULL);
                if (ret < 0)
                        goto done;
        }
index 29c7df87411ba3cdfc88a7f8abd30c25cf3bb3e4..793862b94fbc43354c7d59dc95fdfe900ebd9c58 100644 (file)
@@ -5813,10 +5813,17 @@ struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned int state)
                 * woke a tasklet already.
                 */
                if (ctx->conn->xprt_ctx == ctx) {
+                       int closed_connection = 0;
+
                        if (!ctx->conn->mux)
-                               ret = conn_create_mux(ctx->conn);
-                       if (ret >= 0 && !woke && ctx->conn->mux && ctx->conn->mux->wake)
+                               ret = conn_create_mux(ctx->conn, &closed_connection);
+                       if (ret >= 0 && !woke && ctx->conn->mux && ctx->conn->mux->wake) {
                                ret = ctx->conn->mux->wake(ctx->conn);
+                               if (ret < 0)
+                                       closed_connection = 1;
+                       }
+                       if (closed_connection)
+                               t = NULL;
                        goto leave;
                }
        }
index 33f775087a19955115cf157cb24995d8878f22b0..4d6b4bb89e24d4ba647b6e97acdc356ce04283b7 100644 (file)
@@ -115,7 +115,7 @@ out:
                 */
                if (was_conn_ctx) {
                        if (!ctx->conn->mux)
-                               ret = conn_create_mux(ctx->conn);
+                               ret = conn_create_mux(ctx->conn, NULL);
                        if (ret >= 0 && !woke && ctx->conn->mux && ctx->conn->mux->wake)
                                ret = ctx->conn->mux->wake(ctx->conn);
                }