diff options
author | Phil Sutter <phil@nwl.cc> | 2020-04-24 11:32:08 +0200 |
---|---|---|
committer | Phil Sutter <phil@nwl.cc> | 2020-05-11 14:28:29 +0200 |
commit | 5bd3ab5c778033877d44a0c619ef6f98f34516af (patch) | |
tree | 3a1d034b0318eca53ea57917999c935c4575a593 /iptables/nft.c | |
parent | ea8bb5100a69d1fd39cf737e3bf3acd6631a10f3 (diff) |
nft: Fix for '-F' in iptables dumps
When restoring a dump which contains an explicit flush command,
previously added rules are removed from cache and the following commit
will try to create netlink messages based on freed memory.
Fix this by weeding any rule-based commands from obj_list if they
address the same chain.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Diffstat (limited to 'iptables/nft.c')
-rw-r--r-- | iptables/nft.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/iptables/nft.c b/iptables/nft.c index b505d70a..6503259e 100644 --- a/iptables/nft.c +++ b/iptables/nft.c @@ -402,6 +402,38 @@ batch_rule_add(struct nft_handle *h, enum obj_update_type type, return batch_add(h, type, r); } +static void batch_obj_del(struct nft_handle *h, struct obj_update *o); + +static void batch_chain_flush(struct nft_handle *h, + const char *table, const char *chain) +{ + struct obj_update *obj, *tmp; + + list_for_each_entry_safe(obj, tmp, &h->obj_list, head) { + struct nftnl_rule *r = obj->ptr; + + switch (obj->type) { + case NFT_COMPAT_RULE_APPEND: + case NFT_COMPAT_RULE_INSERT: + case NFT_COMPAT_RULE_REPLACE: + case NFT_COMPAT_RULE_DELETE: + break; + default: + continue; + } + + if (table && + strcmp(table, nftnl_rule_get_str(r, NFTNL_RULE_TABLE))) + continue; + + if (chain && + strcmp(chain, nftnl_rule_get_str(r, NFTNL_RULE_CHAIN))) + continue; + + batch_obj_del(h, obj); + } +} + const struct builtin_table xtables_ipv4[NFT_TABLE_MAX] = { [NFT_TABLE_RAW] = { .name = "raw", @@ -1681,6 +1713,7 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table, } if (chain || !verbose) { + batch_chain_flush(h, table, chain); __nft_rule_flush(h, table, chain, verbose, false); flush_rule_cache(h, table, c); return 1; @@ -1696,6 +1729,7 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table, while (c != NULL) { chain = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); + batch_chain_flush(h, table, chain); __nft_rule_flush(h, table, chain, verbose, false); flush_rule_cache(h, table, c); c = nftnl_chain_list_iter_next(iter); |