From f118729edc25580d2a952dfa1dc302a7259dfc88 Mon Sep 17 00:00:00 2001 From: dlg Date: Thu, 23 Nov 2023 23:45:10 +0000 Subject: [PATCH] avoid passing weird mbuf chains to pf when pushing out a veb. 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 | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/sys/net/if_veb.c b/sys/net/if_veb.c index df405678fa3..cbdc3fb7d53 100644 --- a/sys/net/if_veb.c +++ b/sys/net/if_veb.c @@ -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 @@ -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; -- 2.20.1