aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/netns/nftables.h2
-rw-r--r--net/netfilter/nf_tables_api.c30
2 files changed, 24 insertions, 8 deletions
diff --git a/include/net/netns/nftables.h b/include/net/netns/nftables.h
index 26a394cb91a8..eee608b12cc9 100644
--- a/include/net/netns/nftables.h
+++ b/include/net/netns/nftables.h
@@ -13,8 +13,8 @@ struct netns_nftables {
13 struct nft_af_info *inet; 13 struct nft_af_info *inet;
14 struct nft_af_info *arp; 14 struct nft_af_info *arp;
15 struct nft_af_info *bridge; 15 struct nft_af_info *bridge;
16 unsigned int base_seq;
16 u8 gencursor; 17 u8 gencursor;
17 u8 genctr;
18}; 18};
19 19
20#endif 20#endif
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index a27a7c56e7c3..ac03d748360e 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -278,6 +278,8 @@ static int nf_tables_dump_tables(struct sk_buff *skb,
278 int family = nfmsg->nfgen_family; 278 int family = nfmsg->nfgen_family;
279 279
280 rcu_read_lock(); 280 rcu_read_lock();
281 cb->seq = net->nft.base_seq;
282
281 list_for_each_entry_rcu(afi, &net->nft.af_info, list) { 283 list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
282 if (family != NFPROTO_UNSPEC && family != afi->family) 284 if (family != NFPROTO_UNSPEC && family != afi->family)
283 continue; 285 continue;
@@ -295,6 +297,8 @@ static int nf_tables_dump_tables(struct sk_buff *skb,
295 NLM_F_MULTI, 297 NLM_F_MULTI,
296 afi->family, table) < 0) 298 afi->family, table) < 0)
297 goto done; 299 goto done;
300
301 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
298cont: 302cont:
299 idx++; 303 idx++;
300 } 304 }
@@ -767,6 +771,8 @@ static int nf_tables_dump_chains(struct sk_buff *skb,
767 int family = nfmsg->nfgen_family; 771 int family = nfmsg->nfgen_family;
768 772
769 rcu_read_lock(); 773 rcu_read_lock();
774 cb->seq = net->nft.base_seq;
775
770 list_for_each_entry_rcu(afi, &net->nft.af_info, list) { 776 list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
771 if (family != NFPROTO_UNSPEC && family != afi->family) 777 if (family != NFPROTO_UNSPEC && family != afi->family)
772 continue; 778 continue;
@@ -784,6 +790,8 @@ static int nf_tables_dump_chains(struct sk_buff *skb,
784 NLM_F_MULTI, 790 NLM_F_MULTI,
785 afi->family, table, chain) < 0) 791 afi->family, table, chain) < 0)
786 goto done; 792 goto done;
793
794 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
787cont: 795cont:
788 idx++; 796 idx++;
789 } 797 }
@@ -1555,10 +1563,10 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
1555 unsigned int idx = 0, s_idx = cb->args[0]; 1563 unsigned int idx = 0, s_idx = cb->args[0];
1556 struct net *net = sock_net(skb->sk); 1564 struct net *net = sock_net(skb->sk);
1557 int family = nfmsg->nfgen_family; 1565 int family = nfmsg->nfgen_family;
1558 u8 genctr = ACCESS_ONCE(net->nft.genctr);
1559 u8 gencursor = ACCESS_ONCE(net->nft.gencursor);
1560 1566
1561 rcu_read_lock(); 1567 rcu_read_lock();
1568 cb->seq = net->nft.base_seq;
1569
1562 list_for_each_entry_rcu(afi, &net->nft.af_info, list) { 1570 list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
1563 if (family != NFPROTO_UNSPEC && family != afi->family) 1571 if (family != NFPROTO_UNSPEC && family != afi->family)
1564 continue; 1572 continue;
@@ -1579,6 +1587,8 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
1579 NLM_F_MULTI | NLM_F_APPEND, 1587 NLM_F_MULTI | NLM_F_APPEND,
1580 afi->family, table, chain, rule) < 0) 1588 afi->family, table, chain, rule) < 0)
1581 goto done; 1589 goto done;
1590
1591 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
1582cont: 1592cont:
1583 idx++; 1593 idx++;
1584 } 1594 }
@@ -1588,10 +1598,6 @@ cont:
1588done: 1598done:
1589 rcu_read_unlock(); 1599 rcu_read_unlock();
1590 1600
1591 /* Invalidate this dump, a transition to the new generation happened */
1592 if (gencursor != net->nft.gencursor || genctr != net->nft.genctr)
1593 return -EBUSY;
1594
1595 cb->args[0] = idx; 1601 cb->args[0] = idx;
1596 return skb->len; 1602 return skb->len;
1597} 1603}
@@ -2244,6 +2250,8 @@ static int nf_tables_dump_sets_table(struct nft_ctx *ctx, struct sk_buff *skb,
2244 return skb->len; 2250 return skb->len;
2245 2251
2246 rcu_read_lock(); 2252 rcu_read_lock();
2253 cb->seq = ctx->net->nft.base_seq;
2254
2247 list_for_each_entry_rcu(set, &ctx->table->sets, list) { 2255 list_for_each_entry_rcu(set, &ctx->table->sets, list) {
2248 if (idx < s_idx) 2256 if (idx < s_idx)
2249 goto cont; 2257 goto cont;
@@ -2252,6 +2260,7 @@ static int nf_tables_dump_sets_table(struct nft_ctx *ctx, struct sk_buff *skb,
2252 cb->args[0] = idx; 2260 cb->args[0] = idx;
2253 goto done; 2261 goto done;
2254 } 2262 }
2263 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
2255cont: 2264cont:
2256 idx++; 2265 idx++;
2257 } 2266 }
@@ -2272,6 +2281,8 @@ static int nf_tables_dump_sets_family(struct nft_ctx *ctx, struct sk_buff *skb,
2272 return skb->len; 2281 return skb->len;
2273 2282
2274 rcu_read_lock(); 2283 rcu_read_lock();
2284 cb->seq = ctx->net->nft.base_seq;
2285
2275 list_for_each_entry_rcu(table, &ctx->afi->tables, list) { 2286 list_for_each_entry_rcu(table, &ctx->afi->tables, list) {
2276 if (cur_table) { 2287 if (cur_table) {
2277 if (cur_table != table) 2288 if (cur_table != table)
@@ -2290,6 +2301,7 @@ static int nf_tables_dump_sets_family(struct nft_ctx *ctx, struct sk_buff *skb,
2290 cb->args[2] = (unsigned long) table; 2301 cb->args[2] = (unsigned long) table;
2291 goto done; 2302 goto done;
2292 } 2303 }
2304 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
2293cont: 2305cont:
2294 idx++; 2306 idx++;
2295 } 2307 }
@@ -2314,6 +2326,8 @@ static int nf_tables_dump_sets_all(struct nft_ctx *ctx, struct sk_buff *skb,
2314 return skb->len; 2326 return skb->len;
2315 2327
2316 rcu_read_lock(); 2328 rcu_read_lock();
2329 cb->seq = net->nft.base_seq;
2330
2317 list_for_each_entry_rcu(afi, &net->nft.af_info, list) { 2331 list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
2318 if (cur_family) { 2332 if (cur_family) {
2319 if (afi->family != cur_family) 2333 if (afi->family != cur_family)
@@ -2344,6 +2358,7 @@ static int nf_tables_dump_sets_all(struct nft_ctx *ctx, struct sk_buff *skb,
2344 cb->args[3] = afi->family; 2358 cb->args[3] = afi->family;
2345 goto done; 2359 goto done;
2346 } 2360 }
2361 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
2347cont: 2362cont:
2348 idx++; 2363 idx++;
2349 } 2364 }
@@ -3361,7 +3376,7 @@ static int nf_tables_commit(struct sk_buff *skb)
3361 struct nft_set *set; 3376 struct nft_set *set;
3362 3377
3363 /* Bump generation counter, invalidate any dump in progress */ 3378 /* Bump generation counter, invalidate any dump in progress */
3364 net->nft.genctr++; 3379 while (++net->nft.base_seq == 0);
3365 3380
3366 /* A new generation has just started */ 3381 /* A new generation has just started */
3367 net->nft.gencursor = gencursor_next(net); 3382 net->nft.gencursor = gencursor_next(net);
@@ -3966,6 +3981,7 @@ static int nf_tables_init_net(struct net *net)
3966{ 3981{
3967 INIT_LIST_HEAD(&net->nft.af_info); 3982 INIT_LIST_HEAD(&net->nft.af_info);
3968 INIT_LIST_HEAD(&net->nft.commit_list); 3983 INIT_LIST_HEAD(&net->nft.commit_list);
3984 net->nft.base_seq = 1;
3969 return 0; 3985 return 0;
3970} 3986}
3971 3987