Hi, markus@ pointed out that it makes no sense to call pcb lookup from pf during packet forwarding.
While there remove a useless ifp parameter form ip_output_ipsec_send(). ok? bluhm Index: net/pf.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/net/pf.c,v retrieving revision 1.1046 diff -u -p -r1.1046 pf.c --- net/pf.c 20 Nov 2017 10:35:24 -0000 1.1046 +++ net/pf.c 21 Nov 2017 14:18:32 -0000 @@ -6776,6 +6776,17 @@ pf_test(sa_family_t af, int fwdir, struc } pd.m->m_pkthdr.pf.flags |= PF_TAG_PROCESSED; + /* + * Avoid pcb-lookups from the forwarding path. They should never + * match and would case MP locking problems. + */ + if (fwdir == PF_FWD) { + pd.lookup.done = -1; + pd.lookup.uid = UID_MAX; + pd.lookup.gid = GID_MAX; + pd.lookup.pid = NO_PID; + } + /* lock the lookup/write section of pf_test() */ PF_LOCK(); @@ -7072,7 +7083,8 @@ done: #ifdef INET6 /* if reassembled packet passed, create new fragments */ - if (pf_status.reass && action == PF_PASS && pd.m && fwdir == PF_FWD) { + if (pf_status.reass && action == PF_PASS && pd.m && fwdir == PF_FWD && + pd.af == AF_INET6) { struct m_tag *mtag; if ((mtag = m_tag_find(pd.m, PACKET_TAG_PF_REASSEMBLED, NULL))) Index: netinet/ip_output.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_output.c,v retrieving revision 1.343 diff -u -p -r1.343 ip_output.c --- netinet/ip_output.c 26 Oct 2017 15:13:40 -0000 1.343 +++ netinet/ip_output.c 21 Nov 2017 14:12:45 -0000 @@ -84,8 +84,7 @@ struct tdb * ip_output_ipsec_lookup(struct mbuf *m, int hlen, int *error, struct inpcb *inp, int ipsecflowinfo); int -ip_output_ipsec_send(struct tdb *tdb, struct mbuf *m, struct ifnet *ifp, - struct route *ro); +ip_output_ipsec_send(struct tdb *, struct mbuf *, struct route *, int); #endif /* IPSEC */ /* @@ -404,7 +403,8 @@ sendit: */ if (tdb != NULL) { /* Callee frees mbuf */ - error = ip_output_ipsec_send(tdb, m, ifp, ro); + error = ip_output_ipsec_send(tdb, m, ro, + (flags & IP_FORWARDING) ? 1 : 0); goto done; } #endif /* IPSEC */ @@ -413,7 +413,8 @@ sendit: * Packet filter */ #if NPF > 0 - if (pf_test(AF_INET, PF_OUT, ifp, &m) != PF_PASS) { + if (pf_test(AF_INET, (flags & IP_FORWARDING) ? PF_FWD : PF_OUT, + ifp, &m) != PF_PASS) { error = EACCES; m_freem(m); goto done; @@ -550,8 +551,7 @@ ip_output_ipsec_lookup(struct mbuf *m, i } int -ip_output_ipsec_send(struct tdb *tdb, struct mbuf *m, struct ifnet *ifp, - struct route *ro) +ip_output_ipsec_send(struct tdb *tdb, struct mbuf *m, struct route *ro, int fwd) { #if NPF > 0 struct ifnet *encif; @@ -563,7 +563,7 @@ ip_output_ipsec_send(struct tdb *tdb, st * Packet filter */ if ((encif = enc_getif(tdb->tdb_rdomain, tdb->tdb_tap)) == NULL || - pf_test(AF_INET, PF_OUT, encif, &m) != PF_PASS) { + pf_test(AF_INET, fwd ? PF_FWD : PF_OUT, encif, &m) != PF_PASS) { m_freem(m); return EACCES; }