[iptables PATCH 06/15] nft: cache: Re-establish cache consistency check

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxx>
---
 iptables/nft-cache.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/iptables/nft-cache.c b/iptables/nft-cache.c
index 84ea97d3e54a6..638b18bc7e382 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)
-- 
2.25.1




[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux