]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: proto_reverse_connect: fix FD leak on connection error
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 29 Sep 2023 14:04:21 +0000 (16:04 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 29 Sep 2023 16:02:36 +0000 (18:02 +0200)
Listener using "rev@" address is responsible to setup connection and
reverse it using a server instance. If an error occured before reversal
is completed, proper freeing must be taken care of by the listener as no
session exists for this.

Currently, there is two locations where a connection is freed on error
before reversal inside reverse_connect protocol. Both of these were
incomplete as several function must be used to ensure connection is
properly freed. This commit fixes this by reusing the same cleaning
mechanism used inside H2 multiplexer.

One of the biggest drawback before this patch was that connection FD was
not properly removed from fdtab which caused a file-descriptor leak.

No need to backport this.

src/proto_reverse_connect.c

index a419215396894fde93e15a7a49b339af1060a3dc..1649a69dfa60870e8fa6de4e42966e0bd9fed0aa 100644 (file)
@@ -92,6 +92,15 @@ static struct connection *new_reverse_conn(struct listener *l, struct server *sr
 
  err:
        if (conn) {
+               conn_stop_tracking(conn);
+               conn_xprt_shutw(conn);
+               conn_xprt_close(conn);
+               conn_sock_shutw(conn, 0);
+               conn_ctrl_close(conn);
+
+               if (conn->destroy_cb)
+                       conn->destroy_cb(conn);
+
                /* Mark connection as non-reversable. This prevents conn_free()
                 * to reschedule reverse_connect task on freeing a preconnect
                 * connection.
@@ -137,7 +146,14 @@ struct task *rev_process(struct task *task, void *ctx, unsigned int state)
 
        if (conn) {
                if (conn->flags & CO_FL_ERROR) {
-                       conn_full_close(conn);
+                       conn_stop_tracking(conn);
+                       conn_xprt_shutw(conn);
+                       conn_xprt_close(conn);
+                       conn_sock_shutw(conn, 0);
+                       conn_ctrl_close(conn);
+
+                       if (conn->destroy_cb)
+                               conn->destroy_cb(conn);
                        conn_free(conn);
 
                        /* conn_free() must report preconnect failure using rev_notify_preconn_err(). */