]> git.kaiwu.me - haproxy.git/commitdiff
BUG/MINOR: tcpcheck: check the number of "hdr" in http-check send
authorMartin Mirchev <mirchevmartin2203@gmail.com>
Fri, 30 Oct 2026 05:32:30 +0000 (13:32 +0800)
committerChristopher Faulet <cfaulet@haproxy.com>
Thu, 5 Nov 2026 20:50:03 +0000 (21:50 +0100)
parse_tcpcheck_send_http() collects the "hdr <name> <value>" arguments
of an "http-check send" rule into a stack array sized by
tune.http.maxhdr, followed by an IST_NULL terminator, but never checks
the number of headers against that size. When tune.http.maxhdr is
lowered and a rule sets as many headers as the limit, the terminator is
written past the end of the array, and each extra header writes one
more entry past it.

This happens while parsing the configuration. E.g. with:

    global
        tune.http.maxhdr 5

    backend b
        option httpchk
        http-check send meth GET uri /health hdr X-H1 v1 hdr X-H2 v2 \
                        hdr X-H3 v3 hdr X-H4 v4 hdr X-H5 v5
        server s1 127.0.0.1:1 check

"haproxy -c" crashes with a segfault on a release build, and ASan
reports a dynamic-stack-buffer-overflow WRITE in
parse_tcpcheck_send_http(). With the default value (101) it cannot be
reached because a config line is limited to 64 words.

Let's reject the rule with an error when there are too many headers,
keeping room for the terminator.

This should be backported to all stable versions. The code dates back to
2.2 and commit e5870d872b ("MAJOR: checks: Implement HTTP check using
tcp-check rules").

src/tcpcheck.c

index 1e245e0c80f3603388384467db4c11c864a4e8e5..7861218f8ffbb391275707694ec458497473eb16 100644 (file)
@@ -3090,6 +3090,13 @@ struct tcpcheck_rule *parse_tcpcheck_send_http(char **args, int cur_arg, struct
                                 strcasecmp(args[cur_arg+1], "transfer-encoding") == 0)
                                goto skip_hdr;
 
+                       /* keep room for the terminating IST_NULL entry */
+                       if (i >= global.tune.max_http_hdr - 1) {
+                               memprintf(errmsg, "too many headers (tune.http.maxhdr is %d)",
+                                         global.tune.max_http_hdr);
+                               goto error;
+                       }
+
                        hdrs[i].n = ist(args[cur_arg + 1]);
                        hdrs[i].v = ist(args[cur_arg + 2]);
                        i++;