untrusted comment: signature from openbsd 5.8 base secret key RWQNNZXtC/MqP/fPnAU0TuzIso6yhQcaI3iWxDty0b8z2ORBRZtBToXz1po21rG2FFJ7+YlNc4aIAkGyPq0l9S2hwVUFSlOB0QU= OpenBSD 5.8 errata 18, Jul 14, 2016: Splicing sockets in a loop could cause a kernel spin. Apply by doing: signify -Vep /etc/signify/openbsd-58-base.pub -x 018_splice.patch.sig \ -m - | (cd /usr/src && patch -p0) And then rebuild and install a kernel: cd /usr/src/sys/arch/`machine`/conf KK=`sysctl -n kern.osversion | cut -d# -f1` config $KK cd ../compile/$KK make make install Index: sys/kern/uipc_socket.c =================================================================== RCS file: /cvs/src/sys/kern/uipc_socket.c,v retrieving revision 1.141 diff -u -p -r1.141 uipc_socket.c --- sys/kern/uipc_socket.c 8 Jul 2015 07:21:50 -0000 1.141 +++ sys/kern/uipc_socket.c 14 Jul 2016 03:03:23 -0000 @@ -1195,7 +1195,7 @@ somove(struct socket *so, int wait) goto release; } if (sosp->so_error && sosp->so_error != ETIMEDOUT && - sosp->so_error != EFBIG) { + sosp->so_error != EFBIG && sosp->so_error != ELOOP) { error = sosp->so_error; goto release; } @@ -1252,6 +1252,15 @@ somove(struct socket *so, int wait) goto nextpkt; } + /* + * By splicing sockets connected to localhost, userland might create a + * loop. Dissolve splicing with error if loop is detected by counter. + */ + if ((m->m_flags & M_PKTHDR) && m->m_pkthdr.ph_loopcnt++ >= M_MAXLOOP) { + error = ELOOP; + goto release; + } + if (so->so_proto->pr_flags & PR_ATOMIC) { if ((m->m_flags & M_PKTHDR) == 0) panic("somove pkthdr"); @@ -1324,10 +1333,12 @@ somove(struct socket *so, int wait) goto release; m->m_nextpkt = NULL; if (m->m_flags & M_PKTHDR) { + u_int8_t loopcnt = m->m_pkthdr.ph_loopcnt; m_tag_delete_chain(m); memset(&m->m_pkthdr, 0, sizeof(m->m_pkthdr)); m->m_pkthdr.len = len; m->m_pkthdr.pf.prio = IFQ_DEFPRIO; + m->m_pkthdr.ph_loopcnt = loopcnt; } /* Send window update to source peer as receive buffer has changed. */ Index: sys/netinet/tcp_output.c =================================================================== RCS file: /cvs/src/sys/netinet/tcp_output.c,v retrieving revision 1.113 diff -u -p -r1.113 tcp_output.c --- sys/netinet/tcp_output.c 13 Jul 2015 23:11:37 -0000 1.113 +++ sys/netinet/tcp_output.c 14 Jul 2016 02:56:27 -0000 @@ -732,6 +732,9 @@ send: goto out; } } + if (so->so_snd.sb_mb->m_flags & M_PKTHDR) + m->m_pkthdr.ph_loopcnt = + so->so_snd.sb_mb->m_pkthdr.ph_loopcnt; #endif /* * If we're sending everything we've got, set PUSH. Index: sys/sys/mbuf.h =================================================================== RCS file: /cvs/src/sys/sys/mbuf.h,v retrieving revision 1.195 diff -u -p -r1.195 mbuf.h --- sys/sys/mbuf.h 8 Jul 2015 07:21:50 -0000 1.195 +++ sys/sys/mbuf.h 14 Jul 2016 02:56:27 -0000 @@ -130,6 +130,7 @@ struct pkthdr { u_int16_t ether_vtag; /* Ethernet 802.1p+Q vlan tag */ u_int ph_rtableid; /* routing table id */ u_int ph_ifidx; /* rcv interface index */ + u_int8_t ph_loopcnt; /* mbuf is looping in kernel */ struct pkthdr_pf pf; }; @@ -464,6 +465,9 @@ struct m_tag *m_tag_next(struct mbuf *, * has payload larger than the value below. */ #define PACKET_TAG_MAXSIZE 52 + +/* Detect mbufs looping in the kernel when spliced too often. */ +#define M_MAXLOOP 128 /* * mbuf lists