]> git.ipfire.org Git - thirdparty/haproxy.git/commit
BUG/MEDIUM: sock: bound the recvmsg() length when receiving old sockets
authorOlivier Houchard <ohouchard@haproxy.com>
Thu, 6 Aug 2026 07:32:10 +0000 (09:32 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 7 Aug 2026 08:29:19 +0000 (10:29 +0200)
commit0fdb91c5c953ddc043f2e788d4f7627e1f8ac09b
treed104d92ba5fc6b33d2fd4f5fff3a8173ed5ec94b
parent1014a43e02850682d2426fe5d3f781a4d788df18
BUG/MEDIUM: sock: bound the recvmsg() length when receiving old sockets

sock_get_old_sockets() sizes tmpbuf from the number of FDs announced by the
old process, but passes a fixed iov_len of MAX_SEND_FD entries to every
recvmsg() and loops as long as fewer FDs than announced were received,
without ever comparing curoff to the size of the allocation. A peer
announcing a single FD (4118 bytes allocated) and then streaming plain data
with no SCM_RIGHTS makes the kernel write up to 252*4118 bytes per recvmsg()
past the end of the buffer, and the loop never ends. Reproduced with a fake
old process: glibc aborts on "free(): invalid next size" after ~320 kB. Only
the peer of the -x transfer socket can do this, so it is not reachable from
the network, but it happens before privileges are dropped.

Let's clamp each recvmsg() to the room really left in the allocation and
abort the transfer when the peer sends more. Legitimate transfers are
unaffected, they use at most 1+255+1+255+4 bytes per FD.

This has been there since commit f73629d23 ("MINOR: global: Add an option to
get the old listening sockets.") in 1.8, which already sized tmpbuf on fd_nb
and the iovec on MAX_SEND_FD. It may be backported to all stable versions.

Reported-by: Claude (ANT-2026-Q363CKEH)
src/sock.c