BUG/MEDIUM: stream: never allocate connection addresses from signal handler
authorWilly Tarreau <w@1wt.eu>
Fri, 21 Feb 2025 15:45:18 +0000 (16:45 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 18 Mar 2025 15:13:40 +0000 (16:13 +0100)
In __strm_dump_to_buffer(), we call conn_get_src()/conn_get_dst() to try
to retrieve the connection's IP addresses. But this function may be called
from a signal handler to dump a currently running stream, and if the
addresses were not allocated yet, a poll_alloc() will be performed while
we might possibly already be running pools code, resulting in pool list
corruption.

Let's just make sure we don't call these sensitive functions there when
called from a signal handler.

This must be backported at least to 3.1 and ideally all other versions,
along with this previous commit:

  MINOR: tinfo: add a new thread flag to indicate a call from a sig handler

(cherry picked from commit 84d4c948fce4b31220bb9a30cbf676613bbbf4f2)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 5f22fca932a1c3d5c92f30add31ffce81abdf758)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>

src/stream.c

index aa01f0d..2e6bed2 100644 (file)
@@ -3180,7 +3180,12 @@ void strm_dump_to_buffer(struct buffer *buf, const struct stream *strm, const ch
                     strm_li(strm) ? strm_li(strm)->rx.proto->name : "?");
 
        conn = objt_conn(strm_orig(strm));
-       switch (conn && conn_get_src(conn) ? addr_to_str(conn->src, pn, sizeof(pn)) : AF_UNSPEC) {
+
+       /* be careful not to allocate RAM from a signal handler! */
+       if (conn && !conn->src && !(th_ctx->flags & TH_FL_IN_SIG_HANDLER))
+               conn_get_src(conn);
+
+       switch (conn && conn->src ? addr_to_str(conn->src, pn, sizeof(pn)) : AF_UNSPEC) {
        case AF_INET:
        case AF_INET6:
                chunk_appendf(buf, " source=%s:%d\n",
@@ -3211,7 +3216,11 @@ void strm_dump_to_buffer(struct buffer *buf, const struct stream *strm, const ch
                     strm_li(strm) ? strm_li(strm)->name ? strm_li(strm)->name : "?" : "?",
                     strm_li(strm) ? strm_li(strm)->luid : 0);
 
-       switch (conn && conn_get_dst(conn) ? addr_to_str(conn->dst, pn, sizeof(pn)) : AF_UNSPEC) {
+       /* be careful not to allocate RAM from a signal handler! */
+       if (conn && !conn->dst && !(th_ctx->flags & TH_FL_IN_SIG_HANDLER))
+               conn_get_dst(conn);
+
+       switch (conn && conn->dst ? addr_to_str(conn->dst, pn, sizeof(pn)) : AF_UNSPEC) {
        case AF_INET:
        case AF_INET6:
                chunk_appendf(buf, " addr=%s:%d\n",
@@ -3235,7 +3244,12 @@ void strm_dump_to_buffer(struct buffer *buf, const struct stream *strm, const ch
                chunk_appendf(buf, "%s  backend=<NONE> (id=-1 mode=-)", pfx);
 
        conn = sc_conn(strm->scb);
-       switch (conn && conn_get_src(conn) ? addr_to_str(conn->src, pn, sizeof(pn)) : AF_UNSPEC) {
+
+       /* be careful not to allocate RAM from a signal handler! */
+       if (conn && !conn->src && !(th_ctx->flags & TH_FL_IN_SIG_HANDLER))
+               conn_get_src(conn);
+
+       switch (conn && conn->src ? addr_to_str(conn->src, pn, sizeof(pn)) : AF_UNSPEC) {
        case AF_INET:
        case AF_INET6:
                chunk_appendf(buf, " addr=%s:%d\n",
@@ -3258,7 +3272,11 @@ void strm_dump_to_buffer(struct buffer *buf, const struct stream *strm, const ch
        else
                chunk_appendf(buf, "%s  server=<NONE> (id=-1)", pfx);
 
-       switch (conn && conn_get_dst(conn) ? addr_to_str(conn->dst, pn, sizeof(pn)) : AF_UNSPEC) {
+       /* be careful not to allocate RAM from a signal handler! */
+       if (conn && !conn->dst && !(th_ctx->flags & TH_FL_IN_SIG_HANDLER))
+               conn_get_dst(conn);
+
+       switch (conn && conn->dst ? addr_to_str(conn->dst, pn, sizeof(pn)) : AF_UNSPEC) {
        case AF_INET:
        case AF_INET6:
                chunk_appendf(buf, " addr=%s:%d\n",