m_getptr(m, 0, ...) may return an mbuf different from m -- if m has no
authorclaudio <claudio@openbsd.org>
Thu, 15 Jul 2010 09:45:09 +0000 (09:45 +0000)
committerclaudio <claudio@openbsd.org>
Thu, 15 Jul 2010 09:45:09 +0000 (09:45 +0000)
data in it. m_getptr() hops over empty buffers and points to the first
allocated data byte. Because of this the m_dup_pkthdr() call done by
m_copym0() can panic because not the first mbuf is passed.
Found the hard way by myself, diff by blambert@ commiitting for him since
he is not around. Tested and OK myself

sys/kern/uipc_mbuf.c

index 1b6400c..a823ea6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uipc_mbuf.c,v 1.142 2010/07/14 10:31:54 matthew Exp $ */
+/*     $OpenBSD: uipc_mbuf.c,v 1.143 2010/07/15 09:45:09 claudio Exp $ */
 /*     $NetBSD: uipc_mbuf.c,v 1.15.4.1 1996/06/13 17:11:44 cgd Exp $   */
 
 /*
@@ -620,17 +620,17 @@ m_copym2(struct mbuf *m, int off, int len, int wait)
 }
 
 struct mbuf *
-m_copym0(struct mbuf *m, int off, int len, int wait, int deep)
+m_copym0(struct mbuf *m0, int off, int len, int wait, int deep)
 {
-       struct mbuf *n, **np;
+       struct mbuf *m, *n, **np;
        struct mbuf *top;
        int copyhdr = 0;
 
        if (off < 0 || len < 0)
                panic("m_copym0: off %d, len %d", off, len);
-       if (off == 0 && m->m_flags & M_PKTHDR)
+       if (off == 0 && m0->m_flags & M_PKTHDR)
                copyhdr = 1;
-       if ((m = m_getptr(m, off, &off)) == NULL)
+       if ((m = m_getptr(m0, off, &off)) == NULL)
                panic("m_copym0: short mbuf chain");
        np = &top;
        top = NULL;
@@ -645,7 +645,7 @@ m_copym0(struct mbuf *m, int off, int len, int wait, int deep)
                if (n == NULL)
                        goto nospace;
                if (copyhdr) {
-                       if (m_dup_pkthdr(n, m))
+                       if (m_dup_pkthdr(n, m0))
                                goto nospace;
                        if (len != M_COPYALL)
                                n->m_pkthdr.len = len;