]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: spoe: fix pointer arithmetic overflow in spoe_decode_buffer()
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 9 Apr 2026 11:06:42 +0000 (13:06 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Thu, 9 Apr 2026 14:47:19 +0000 (16:47 +0200)
decode_varint() has no iteration cap and accepts varints decoding to
any uint64_t value. When sz is large enough that p + sz wraps modulo
2^64, the check "p + sz > end" passes, *buf is set to the wrapped
pointer, and the caller's parsing loop continues from an arbitrary
relative offset before the demux buffer.

A malicious SPOE agent sending an AGENT_HELLO frame with a key-name
length varint of 0xfffffffffffff000 causes spop_conn_handle_hello()
to dereference memory ~64KB before the dbuf allocation, resulting in
SIGSEGV (DoS) or, if the read lands on live heap data, parser
confusion. The relative offset is fully attacker-controlled and
ASLR-independent.

Compare against the remaining length instead of computing p + sz.
Since p <= end is guaranteed after a successful decode_varint(),
end - p is non-negative.

This patch must be backport to all stable versions.

include/haproxy/spoe.h

index 585b8bff9e2c5c46cefff6ef7ca4ea343c96faf1..eeae37181527b389842cfa776c1a19fe07960c90 100644 (file)
@@ -76,7 +76,7 @@ static inline int spoe_decode_buffer(char **buf, char *end, char **str, uint64_t
        *len = 0;
 
        ret = decode_varint(&p, end, &sz);
-       if (ret == -1 || p + sz > end)
+       if (ret == -1 || sz > (uint64_t)(end - p))
                return -1;
 
        *str = p;