pf panic trace [Was: Re: Return-icmp doesn't work]

Pyun YongHyeon yongari at kt-is.co.kr
Fri Mar 11 21:07:46 PST 2005


On Fri, Mar 11, 2005 at 05:12:31PM +0100, Emanuel Strobl wrote:
 > Am Freitag, 11. M?rz 2005 16:19 schrieb Emanuel Strobl:
 > > Am Freitag, 11. M?rz 2005 14:52 schrieb Daniel Hartmeier:
 > > >   block return-rst in on wi0 reply-to (wi0 10.1.1.1) inet proto tcp all
 > > >
 > > > This is valid syntax and pfctl loads the rule, but the functionality is
 > > > not implemented in kernel yet, i.e. the reply-to option is simply
 > > > ignored.
 > >
 > > Thanks, I tried a very similar rule and after that the box vanished.
 > > I went on location (the box paniced but didn't reboot) and installed a
 > > console-server so I can access the box from here and currently I'm baking a
 > > debug kernel.
 > > I'll notify you if I have a trace!
 > 
 > Here's the original panic message (the non debug kernel) with 5.4-PRE one week 
 > old:
 > Fatal trap 12: page fault while in kernel mode
 > fault virtual address   = 0xc
 > fault code              = supervisor read, page not pre
 > instruction pointer     = 0x8:0xc05ac722
 > stack pointer           = 0x10:0xcc6919ac
 > frame pointer           = 0x10:0xcc6919e0
 > code segment            = base 0x0, limit 0xfffff, type
 >                         = DPL 0, pres 1, def32 1, gran
 > processor eflags        = interrupt enabled, resume, IO
 > current process         = 34 (swi1: net)
 > trap number             = 12
 > panic: page fault
 > Uptime: 1d1h20m33s
 > GEOM_MIRROR: Device web: provider mirror/web destroyed.
 > GEOM_MIRROR: Device web destroyed.
 > ...
 > The machine didn't reboot!
 > 
 > 
 > The following rule panickes the machine:
 > block return-icmp(13) in on $SDSL route-to ($SDSL $sdsl_gw) from any to 
 > $sdsl_net
 > 
 > Here's the trace from 5.4-PRE today:
 > panic: m_copym, offset > size of mbuf chain
 > KDB: stack backtrace:
 > panic(c076ab9a,c174d500,100,cc694a30,0) at panic+0x13c
 > m_copym(c1621b00,5dc,5c8,1,14) at m_copym+0x1c7
 > ip_fragment(c1642010,cc694a74,5dc,6,f01) at ip_fragment+0x168
 > pf_route(cc694bf0,c1a10d20,1,c1585000,0) at pf_route+0x767
 > pf_test(1,c1585000,cc694bf0,0,c17554e0) at pf_test+0x7b1
 > pf_check_in(0,cc694bf0,c1585000,1,0) at pf_check_in+0x48
 > pfil_run_hooks(c07f3e60,cc694c9c,c1585000,1,0) at pfil_run_hooks+0x15b
 > ip_input(c1621b00,0,c076e621,e6,c07f3f20) at ip_input+0x20f
 > netisr_processqueue(cc694cd8,246,c07c8ee0,2,c1508d40) at 
 > netisr_processqueue+0x15
 > swi_net(0,0,c0762ddc,269,0) at swi_net+0x8d
 > ithread_loop(c1526300,cc694d48,c0762bbd,30e,0) at ithread_loop+0x1ff
 > fork_exit(c0560640,c1526300,cc694d48) at fork_exit+0xa9
 > fork_trampoline() at fork_trampoline+0x8
 > --- trap 0x1, eip = 0, esp = 0xcc694d7c, ebp = 0 ---
 > 
 > If you need more info, on http://www.schmalzbauer.de/statics/phobos you can 
 > find dmesg and the whole pf.conf
 > 

Hmm, Max and I had seen these kind of traces when pf porting
was in progress. But now I believe we fixed all possible
cases.

I can't sure but your trace indicates there is a bug in
ip_fragment(). If a packet already set IP_MF flag in ip header,
we would get invalid ip_off in fragmented packet.
And it seems that there is another bug in pf. Since ip_fragment()
can change passed mbuf, we should not use saved copy of it.
Untested patch for CURRENT attached.

-- 
Regards,
Pyun YongHyeon
http://www.kr.freebsd.org/~yongari	|	yongari at freebsd.org
-------------- next part --------------
--- sys/netinet/ip_output.c.orig	Tue Mar  1 20:57:14 2005
+++ sys/netinet/ip_output.c	Sat Mar 12 13:50:54 2005
@@ -959,7 +959,7 @@
 		}
 		m->m_len = mhlen;
 		/* XXX do we need to add ip->ip_off below ? */
-		mhip->ip_off = ((off - hlen) >> 3) + ip->ip_off;
+		mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
 		if (off + len >= ip->ip_len) {	/* last fragment */
 			len = ip->ip_len - off;
 			m->m_flags |= M_LASTFRAG;
-------------- next part --------------
--- sys/contrib/pf/net/pf.c.orig	Tue Feb 22 10:30:53 2005
+++ sys/contrib/pf/net/pf.c	Sat Mar 12 12:42:37 2005
@@ -5421,7 +5421,6 @@
 			goto bad;
 	}
 
-	m1 = m0;
 #ifdef __FreeBSD__
 	/*
 	 * XXX: is cheaper + less error prone than own function
@@ -5430,6 +5429,7 @@
 	NTOHS(ip->ip_off);
 	error = ip_fragment(ip, &m0, ifp->if_mtu, ifp->if_hwassist, sw_csum);
 #else
+	m1 = m0;
 	error = ip_fragment(m0, ifp, ifp->if_mtu);
 #endif
 	if (error) {
@@ -5439,10 +5439,14 @@
 		goto bad;
 	}
 
+#ifdef __FreeBSD__
+	for (; m0; m0 = m1) {
+#else
 	for (m0 = m1; m0; m0 = m1) {
+#endif
 		m1 = m0->m_nextpkt;
-		m0->m_nextpkt = 0;
 #ifdef __FreeBSD__
+		m0->m_nextpkt = NULL;
 		if (error == 0) {
 			PF_UNLOCK();
 			error = (*ifp->if_output)(ifp, m0, sintosa(dst),
@@ -5450,6 +5454,7 @@
 			PF_LOCK();
 		} else
 #else
+		m0->m_nextpkt = 0;
 		if (error == 0)
 			error = (*ifp->if_output)(ifp, m0, sintosa(dst),
 			    NULL);


More information about the freebsd-pf mailing list