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)
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);