diff options
author | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2013-05-10 11:36:25 +0000 |
---|---|---|
committer | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2013-05-10 11:36:25 +0000 |
commit | 107af1f28831acb7f690ef701f32804449f24dbc (patch) | |
tree | 5b810bac06b931c0b3f24d8ac21fa3cfac199be1 /sys/net/pf.c | |
parent | 4fc4909f5039ce3c9ee294c8017fe0f2c4be0199 (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.c | 19 |
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; |