panic on ip_input, ip_len byte ordering problem?
kevin brintnall
kbrint at rufus.net
Sat Jul 11 04:13:52 UTC 2009
Hi,
Here is my system:
FreeBSD fw.rufus.net 7.2-RELEASE-p1 FreeBSD 7.2-RELEASE-p1 #1: Wed Jun 10 11:32:28 CDT 2009 root at hamachi.rufus.net:/usr/obj/usr/src/sys/SOEKRIS i386
I am seeing occasional panics in ip_input when forwarding IP traffic at
low rates (<100pkt/sec).
Fatal trap 12: page fault while in kernel mode
cpuid = 0; apic id = 00
fault virtual address = 0xc
fault code = supervisor read, page not present
instruction pointer = 0x20:0xc0872228
stack pointer = 0x28:0xc17f2b20
frame pointer = 0x28:0xc17f2b3c
code segment = base 0x0, limit 0xfffff, type 0x1b
= DPL 0, pres 1, def32 1, gran 1
processor eflags = interrupt enabled, resume, IOPL = 0
current process = 20 (irq10: sis0 sis1+)
trap number = 12
panic: page fault
cpuid = 0
Uptime: 12d10h48m45s
Physical memory: 115 MB
Dumping 49 MB: 34 18 2
Dump complete
The stack trace is as follows:
#5 0xc0b502cc in trap (frame=0xc17f2ae0) at /usr/src/sys/i386/i386/trap.c:530
#6 0xc0b342bb in calltrap () at /usr/src/sys/i386/i386/exception.s:159
#7 0xc0872228 in m_copydata (m=0x0, off=0, len=88,
cp=0xc1aeb6a8 "some garbage") at /usr/src/sys/kern/uipc_mbuf.c:815
#8 0xc090a728 in ip_forward (m=0xc19f0700, srcrt=0)
at /usr/src/sys/netinet/ip_input.c:1307
#9 0xc090bf0c in ip_input (m=0xc19f0700)
at /usr/src/sys/netinet/ip_input.c:609
#10 0xc08c9fa5 in netisr_dispatch (num=2, m=0xc19f0700)
at /usr/src/sys/net/netisr.c:185
m_copydata is walking off the end of the mbuf chain.. It turns out that
the IP header length is incorrect.
Here is the code from frame 8:
1304 if (mcopy != NULL) {
1305 mcopy->m_len = min(ip->ip_len, M_TRAILINGSPACE(mcopy));
1306 mcopy->m_pkthdr.len = mcopy->m_len;
1307 m_copydata(m, 0, mcopy->m_len, mtod(mcopy, caddr_t));
1308 }
The packet is 116 bytes, which is correctly reflected in the mbuf header.
However, the IP packet length appears to be in network byte order rather
than host byte order. Note that 29696=ntohs(116).
(kgdb) p m->m_hdr->mh_len
$55 = 116
(kgdb) p mcopy->m_hdr->mh_len
$56 = 204
(kgdb) p ip->ip_len
$57 = 29696 <<-- should be 116!
The rest of the IP header looks correct:
$58 = {ip_hl = 5, ip_v = 4, ip_tos = 16 '\020', ip_len = 29696, ip_id = 38700,
ip_off = 64, ip_ttl = 58 ':', ip_p = 6 '\006', ip_sum = 5172, ip_src = {
s_addr = X}, ip_dst = {s_addr = 1139586513}}
When ip_input is initially called, I think the ip_len must be right..
Otherwise, the "tooshort" block around ip_input.c:383 would stop
processing.
if (m->m_pkthdr.len < ip->ip_len) {
tooshort:
ipstat.ips_tooshort++;
goto bad;
}
Any ideas? My best guess is that there exists a code path in PF somewhere
that is doing an uneven number of ntohs() and htons().
Thanks in advance!
--
kevin brintnall =~ /kbrint at rufus.net/
More information about the freebsd-net
mailing list