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) {