summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorHenning Brauer <henning@cvs.openbsd.org>2003-06-27 11:38:24 +0000
committerHenning Brauer <henning@cvs.openbsd.org>2003-06-27 11:38:24 +0000
commitd57bb7fcd9ad7d4f94fa3bba704919a0afa39d0a (patch)
treeb85c86cd94824279e9231c870ef72256ab2ed5a2 /sys
parent6ff8faee335b10c8bf0e06d7da93e9e421eb29bc (diff)
move down pf_tag_unref() calls in pf_rm_rule() to after the check wetehr there
are still states for the given rule existant. based on a very nice analysis from cedric@, that is so completely right that I have nothing to add: in pf_rm_rule(), the pf_tag_unref() calls are done *before* the if (rule->states > 0 || rule->entries.tqe_prev != NULL) test. That mean that the two pf_tag_unref() calls could occur *twice* for a given rule: first when the rule is removed from the ruleset and (if the rule was kept around because of a state) a second time when the state refcount drops to zero and the rule gets really deleted. Unless I'm mistaken, that breaks the refcounting. ...and cedric was not mistaken. and, as daniel pointed out: The breakage this causes is so subtle, I doubt anyone noticed it before, if it did occur. consensus on this between cedric, dhartmei and myself
Diffstat (limited to 'sys')
-rw-r--r--sys/net/pf_ioctl.c6
1 files changed, 3 insertions, 3 deletions
diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c
index 6198ece0529..4355a7e9a46 100644
--- a/sys/net/pf_ioctl.c
+++ b/sys/net/pf_ioctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_ioctl.c,v 1.70 2003/06/23 02:33:39 cedric Exp $ */
+/* $OpenBSD: pf_ioctl.c,v 1.71 2003/06/27 11:38:23 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -407,10 +407,10 @@ pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule)
rule->entries.tqe_prev = NULL;
rule->nr = -1;
}
- pf_tag_unref(rule->tag);
- pf_tag_unref(rule->match_tag);
if (rule->states > 0 || rule->entries.tqe_prev != NULL)
return;
+ pf_tag_unref(rule->tag);
+ pf_tag_unref(rule->match_tag);
pf_dynaddr_remove(&rule->src.addr);
pf_dynaddr_remove(&rule->dst.addr);
if (rulequeue == NULL) {