Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 27 May 2012 18:30:09 GMT
From:      Joerg Pulz <Joerg.Pulz@frm2.tum.de>
To:        freebsd-pf@FreeBSD.org
Subject:   Re: kern/168190: [pf] panic when using pf and route-to (maybe: bad fragment handling?)
Message-ID:  <201205271830.q4RIU9fA039893@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/168190; it has been noted by GNATS.

From: Joerg Pulz <Joerg.Pulz@frm2.tum.de>
To: Daniel Hartmeier <daniel@benzedrine.cx>
Cc: freebsd-pf@freebsd.org, bug-followup@freebsd.org
Subject: Re: kern/168190: [pf] panic when using pf and route-to (maybe: bad fragment handling?)
Date: Sun, 27 May 2012 20:27:58 +0200

 Daniel Hartmeier <daniel@benzedrine.cx> wrote:
 
 >On Fri, May 25, 2012 at 07:30:16AM +0000, Joerg Pulz wrote:
 >
 >>  the system is still running without panic, but i found the following
 >log 
 >>  entries from last night:
 >>  
 >>  May 24 23:28:57 charon kernel: pf_route: m0->m_len < sizeof(struct
 >ip)
 >>  May 24 23:28:57 charon kernel: pf_route: m0->m_len < sizeof(struct
 >ip)
 >>  
 >>  Do you think that this may be related to the panics?
 >>  I've found this error message two times in contrib/pf/net/pf.c.
 >>  I can't say which of them or both have printed the message.
 >
 >Yes, this could possibly explain it.
 >
 >All pfil consumers assume that the IP header is one continuous memory
 >region in the mbuf, without verifying this or correcting it (with
 >m_pullup() or such) if wrong.
 >
 >pf: pf_check_in() in sys/contrib/pf/net/pf_ioctl.c
 >	h = mtod(*m, struct ip *);
 >	access h->ip_len
 >
 >ipfw: ipfw_check_hook() in sys/netinet/ipfw/ip_fw_pfil.c
 >	SET_NET_IPLEN(mtod(*m0, struct ip *));
 >
 >ipfilter: fr_check_wrapper() in
 >sys/contrib/ipfilter/netinet/ip_fil_freebsd.c
 >	struct ip *ip = mtod(*mp, struct ip *);
 >	access ip->ip_hl
 >
 >Hence, the caller of pfil_run_hooks() must ensure this before the call.
 >ip_input() does, but there are operations that might violate the
 >condition again.
 >
 >If the IP header is not continuous in the first mbuf, doing
 >
 >	struct ip *ip = mtod(m, struct ip *);
 >	ip->ip_len = ntohs(ip->ip_len);
 >
 >will read (and write) unrelated memory.
 >
 >If, later, something does call m_pullup(), ip_len will get 'replaced'
 >again. This could lead to some byte order swaps getting undone.
 >
 >I'm not sure what the proper action is here, i.e. should we be
 >surprised
 >that an mbuf with such a small m_len is found, and track down how it
 >was produced, or should the pfil code simply expect this?
 >
 >I'd probably add a sanity check to pfil_run_hooks(), like
 >
 >--- sys/net/pfil.c      23 Sep 2011 00:51:37 -0000      1.19.2.1
 >+++ sys/net/pfil.c      25 May 2012 09:10:27 -0000
 >@@ -46,6 +46,8 @@
 >
 > #include <net/if.h>
 > #include <net/pfil.h>
 >+#include <netinet/in.h>
 >+#include <netinet/ip.h>
 >
 > static struct mtx pfil_global_lock;
 >
 >@@ -74,15 +76,21 @@
 >        struct mbuf *m = *mp;
 >        int rv = 0;
 >
 >+       if (m->m_pkthdr.len < sizeof(struct ip) ||
 >+           m->m_len < sizeof(struct ip))
 >+               panic("pfil_run_hooks: m->m_pkthdr.len %d, m->m_len
 >%d",
 >+                   (int)m->m_pkthdr.len, (int)m->m_len);
 >        PFIL_RLOCK(ph, &rmpt);
 >        KASSERT(ph->ph_nhooks >= 0, ("Pfil hook count dropped < 0"));
 >        for (pfh = pfil_hook_get(dir, ph); pfh != NULL;
 >             pfh = TAILQ_NEXT(pfh, pfil_link)) {
 >                if (pfh->pfil_func != NULL) {
 >+                       ASSERT_HOST_BYTE_ORDER(m);
 >                    rv = (*pfh->pfil_func)(pfh->pfil_arg, &m, ifp, dir,
 >                            inp);
 >                        if (rv != 0 || m == NULL)
 >                                break;
 >+                       ASSERT_HOST_BYTE_ORDER(m);
 >                }
 >        }
 >        PFIL_RUNLOCK(ph, &rmpt);
 >
 >Then when it will panic (instead of just the pf_route() message), the
 >stack trace could help.
 >
 >This might require several iterations, adding such checks all around
 >the
 >place. The cause might be some mbuf operation done in ipsec, for some
 >edge case, explaining why it occurs so rarely...
 >
 >If I could easily reproduce it locally, I'd probably do it, but it's
 >your machine that crashes all the time, so it's your call :)
 >
 >Daniel
 
 Daniel,
 
 i've seen 12 more "pf_route: m0->m_len < sizeof(struct ip)" messages since the system is running after adding your patch, but no panic.
 Is there another place in the code where i can add an additional check?
 
 Kind regards
 Jörg



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201205271830.q4RIU9fA039893>