]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: connection: skip FD-based syscalls for FD-less connections
authorWilly Tarreau <w@1wt.eu>
Mon, 11 Apr 2022 16:04:33 +0000 (18:04 +0200)
committerWilly Tarreau <w@1wt.eu>
Mon, 11 Apr 2022 17:31:47 +0000 (19:31 +0200)
Some syscalls at the TCP level act directly on the FD. Some of them
are used by TCP actions like set-tos, set-mark, silent-drop, others
try to retrieve TCP info, get the source or destination address. These
ones must not be called with an invalid FD coming from an FD-less
connection, so let's add the relevant tests for this. It's worth
noting that all these ones already have fall back plans (do nothing,
error, or switch to alternate implementation).

include/haproxy/connection.h
src/tcp_act.c
src/tcp_sample.c
src/tcpcheck.c

index f6407ff4b21ec5fac6bd590e6daf4022973c326e..5d9b5ca7485ac319e5ffc6be744e6e30c87f9ace 100644 (file)
@@ -352,7 +352,8 @@ static inline int conn_get_src(struct connection *conn)
        if (!sockaddr_alloc(&conn->src, NULL, 0))
                return 0;
 
-       if (conn->ctrl->fam->get_src(conn->handle.fd, (struct sockaddr *)conn->src,
+       if (conn->ctrl->fam->get_src && !(conn->flags & CO_FL_FDLESS) &&
+           conn->ctrl->fam->get_src(conn->handle.fd, (struct sockaddr *)conn->src,
                                sizeof(*conn->src),
                                obj_type(conn->target) != OBJ_TYPE_LISTENER) == -1)
                return 0;
@@ -375,7 +376,8 @@ static inline int conn_get_dst(struct connection *conn)
        if (!sockaddr_alloc(&conn->dst, NULL, 0))
                return 0;
 
-       if (conn->ctrl->fam->get_dst(conn->handle.fd, (struct sockaddr *)conn->dst,
+       if (conn->ctrl->fam->get_dst && !(conn->flags & CO_FL_FDLESS) &&
+           conn->ctrl->fam->get_dst(conn->handle.fd, (struct sockaddr *)conn->dst,
                                sizeof(*conn->dst),
                                obj_type(conn->target) != OBJ_TYPE_LISTENER) == -1)
                return 0;
@@ -389,7 +391,7 @@ static inline int conn_get_dst(struct connection *conn)
  */
 static inline void conn_set_tos(const struct connection *conn, int tos)
 {
-       if (!conn || !conn_ctrl_ready(conn))
+       if (!conn || !conn_ctrl_ready(conn) || (conn->flags & CO_FL_FDLESS))
                return;
 
 #ifdef IP_TOS
@@ -412,7 +414,7 @@ static inline void conn_set_tos(const struct connection *conn, int tos)
  */
 static inline void conn_set_mark(const struct connection *conn, int mark)
 {
-       if (!conn || !conn_ctrl_ready(conn))
+       if (!conn || !conn_ctrl_ready(conn) || (conn->flags & CO_FL_FDLESS))
                return;
 
 #if defined(SO_MARK)
@@ -429,7 +431,7 @@ static inline void conn_set_mark(const struct connection *conn, int mark)
  */
 static inline void conn_set_quickack(const struct connection *conn, int value)
 {
-       if (!conn || !conn_ctrl_ready(conn))
+       if (!conn || !conn_ctrl_ready(conn) || (conn->flags & CO_FL_FDLESS))
                return;
 
 #ifdef TCP_QUICKACK
index ecb33d9f3a12b0752c2e62a60db0bba0f72a7dec..04400d2107654d38c3472c57f4483d8fe9662eba 100644 (file)
@@ -290,6 +290,9 @@ static enum act_return tcp_exec_action_silent_drop(struct act_rule *rule, struct
        if (strm)
                strm->csf->si->flags |= SI_FL_NOLINGER;
 
+       if (conn->flags & CO_FL_FDLESS)
+               goto out;
+
        /* We're on the client-facing side, we must force to disable lingering to
         * ensure we will use an RST exclusively and kill any pending data.
         */
index 895a1306fd230207e85c0f3c9988e9525f6da44a..53e3d1e01f28a4f8055638450a3d130121b01d9a 100644 (file)
@@ -332,7 +332,8 @@ static inline int get_tcp_info(const struct arg *args, struct sample *smp,
        /* The fd may not be available for the tcp_info struct, and the
          syscal can fail. */
        optlen = sizeof(info);
-       if (getsockopt(conn->handle.fd, IPPROTO_TCP, TCP_INFO, &info, &optlen) == -1)
+       if ((conn->flags & CO_FL_FDLESS) ||
+           getsockopt(conn->handle.fd, IPPROTO_TCP, TCP_INFO, &info, &optlen) == -1)
                return 0;
 
        /* extract the value. */
index 1926311f7fa213201c8073e1dcf0947194078e7f..6e995a0ea0f26ee51f3a0f04fd0b9eb7e728c031 100644 (file)
@@ -1210,7 +1210,7 @@ enum tcpcheck_eval_ret tcpcheck_eval_connect(struct check *check, struct tcpchec
                ssl_sock_set_alpn(conn, (unsigned char *)s->check.alpn_str, s->check.alpn_len);
 #endif
 
-       if (conn_ctrl_ready(conn) && (connect->options & TCPCHK_OPT_LINGER)) {
+       if (conn_ctrl_ready(conn) && (connect->options & TCPCHK_OPT_LINGER) && !(conn->flags & CO_FL_FDLESS)) {
                /* Some servers don't like reset on close */
                HA_ATOMIC_AND(&fdtab[conn->handle.fd].state, ~FD_LINGER_RISK);
        }