]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: connection: Do not retrieve src/dst on another thread group's FD
authorOlivier Houchard <ohouchard@haproxy.com>
Wed, 29 Jul 2026 23:04:50 +0000 (01:04 +0200)
committerOlivier Houchard <cognet@ci0.org>
Thu, 30 Jul 2026 11:36:17 +0000 (13:36 +0200)
conn_get_src() and conn_get_dst() lazily fetch the connection's
addresses with getsockname()/getpeername() when they were not known
yet. They may be called on a foreign connection by observability code
running on any thread, for example "show peers", which dumps the peers
sessions' connections from whatever thread serves the CLI. With
per-thread-group FD tables, the FD of a connection owned by another
group is not usable from the calling thread.
So just fail if we attempt to access a connection that is owned by
another thread group.

include/haproxy/connection.h

index 980d696a8bc07b3393c1188edd528f1a2a25b28f..e51f2b42371662db3bfd32f78d61500ceb1d9542 100644 (file)
@@ -384,8 +384,14 @@ static inline int conn_get_src(struct connection *conn)
        if (conn->ctrl->proto_type != PROTO_TYPE_STREAM)
                goto fail;
 
-       /* most other socket-based stream protocols will use their socket family's functions */
+       /* most other socket-based stream protocols will use their socket
+        * family's functions. With per-thread-group FD tables however, the
+        * FD may belong to a connection of another group, its number is only
+        * usable within that group.
+        */
        if (conn->ctrl->fam->get_src && !(conn->flags & CO_FL_FDLESS) &&
+           (!(global.tune.options & GTUNE_NO_TG_FD_SHARING) ||
+            fdtab[conn->handle.fd].owner == conn) &&
            conn->ctrl->fam->get_src(conn->handle.fd, (struct sockaddr *)conn->src,
                                sizeof(*conn->src),
                                obj_type(conn->target) != OBJ_TYPE_LISTENER) != -1)
@@ -424,6 +430,8 @@ static inline int conn_get_dst(struct connection *conn)
 
        /* most other socket-based stream protocols will use their socket family's functions */
        if (conn->ctrl->fam->get_dst && !(conn->flags & CO_FL_FDLESS) &&
+           (!(global.tune.options & GTUNE_NO_TG_FD_SHARING) ||
+            fdtab[conn->handle.fd].owner == conn) &&
            conn->ctrl->fam->get_dst(conn->handle.fd, (struct sockaddr *)conn->dst,
                                sizeof(*conn->dst),
                                obj_type(conn->target) != OBJ_TYPE_LISTENER) != -1)