]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: connection: reserve the whole CRC32C TLV before saving its pointer
authorWilly Tarreau <w@1wt.eu>
Thu, 6 Aug 2026 07:27:02 +0000 (09:27 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 7 Aug 2026 11:54:14 +0000 (13:54 +0200)
make_proxy_line_v2() saves a pointer to the CRC32C TLV value so the
checksum can be appended once the whole header is known. It only checked
for 3 bytes (the TLV header) instead of the 7 needed for the full TLV, so
with 3 to 6 bytes left, make_tlv() emitted nothing and returned 0, yet
tlv_crc32c_p was still set, and the final write_u32() wrote 4 bytes up to
3 bytes past the end of the header buffer.

Not only this theoretically only affects servers using "send-proxy-v2"
with "proxy-v2-options crc32c" combined with "set-proxy-v2-tlv-fmt" TLVs,
but in addition in practice the proxy protocol is designed to be way
shorter than a regular buffer, and the only practical way to reach that
is to purposely write a config to demonstrate this, so it cannot happen.

This has been there since crc32c support was added in 1.9 by commit
4399c75f6 ("MINOR: proxy-v2-options: add crc32c"). It should be backported
to all stable versions.

Reported-by: Claude (ANT-2026-H10QWEV6)
src/connection.c

index bda89206636c4955832464e27ccd606b283aa1cd..9ebbff286c461cdaf1d7540f6e15b5af1f27f941 100644 (file)
@@ -2357,7 +2357,8 @@ static int make_proxy_line_v2(char *buf, int buf_len, struct server *srv, struct
        if (srv->pp_opts & SRV_PP_V2_CRC32C) {
                uint32_t zero_crc32c = 0;
 
-               if ((buf_len - ret) < sizeof(struct tlv))
+               /* make sure the whole TLV fits, not just its header */
+               if ((buf_len - ret) < sizeof(struct tlv) + sizeof(zero_crc32c))
                        return 0;
                tlv_crc32c_p = (void *)((struct tlv *)&buf[ret])->value;
                ret += make_tlv(&buf[ret], (buf_len - ret), PP2_TYPE_CRC32C, sizeof(zero_crc32c), (const char *)&zero_crc32c);