summaryrefslogtreecommitdiffstats
path: root/iptables/nft-bridge.c
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2018-08-06 17:21:56 +0200
committerFlorian Westphal <fw@strlen.de>2018-08-06 18:17:39 +0200
commitaa7fb04fcf72cf50ba6c490ae1cae30181672004 (patch)
tree7373b8430df10fe429ec6cbc30adcfcaa6d8eb14 /iptables/nft-bridge.c
parent3f123dcf556487e753b43d7e43ff7016013349dc (diff)
ebtables: Review match/target lookup
Since ebtables does not indicate extension use on commandline via '-m' flag as in iptables, loading of matches has to happen prior to commandline parsing. While parsing, the right extension is searched for unknown parameters by passing it to its 'parse' callback and checking if it succeeds. As an unavoidable side-effect, custom data in xtables_targets objects is being altered if the extension parser succeeds. If called multiple times, do_commandeb() leaks memory and fixing this requires to properly treat the above quirk: * Load extensions just once at program startup, thereby reusing the existing ones for several calls of do_commandeb(). * In ebt_cs_clean(), don't free memory which is being reused. Instead reinit custom extension data if it was used in current do_commandeb() call (i.e., it is contained in cs->match_list). On the other hand, target lookup in command_jump() can be simplified a lot: The only target it may have loaded is 'standard', so just load that at as well at program startup and reduce command_jump() to a simple linked list search. Since 'standard' target does not prove a 'parse' callback, a check is necessary when parsing target options. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Florian Westphal <fw@strlen.de>
Diffstat (limited to 'iptables/nft-bridge.c')
-rw-r--r--iptables/nft-bridge.c35
1 files changed, 32 insertions, 3 deletions
diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c
index c8605dc9..386da869 100644
--- a/iptables/nft-bridge.c
+++ b/iptables/nft-bridge.c
@@ -25,16 +25,45 @@
void ebt_cs_clean(struct iptables_command_state *cs)
{
struct ebt_match *m, *nm;
+ struct xtables_rule_match *matchp, *tmp;
- xtables_rule_matches_free(&cs->matches);
+ for (matchp = cs->matches; matchp;) {
+ tmp = matchp->next;
+
+ if (matchp->match == matchp->match->next) {
+ free(matchp->match);
+ matchp->match = NULL;
+ }
+ free(matchp);
+ matchp = tmp;
+ }
for (m = cs->match_list; m;) {
+ if (m->ismatch) {
+ struct xtables_match *match = m->u.match;
+
+ memset(match->m->data, 0,
+ match->m->u.match_size - sizeof(*match->m));
+ if (match->init)
+ match->init(match->m);
+ } else {
+ struct xtables_target *target = m->u.watcher;
+
+ memset(target->t->data, 0,
+ target->t->u.target_size - sizeof(*target->t));
+ if (target->init)
+ target->init(target->t);
+ }
+
nm = m->next;
- if (!m->ismatch)
- free(m->u.watcher->t);
free(m);
m = nm;
}
+
+ if (cs->target) {
+ if (cs->target->udata_size)
+ free(cs->target->udata);
+ }
}
/* 0: default, print only 2 digits if necessary