avoid passing weird mbuf chains to pf when pushing out a veb.
authordlg <dlg@openbsd.org>
Thu, 23 Nov 2023 23:45:10 +0000 (23:45 +0000)
committerdlg <dlg@openbsd.org>
Thu, 23 Nov 2023 23:45:10 +0000 (23:45 +0000)
pf expects the ip header to be in the first mbuf of the chain we
pass to pf_test, but in some situations the ethernet header is the
only data in the first mbuf. after we remove the ethernet header,
the first mbuf had no data in it which confused pf. fix this by
passing all packets to ip_check on output as well as input. ip input
handlers do all the necessary m_pullups.

found by Mark Patruck.

sys/net/if_veb.c

index df40567..cbdc3fb 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_veb.c,v 1.31 2023/05/16 14:32:54 jan Exp $ */
+/*     $OpenBSD: if_veb.c,v 1.32 2023/11/23 23:45:10 dlg Exp $ */
 
 /*
  * Copyright (c) 2021 David Gwynne <dlg@openbsd.org>
@@ -612,6 +612,7 @@ veb_pf(struct ifnet *ifp0, int dir, struct mbuf *m)
 {
        struct ether_header *eh, copy;
        const struct veb_pf_ip_family *fam;
+       int hlen;
 
        /*
         * pf runs on vport interfaces when they enter or leave the
@@ -640,11 +641,9 @@ veb_pf(struct ifnet *ifp0, int dir, struct mbuf *m)
        copy = *eh;
        m_adj(m, sizeof(*eh));
 
-       if (dir == PF_IN) {
-               m = (*fam->ip_check)(ifp0, m);
-               if (m == NULL)
-                       return (NULL);
-       }
+       m = (*fam->ip_check)(ifp0, m);
+       if (m == NULL)
+               return (NULL);
 
        if (pf_test(fam->af, dir, ifp0, &m) != PF_PASS) {
                m_freem(m);
@@ -660,12 +659,14 @@ veb_pf(struct ifnet *ifp0, int dir, struct mbuf *m)
                return (NULL);
        }
 
-       m = m_prepend(m, sizeof(*eh), M_DONTWAIT);
+       hlen = roundup(sizeof(*eh), sizeof(long));
+       m = m_prepend(m, hlen, M_DONTWAIT);
        if (m == NULL)
                return (NULL);
 
        /* checksum? */
 
+       m_adj(m, hlen - sizeof(*eh));
        eh = mtod(m, struct ether_header *);
        *eh = copy;