diff options
-rw-r--r-- | include/net/netns/nftables.h | 2 | ||||
-rw-r--r-- | net/netfilter/nf_tables_api.c | 30 |
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)); | ||
298 | cont: | 302 | cont: |
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)); | ||
787 | cont: | 795 | cont: |
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)); | ||
1582 | cont: | 1592 | cont: |
1583 | idx++; | 1593 | idx++; |
1584 | } | 1594 | } |
@@ -1588,10 +1598,6 @@ cont: | |||
1588 | done: | 1598 | done: |
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)); | ||
2255 | cont: | 2264 | cont: |
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)); | ||
2293 | cont: | 2305 | cont: |
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)); | ||
2347 | cont: | 2362 | cont: |
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 | ||