Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 17 Apr 2012 12:14:06 +0400
From:      Gleb Smirnoff <glebius@FreeBSD.org>
To:        Ermal Lu?i <eri@FreeBSD.org>
Cc:        freebsd-pf@FreeBSD.org
Subject:   Re: kern/164402: [pf] pf crashes with a particular set of rules when first matching packet arrives
Message-ID:  <20120417081406.GA93887@glebius.int.ru>
In-Reply-To: <CAPBZQG2Tjg36GNCBetRZ20FhQnL1sK9i_-oQDDb97bcb4N=sLA@mail.gmail.com>
References:  <201204151200.q3FC0LT5085161@freefall.freebsd.org> <20120416185949.GC92286@FreeBSD.org> <CAPBZQG2Tjg36GNCBetRZ20FhQnL1sK9i_-oQDDb97bcb4N=sLA@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Tue, Apr 17, 2012 at 10:06:15AM +0200, Ermal Lu?i wrote:
E> 2012/4/16 Gleb Smirnoff <glebius@freebsd.org>:
E> > On Sun, Apr 15, 2012 at 12:00:21PM +0000, Gleb Smirnoff wrote:
E> > T> šOn Sun, Apr 15, 2012 at 11:10:03AM +0000, Gleb Smirnoff wrote:
E> > T> šT> š šI have a vague suspicion on what is happening. Your description of
E> > T> šT> šthe problem looks like if a packet processing in the kernel has entered
E> > T> šT> šan endless loop.
E> > T> šT>
E> > T> šT> š šLooking at pf_route() I see such possibility. From OpenBSD we have
E> > T> šT> šthis protection against endless looping:
E> > T> šT>
E> > T> šT> š š š š šif ((*m)->m_pkthdr.pf.routed++ > 3) {
E> > T> šT> š š š š š š š š šm0 = *m;
E> > T> šT> š š š š š š š š š*m = NULL;
E> > T> šT> š š š š š š š š šgoto bad;
E> > T> šT> š š š š š}
E> > T> šT>
E> > T> šT> šIn our code this transforms to:
E> > T> šT>
E> > T> šT> š š š š šif (pd->pf_mtag->routed++ > 3) {
E> > T> šT> š š š š š š š š šm0 = *m;
E> > T> šT> š š š š š š š š š*m = NULL;
E> > T> šT> š š š š š š š š šgoto bad;
E> > T> šT> š š š š š}
E> > T> šT>
E> > T> šT> šThe root difference between storing the tag on mbuf and on pfdesc
E> > T> šT> šis that we lose pfdesc, and thus the tag, when we enter pf_test()
E> > T> šT> šrecursively. And pf_route() does this recursion:
E> > T> šT>
E> > T> šT> š š š š šif (oifp != ifp) {
E> > T> šT> š š š š š š š š šif (pf_test(PF_OUT, ifp, &m0, NULL) != PF_PASS) {
E> > T> šT> š š š š š š š š š š š š šgoto bad;
E> > T> šT> š š š š š....
E> > T>
E> > T> šOn second look I see that my suspicion may not be true. In the
E> > T> šbeginning of pf_test() we do pf_get_mtag() which preserves already
E> > T> špresent tag if there is one.
E> >
E> > Further investigation showed that problem exist when route applied
E> > ends in lo0, and packet passes to if_simloop(). There all mtags are
E> > stripped from the mbuf, including the pf mtag. Then packet is again
E> > processed by ip_input() again entering pf(4), if it again matches
E> > a routing rule, then we got an endless loop.
E> >
E> > We can try to fix this applying MTAG_PERSISTENT to the pf(4) tag id.
E> 
E> That seems like the best fix for this case.

In this case crash or freeze is fixed, but still packet is dropped. Example
of such rule:

pass in on igb0 fastroute proto tcp from any to $localip

Anyway, dropping packets is much better than crashing.

-- 
Totus tuus, Glebius.



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