summaryrefslogtreecommitdiff
path: root/sys/net/pf.c
diff options
context:
space:
mode:
authorMike Belopuhov <mikeb@cvs.openbsd.org>2013-05-10 11:36:25 +0000
committerMike Belopuhov <mikeb@cvs.openbsd.org>2013-05-10 11:36:25 +0000
commit107af1f28831acb7f690ef701f32804449f24dbc (patch)
tree5b810bac06b931c0b3f24d8ac21fa3cfac199be1 /sys/net/pf.c
parent4fc4909f5039ce3c9ee294c8017fe0f2c4be0199 (diff)
Since pf_state_key_attach can decide to free the provided state
key we need to sync our state key pointers with whatever values the function will pick. Not doing so will produce wrong results if address translation must be applied afterwards and we happen to have a state key collision. Then pf_translate will follow an old pointer and punch in garbage addresses into the packet. Noticed, initial patch and tests by Vitaly Sinilin <vs @ kp4 ! ru> ok tedu, henning
Diffstat (limited to 'sys/net/pf.c')
-rw-r--r--sys/net/pf.c19
1 files changed, 11 insertions, 8 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c
index c71cfc00635..0c847f6170c 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.823 2013/05/03 15:33:47 florian Exp $ */
+/* $OpenBSD: pf.c,v 1.824 2013/05/10 11:36:24 mikeb Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -916,25 +916,28 @@ pf_state_key_setup(struct pf_pdesc *pd, struct pf_state_key **skw,
}
int
-pf_state_insert(struct pfi_kif *kif, struct pf_state_key *skw,
- struct pf_state_key *sks, struct pf_state *s)
+pf_state_insert(struct pfi_kif *kif, struct pf_state_key **skw,
+ struct pf_state_key **sks, struct pf_state *s)
{
splsoftassert(IPL_SOFTNET);
s->kif = kif;
- if (skw == sks) {
- if (pf_state_key_attach(skw, s, PF_SK_WIRE))
+ if (*skw == *sks) {
+ if (pf_state_key_attach(*skw, s, PF_SK_WIRE))
return (-1);
+ *skw = *sks = s->key[PF_SK_WIRE];
s->key[PF_SK_STACK] = s->key[PF_SK_WIRE];
} else {
- if (pf_state_key_attach(skw, s, PF_SK_WIRE)) {
+ if (pf_state_key_attach(*skw, s, PF_SK_WIRE)) {
pool_put(&pf_state_key_pl, sks);
return (-1);
}
- if (pf_state_key_attach(sks, s, PF_SK_STACK)) {
+ *skw = s->key[PF_SK_WIRE];
+ if (pf_state_key_attach(*sks, s, PF_SK_STACK)) {
pf_state_key_detach(s, PF_SK_WIRE);
return (-1);
}
+ *sks = s->key[PF_SK_STACK];
}
if (s->id == 0 && s->creatorid == 0) {
@@ -3789,7 +3792,7 @@ pf_create_state(struct pf_pdesc *pd, struct pf_rule *r, struct pf_rule *a,
goto csfailed;
}
- if (pf_state_insert(BOUND_IFACE(r, pd->kif), *skw, *sks, s)) {
+ if (pf_state_insert(BOUND_IFACE(r, pd->kif), skw, sks, s)) {
pf_state_key_detach(s, PF_SK_STACK);
pf_state_key_detach(s, PF_SK_WIRE);
*sks = *skw = NULL;