]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: prevent conn leak in case of xprt_qmux init failure
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 29 Apr 2026 08:22:14 +0000 (10:22 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 20 May 2026 09:13:56 +0000 (11:13 +0200)
In case of XPRT_QMUX init failure on the frontend side, the connection
must immediately be released. This is not the case on the backend side
as a stream can supervize the connection lifetime.

This patch performs the connection free via conn_complete_session(). As
conn is flagged with CO_FL_ERROR, this will automatically fail and
invoke session_kill_embryonic(), which ensures the session and its
connection are both freed as wanted in this case.

No need to backport.

src/ssl_sock.c

index dcc41124d522c35667c7baf2977168ff66111f63..b74ee1952dee48b199628b5f2d37503bfa13c20d 100644 (file)
@@ -6977,16 +6977,24 @@ struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned int state)
                                        void *xprt_ctx_hs = NULL;
 
                                        ret = ops->init(conn, &xprt_ctx_hs);
-                                       BUG_ON(ret);
+                                       /* Frontend conn must be freed in case of XPRT init failure. */
+                                       if (ret) {
+                                               if (!conn_is_back(conn)) {
+                                                       conn->flags |= CO_FL_ERROR; /* Ensure conn will be freed on next call. */
+                                                       ret = conn_complete_session(conn);
+                                                       BUG_ON(ret >= 0); /* conn_complete_session() expected to fail on CO_FL_ERROR */
+                                                       t = NULL;
+                                               }
+                                               goto leave;
+                                       }
 
                                        ret = ops->add_xprt(conn, xprt_ctx_hs,
                                          conn->xprt_ctx, conn->xprt, NULL, NULL);
-                                       BUG_ON(ret);
+                                       BUG_ON(ret); /* xprt_qmux add_xprt always succeeds */
 
                                        conn->xprt = ops;
                                        conn->xprt_ctx = xprt_ctx_hs;
 
-
                                        ret = conn->xprt->start(conn, xprt_ctx_hs);
                                        BUG_ON(ret);
                                }