summaryrefslogtreecommitdiff
path: root/sys/net/pf.c
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2017-12-24 14:18:20 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2017-12-24 14:18:20 +0000
commita41077d7835e4740f073af57bb948aa525dba99f (patch)
tree09185bd5f06adaf768ecf7e910d5bfe31f0c9880 /sys/net/pf.c
parent5e12d26c40a9a0042f3a698e3dcac29f1dbdc1e9 (diff)
There was a corner case where linking the inp to the state key did
work in pf. The function pf_inp_link() takes the state key from the mbuf and not the one pf_find_state() has just found. Introduce a new function pf_state_key_link_inpcb() that links the given state key and inpcb together with some sanity checks. OK sashan@
Diffstat (limited to 'sys/net/pf.c')
-rw-r--r--sys/net/pf.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c
index 9edbe0f80e6..27a1f9e696b 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.1050 2017/12/04 15:13:12 bluhm Exp $ */
+/* $OpenBSD: pf.c,v 1.1051 2017/12/24 14:18:19 bluhm Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -249,6 +249,8 @@ void pf_state_key_link(struct pf_state_key *,
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, struct pf_state_key_cmp *key, u_int dir,
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 */
@@ -7262,6 +7265,15 @@ pf_pkt_state_key_ref(struct mbuf *m)
}
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
pf_inpcb_unlink_state_key(struct inpcb *inp)
{
if (inp != NULL) {