summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2019-05-20 11:16:21 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2019-05-20 14:16:53 +0200
commitab1cd3b510fa5d5642b8698c5bd5c125b53ff7c7 (patch)
tree22cf314916f6de076e4a76d10dc87105dd951a4a
parente3a1682b68848d4012ef99dab0ff41e7cdaf49fb (diff)
nft: ensure cache consistency
Check for generation ID before and after fetching the cache to ensure consistency. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--iptables/nft.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/iptables/nft.c b/iptables/nft.c
index 063637e2..172beec9 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -63,7 +63,7 @@ static void *nft_fn;
static int genid_cb(const struct nlmsghdr *nlh, void *data)
{
- struct nft_handle *h = data;
+ uint32_t *genid = data;
struct nftnl_gen *gen;
gen = nftnl_gen_alloc();
@@ -73,7 +73,7 @@ static int genid_cb(const struct nlmsghdr *nlh, void *data)
if (nftnl_gen_nlmsg_parse(nlh, gen) < 0)
goto out;
- h->nft_genid = nftnl_gen_get_u32(gen, NFTNL_GEN_ID);
+ *genid = nftnl_gen_get_u32(gen, NFTNL_GEN_ID);
nftnl_gen_free(gen);
return MNL_CB_STOP;
@@ -82,13 +82,13 @@ out:
return MNL_CB_ERROR;
}
-static int mnl_genid_get(struct nft_handle *h)
+static int mnl_genid_get(struct nft_handle *h, uint32_t *genid)
{
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nlmsghdr *nlh;
nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETGEN, 0, 0, h->seq);
- return mnl_talk(h, nlh, genid_cb, h);
+ return mnl_talk(h, nlh, genid_cb, genid);
}
int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh,
@@ -1595,12 +1595,22 @@ static int fetch_rule_cache(struct nft_handle *h)
static void __nft_build_cache(struct nft_handle *h)
{
- mnl_genid_get(h);
+ uint32_t genid_start, genid_stop;
+
+retry:
+ mnl_genid_get(h, &genid_start);
fetch_chain_cache(h);
fetch_rule_cache(h);
h->have_cache = true;
-}
+ mnl_genid_get(h, &genid_stop);
+ if (genid_start != genid_stop) {
+ flush_chain_cache(h, NULL);
+ goto retry;
+ }
+
+ h->nft_genid = genid_start;
+}
void nft_build_cache(struct nft_handle *h)
{