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

Reply via email to