Download raw body.
socket splicing loop counter
On Fri, Feb 20, 2026 at 06:47:31PM +0100, Alexander Bluhm wrote:
> Hi,
>
> To avoid endless splicing loops, the mbuf's lifetime is limited by
> the ph_loopcnt counter. Each time somove() compares the value to
> a maximum and increments.
>
> After that, in the unlikely case that the drain buffer is full, the
> mbuf stays in the source buffer. Then it is incremented again when
> more data arrives and somove() is called. Eventually the maxiumm
> could be reached and splicing dissolved with ELOOP. This was not
> intended for mbufs which never moved, we want to count the moves.
>
> Avoid the race and increment just before sending the mbuf out to
> the new buffer.
>
> ok?
>
ok mvs
> bluhm
>
> Index: kern/uipc_socket.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/kern/uipc_socket.c,v
> diff -u -p -r1.387 uipc_socket.c
> --- kern/uipc_socket.c 21 Jan 2026 10:18:20 -0000 1.387
> +++ kern/uipc_socket.c 20 Feb 2026 15:40:27 -0000
> @@ -1592,12 +1592,9 @@ somove(struct socket *so, int wait)
> /*
> * By splicing sockets connected to localhost, userland might create a
> * loop. Dissolve splicing with error if loop is detected by counter.
> - *
> - * If we deal with looped broadcast/multicast packet we bail out with
> - * no error to suppress splice termination.
> */
> if ((m->m_flags & M_PKTHDR) &&
> - ((m->m_pkthdr.ph_loopcnt++ >= M_MAXLOOP) ||
> + ((m->m_pkthdr.ph_loopcnt >= M_MAXLOOP) ||
> ((m->m_flags & M_LOOP) && (m->m_flags & (M_BCAST|M_MCAST))))) {
> error = ELOOP;
> goto release;
> @@ -1737,6 +1734,8 @@ somove(struct socket *so, int wait)
> } else if (oobmark) {
> o = m_split(m, oobmark, wait);
> if (o) {
> + if (m->m_flags & M_PKTHDR)
> + m->m_pkthdr.ph_loopcnt++;
> solock_shared(sosp);
> error = pru_send(sosp, m, NULL, NULL);
> sounlock_shared(sosp);
> @@ -1793,6 +1792,8 @@ somove(struct socket *so, int wait)
>
> mtx_leave(&sosp->so_snd.sb_mtx);
> mtx_leave(&so->so_rcv.sb_mtx);
> + if (m->m_flags & M_PKTHDR)
> + m->m_pkthdr.ph_loopcnt++;
> solock_shared(sosp);
> error = pru_send(sosp, m, NULL, NULL);
> sounlock_shared(sosp);
>
socket splicing loop counter