kern/168190: [pf] panic when using pf and route-to (maybe: bad
fragment handling?)
Darren Reed
darrenr at freebsd.org
Tue Jun 5 18:13:18 UTC 2012
To echo comments made on tech-net for NetBSD...
---
As much as I dislike the patch you created, I can't see any other way
to elegantly solve the problem. The reason that I don't like the change
is that it seems silly to have to put the packet in two different mbufs
after having put it all in one. I'll file this as a workaround for the
code in m_pulldown() being buggy.
The patch below should work for FreeBSD (includes IPv6 code.)
The greater problem that I see here is what if someone else were to use
m_pulldown in their home-brew code that uses pfil ... from that angle,
there should be a responsibility to make the interfaces more robust but
perhaps that can be achieved with documentation updates.
---
But otherwise, the root cause of this problem is not solved with this
patch. It's just a workaround.
Darren
*** ip_fil_freebsd.c.orig 26 Jan 2012 06:03:43 -0000
--- ip_fil_freebsd.c 5 Jun 2012 18:09:25 -0000
***************
*** 171,177 ****
fr_check_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
{
struct ip *ip = mtod(*mp, struct ip *);
! return fr_check(ip, ip->ip_hl << 2, ifp, (dir == PFIL_OUT), mp);
}
# ifdef USE_INET6
--- 171,186 ----
fr_check_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
{
struct ip *ip = mtod(*mp, struct ip *);
! int hlen = ip->ip_hl << 2;
! struct mbuf *m;
! int rv;
!
! rv = fr_check(ip, hlen, ifp, (dir == PFIL_OUT), mp);
! if ((rv == 0) && ((m = *mp) != NULL)) {
! if (m->m_len < hlen)
! *mp = m_pullup(m, hlen);
! }
! return rv;
}
# ifdef USE_INET6
***************
*** 180,187 ****
static int
fr_check_wrapper6(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
{
! return (fr_check(mtod(*mp, struct ip *), sizeof(struct ip6_hdr),
! ifp, (dir == PFIL_OUT), mp));
}
# endif
#endif /* __FreeBSD_version >= 501108 */
--- 189,204 ----
static int
fr_check_wrapper6(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
{
! struct mbuf *m;
! int rv;
!
! rv = fr_check(mtod(*mp, struct ip *), sizeof(struct ip6_hdr),
! ifp, (dir == PFIL_OUT), mp);
! if ((rv == 0) && ((m = *mp) != NULL)) {
! if (m->m_len < sizeof(struct ip6_hdr))
! *mp = m_pullup(m, sizeof(struct ip6_hdr));
! }
! return rv;
}
# endif
#endif /* __FreeBSD_version >= 501108 */
More information about the freebsd-net
mailing list