summaryrefslogtreecommitdiffstats
path: root/iptables/nft-cache.c
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2020-05-01 07:59:36 +0200
committerPhil Sutter <phil@nwl.cc>2020-05-11 14:28:29 +0200
commitf42bfb344af82d10615420a96d088f11a0f78065 (patch)
tree65da8f72536451419e44d084ec26dbc517213380 /iptables/nft-cache.c
parent7b3558f16035eb13bdbb481bea1e4672f3679236 (diff)
nft: cache: Re-establish cache consistency check
Restore code ensuring __nft_build_cache() returns a consistent cache in which all ruleset elements belong to the same generation. This check was removed by commit 200bc39965149 ("nft: cache: Fix iptables-save segfault under stress") as it could lead to segfaults if a partial cache fetch was done while cache's chain list was traversed. With the new cache fetch logic, __nft_build_cache() is never called while holding references to cache entries. Signed-off-by: Phil Sutter <phil@nwl.cc>
Diffstat (limited to 'iptables/nft-cache.c')
-rw-r--r--iptables/nft-cache.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/iptables/nft-cache.c b/iptables/nft-cache.c
index 84ea97d3..638b18bc 100644
--- a/iptables/nft-cache.c
+++ b/iptables/nft-cache.c
@@ -484,12 +484,16 @@ static int fetch_rule_cache(struct nft_handle *h,
return 0;
}
+static int flush_cache(struct nft_handle *h, struct nft_cache *c,
+ const char *tablename);
+
static void
__nft_build_cache(struct nft_handle *h)
{
struct nft_cache_req *req = &h->cache_req;
const struct builtin_table *t = NULL;
struct list_head *chains = NULL;
+ uint32_t genid_check;
if (h->cache_init)
return;
@@ -501,6 +505,7 @@ __nft_build_cache(struct nft_handle *h)
}
h->cache_init = true;
+retry:
mnl_genid_get(h, &h->nft_genid);
if (req->level >= NFT_CL_TABLES)
@@ -513,6 +518,12 @@ __nft_build_cache(struct nft_handle *h)
fetch_set_cache(h, t, NULL);
if (req->level >= NFT_CL_RULES)
fetch_rule_cache(h, t);
+
+ mnl_genid_get(h, &genid_check);
+ if (h->nft_genid != genid_check) {
+ flush_cache(h, h->cache, NULL);
+ goto retry;
+ }
}
static void __nft_flush_cache(struct nft_handle *h)