Hi, There is a corner case where linking the inp to the state key does not work in pf. The function pf_inp_link() takes the state key from the mbuf and not the one we have just found. Introduce a new function pf_state_key_link_inpcb() that does exactly that together with some sanity checks.
I have regress tests that can trigger cases where this is relevant. ok? bluhm Index: net/pf.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/net/pf.c,v retrieving revision 1.1050 diff -u -p -r1.1050 pf.c --- net/pf.c 4 Dec 2017 15:13:12 -0000 1.1050 +++ net/pf.c 22 Dec 2017 14:21:09 -0000 @@ -249,6 +249,8 @@ void pf_state_key_link(struct pf_stat struct pf_state_key *); void pf_inpcb_unlink_state_key(struct inpcb *); void pf_state_key_unlink_reverse(struct pf_state_key *); +void pf_state_key_link_inpcb(struct pf_state_key *, + struct inpcb *); #if NPFLOG > 0 void pf_log_matches(struct pf_pdesc *, struct pf_rule *, @@ -1085,8 +1087,9 @@ pf_find_state(struct pfi_kif *kif, struc if (dir == PF_OUT && pkt_sk && pf_compare_state_keys(pkt_sk, sk, kif, dir) == 0) pf_state_key_link(sk, pkt_sk); - else if (dir == PF_OUT) - pf_inp_link(m, m->m_pkthdr.pf.inp); + else if (dir == PF_OUT && m->m_pkthdr.pf.inp && + !m->m_pkthdr.pf.inp->inp_pf_sk && !sk->inp) + pf_state_key_link_inpcb(sk, m->m_pkthdr.pf.inp); } /* remove firewall data from outbound packet */ @@ -7259,6 +7262,15 @@ void pf_pkt_state_key_ref(struct mbuf *m) { pf_state_key_ref(m->m_pkthdr.pf.statekey); +} + +void +pf_state_key_link_inpcb(struct pf_state_key *sk, struct inpcb *inp) +{ + KASSERT(sk->inp == NULL); + sk->inp = inp; + KASSERT(inp->inp_pf_sk == NULL); + inp->inp_pf_sk = pf_state_key_ref(sk); } void