This patch fixes two issues in m_split() in sys/kern/uipc_mbuf.c, which are correctly handled in FreeBSD's m_split():
If the m_split() would split an mbuf chain exactly between 2 mbufs (i.e. remain == 0), the returned M_PKTHDR might unnecessarily reference an mbuf cluster from the first part of the original mbuf chain. So the returned mbuf would have the M_EXT flag set in n->m_flags, but with n->m_len == 0. Instead m_split should explicitly handle that case. The second issue fixes a case in m_split() where n->m_len isn't initialized explicitly before returning, and also wasn't pre-zeroed by MGETHDR (since that calls pool_get without PR_ZERO flag). Index: uipc_mbuf.c =================================================================== RCS file: /cvs/src/sys/kern/uipc_mbuf.c,v retrieving revision 1.239 diff -u -r1.239 uipc_mbuf.c --- uipc_mbuf.c 29 Nov 2016 10:22:30 -0000 1.239 +++ uipc_mbuf.c 24 Jan 2017 14:07:03 -0000 @@ -1013,6 +1013,12 @@ n->m_pkthdr.len -= len0; olen = m0->m_pkthdr.len; m0->m_pkthdr.len = len0; + if (remain == 0) { + n->m_next = m->m_next; + m->m_next = NULL; + n->m_len = 0; + return (n); + } if (m->m_flags & M_EXT) goto extpacket; if (remain > MHLEN) { @@ -1023,8 +1029,10 @@ (void) m_free(n); m0->m_pkthdr.len = olen; return (NULL); - } else + } else { + n->m_len = 0; return (n); + } } else MH_ALIGN(n, remain); } else if (remain == 0) {