untrusted comment: signature from openbsd 5.9 base secret key
RWQJVNompF3pwTjgCAPs773lqZHz26l/fugXC2L0N8EjkzFz4ZoW8xwCV0/2VlAPu28lp+dE7DMQcVJv3Wf6FvYarYgr0FtmUQw=
OpenBSD 5.9 errata 13, Jul 14, 2016:
Splicing sockets in a loop could cause a kernel spin.
Apply by doing:
signify -Vep /etc/signify/openbsd-59-base.pub -x 013_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_mbuf.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_mbuf.c,v
retrieving revision 1.219.2.1
diff -u -p -r1.219.2.1 uipc_mbuf.c
--- sys/kern/uipc_mbuf.c 28 Apr 2016 22:31:55 -0000 1.219.2.1
+++ sys/kern/uipc_mbuf.c 14 Jul 2016 02:55:23 -0000
@@ -254,6 +254,7 @@ void
m_resethdr(struct mbuf *m)
{
int len = m->m_pkthdr.len;
+ u_int8_t loopcnt = m->m_pkthdr.ph_loopcnt;
KASSERT(m->m_flags & M_PKTHDR);
m->m_flags &= (M_EXT|M_PKTHDR|M_EOR|M_EXTWR|M_ZEROIZE);
@@ -265,6 +266,7 @@ m_resethdr(struct mbuf *m)
memset(&m->m_pkthdr, 0, sizeof(m->m_pkthdr));
m->m_pkthdr.pf.prio = IFQ_DEFPRIO;
m->m_pkthdr.len = len;
+ m->m_pkthdr.ph_loopcnt = loopcnt;
}
struct mbuf *
@@ -1265,7 +1267,8 @@ m_print(void *v,
(*pr)("m_ptkhdr.ph_tags: %p\tm_pkthdr.ph_tagsset: %b\n",
SLIST_FIRST(&m->m_pkthdr.ph_tags),
m->m_pkthdr.ph_tagsset, MTAG_BITS);
- (*pr)("m_pkthdr.ph_flowid: %u\n", m->m_pkthdr.ph_flowid);
+ (*pr)("m_pkthdr.ph_flowid: %u\tm_pkthdr.ph_loopcnt: %u\n",
+ m->m_pkthdr.ph_flowid, m->m_pkthdr.ph_loopcnt);
(*pr)("m_pkthdr.csum_flags: %b\n",
m->m_pkthdr.csum_flags, MCS_BITS);
(*pr)("m_pkthdr.ether_vtag: %u\tm_ptkhdr.ph_rtableid: %u\n",
Index: sys/kern/uipc_socket.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_socket.c,v
retrieving revision 1.149
diff -u -p -r1.149 uipc_socket.c
--- sys/kern/uipc_socket.c 15 Jan 2016 11:58:34 -0000 1.149
+++ sys/kern/uipc_socket.c 14 Jul 2016 02:55:23 -0000
@@ -1199,7 +1199,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;
}
@@ -1255,6 +1255,15 @@ somove(struct socket *so, int wait)
(so->so_proto->pr_usrreq)(so, PRU_RCVD, NULL,
(struct mbuf *)0L, NULL, NULL);
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) {
Index: sys/netinet/tcp_output.c
===================================================================
RCS file: /cvs/src/sys/netinet/tcp_output.c,v
retrieving revision 1.116
diff -u -p -r1.116 tcp_output.c
--- sys/netinet/tcp_output.c 5 Dec 2015 10:52:26 -0000 1.116
+++ sys/netinet/tcp_output.c 14 Jul 2016 02:55:23 -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.208
diff -u -p -r1.208 mbuf.h
--- sys/sys/mbuf.h 23 Feb 2016 01:39:14 -0000 1.208
+++ sys/sys/mbuf.h 14 Jul 2016 02:55:23 -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;
};
@@ -485,6 +486,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