tech-net archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

panic: mbuf too short for IPv6 header



Hi,
on a recent -current (kernel sources as of yesterday), I've got several
panic: mbuf too short for IPv6 header

with the stack trace being:
0x0(0xf0c60500, 0x3a, 0x28, 0x169, 0xf2668dcc, 0x28) at netbsd:icmp6_input+0x78
icmp6_input(0xf0c60500, 0xf2668e70, 0x3a, 0xf2668e74, 0x6, 0x1) at 
netbsd:ip6_input+0x8ec
ip6_input(0x0, 0xe, 0x0, 0xf21474f0, 0x52e1474c, 0xf02ef580) at 
netbsd:ip6intr+0x68
ip6intr(0xf02ef400, 0xf2668edc, 0xf02ea400, 0x10, 0x44, 0x0) at 
netbsd:softint_thread+0x90
softint_thread(0xf212d170, 0xf2147980, 0xf02a8ac0, 0x0, 0x904010e1, 0x90401fe1) 
at netbsd:lwp_trampoline+0x8
End traceback...

I think it's related to running named on this box. Without named running,
the box had been up for several hours; with named the panic occurs in less
than one hour (tried 3 times).

Looking at the mail archives, it seems this issue has already been reported,
but I didn't find a definitive fix. The attached patch mimics code in
ipv4 icmp_input, and makes sure the related mbuf part is contigous and
writeable. With this patch, the box has been up for 13 hours with named
running, without problems. Does it look right ?

-- 
Manuel Bouyer <bouyer%antioche.eu.org@localhost>
     NetBSD: 26 ans d'experience feront toujours la difference
--
Index: icmp6.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/icmp6.c,v
retrieving revision 1.146
diff -u -r1.146 icmp6.c
--- icmp6.c     23 Apr 2008 05:26:50 -0000      1.146
+++ icmp6.c     4 May 2008 10:50:29 -0000
@@ -455,7 +455,7 @@
        struct icmp6_hdr *icmp6, *nicmp6;
        int off = *offp;
        int icmp6len = m->m_pkthdr.len - *offp;
-       int code, sum, noff;
+       int code, sum, noff, i;
 
 #define ICMP6_MAXLEN (sizeof(*nip6) + sizeof(*nicmp6) + 4)
        KASSERT(ICMP6_MAXLEN < MCLBYTES);
@@ -466,13 +466,19 @@
         * that not corrupted and of at least minimum length
         */
 
-       ip6 = mtod(m, struct ip6_hdr *);
        if (icmp6len < sizeof(struct icmp6_hdr)) {
                ICMP6_STATINC(ICMP6_STAT_TOOSHORT);
                icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_error);
                goto freeit;
        }
 
+       i = off + sizeof(*icmp6);
+       if ((m->m_len < i || M_READONLY(m)) && (m = m_pullup(m, i)) == 0) {
+               ICMP6_STATINC(ICMP6_STAT_TOOSHORT);
+               icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_error);
+               goto freeit;
+       }
+       ip6 = mtod(m, struct ip6_hdr *);
        /*
         * calculate the checksum
         */


Home | Main Index | Thread Index | Old Index