aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/netfilter/nf_tables_api.c59
-rw-r--r--net/netfilter/nfnetlink_acct.c1
-rw-r--r--net/netfilter/nft_rbtree.c22
3 files changed, 62 insertions, 20 deletions
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 047884776586..624e083125b9 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -538,8 +538,7 @@ static int nf_tables_deltable(struct sock *nlsk, struct sk_buff *skb,
538 return PTR_ERR(table); 538 return PTR_ERR(table);
539 if (table->flags & NFT_TABLE_INACTIVE) 539 if (table->flags & NFT_TABLE_INACTIVE)
540 return -ENOENT; 540 return -ENOENT;
541 541 if (table->use > 0)
542 if (!list_empty(&table->chains) || !list_empty(&table->sets))
543 return -EBUSY; 542 return -EBUSY;
544 543
545 nft_ctx_init(&ctx, skb, nlh, afi, table, NULL, nla); 544 nft_ctx_init(&ctx, skb, nlh, afi, table, NULL, nla);
@@ -553,6 +552,8 @@ static int nf_tables_deltable(struct sock *nlsk, struct sk_buff *skb,
553 552
554static void nf_tables_table_destroy(struct nft_ctx *ctx) 553static void nf_tables_table_destroy(struct nft_ctx *ctx)
555{ 554{
555 BUG_ON(ctx->table->use > 0);
556
556 kfree(ctx->table); 557 kfree(ctx->table);
557 module_put(ctx->afi->owner); 558 module_put(ctx->afi->owner);
558} 559}
@@ -1128,6 +1129,7 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
1128 if (err < 0) 1129 if (err < 0)
1129 goto err2; 1130 goto err2;
1130 1131
1132 table->use++;
1131 list_add_tail(&chain->list, &table->chains); 1133 list_add_tail(&chain->list, &table->chains);
1132 return 0; 1134 return 0;
1133err2: 1135err2:
@@ -1169,7 +1171,7 @@ static int nf_tables_delchain(struct sock *nlsk, struct sk_buff *skb,
1169 return PTR_ERR(chain); 1171 return PTR_ERR(chain);
1170 if (chain->flags & NFT_CHAIN_INACTIVE) 1172 if (chain->flags & NFT_CHAIN_INACTIVE)
1171 return -ENOENT; 1173 return -ENOENT;
1172 if (!list_empty(&chain->rules) || chain->use > 0) 1174 if (chain->use > 0)
1173 return -EBUSY; 1175 return -EBUSY;
1174 1176
1175 nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla); 1177 nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla);
@@ -1177,6 +1179,7 @@ static int nf_tables_delchain(struct sock *nlsk, struct sk_buff *skb,
1177 if (err < 0) 1179 if (err < 0)
1178 return err; 1180 return err;
1179 1181
1182 table->use--;
1180 list_del(&chain->list); 1183 list_del(&chain->list);
1181 return 0; 1184 return 0;
1182} 1185}
@@ -1814,6 +1817,7 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
1814 err = -ENOMEM; 1817 err = -ENOMEM;
1815 goto err3; 1818 goto err3;
1816 } 1819 }
1820 chain->use++;
1817 return 0; 1821 return 0;
1818 1822
1819err3: 1823err3:
@@ -1841,6 +1845,7 @@ nf_tables_delrule_one(struct nft_ctx *ctx, struct nft_rule *rule)
1841 if (nft_trans_rule_add(ctx, NFT_MSG_DELRULE, rule) == NULL) 1845 if (nft_trans_rule_add(ctx, NFT_MSG_DELRULE, rule) == NULL)
1842 return -ENOMEM; 1846 return -ENOMEM;
1843 nft_rule_disactivate_next(ctx->net, rule); 1847 nft_rule_disactivate_next(ctx->net, rule);
1848 ctx->chain->use--;
1844 return 0; 1849 return 0;
1845 } 1850 }
1846 return -ENOENT; 1851 return -ENOENT;
@@ -2186,7 +2191,7 @@ nla_put_failure:
2186 2191
2187static int nf_tables_set_notify(const struct nft_ctx *ctx, 2192static int nf_tables_set_notify(const struct nft_ctx *ctx,
2188 const struct nft_set *set, 2193 const struct nft_set *set,
2189 int event) 2194 int event, gfp_t gfp_flags)
2190{ 2195{
2191 struct sk_buff *skb; 2196 struct sk_buff *skb;
2192 u32 portid = ctx->portid; 2197 u32 portid = ctx->portid;
@@ -2197,7 +2202,7 @@ static int nf_tables_set_notify(const struct nft_ctx *ctx,
2197 return 0; 2202 return 0;
2198 2203
2199 err = -ENOBUFS; 2204 err = -ENOBUFS;
2200 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 2205 skb = nlmsg_new(NLMSG_GOODSIZE, gfp_flags);
2201 if (skb == NULL) 2206 if (skb == NULL)
2202 goto err; 2207 goto err;
2203 2208
@@ -2208,7 +2213,7 @@ static int nf_tables_set_notify(const struct nft_ctx *ctx,
2208 } 2213 }
2209 2214
2210 err = nfnetlink_send(skb, ctx->net, portid, NFNLGRP_NFTABLES, 2215 err = nfnetlink_send(skb, ctx->net, portid, NFNLGRP_NFTABLES,
2211 ctx->report, GFP_KERNEL); 2216 ctx->report, gfp_flags);
2212err: 2217err:
2213 if (err < 0) 2218 if (err < 0)
2214 nfnetlink_set_err(ctx->net, portid, NFNLGRP_NFTABLES, err); 2219 nfnetlink_set_err(ctx->net, portid, NFNLGRP_NFTABLES, err);
@@ -2588,6 +2593,7 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb,
2588 goto err2; 2593 goto err2;
2589 2594
2590 list_add_tail(&set->list, &table->sets); 2595 list_add_tail(&set->list, &table->sets);
2596 table->use++;
2591 return 0; 2597 return 0;
2592 2598
2593err2: 2599err2:
@@ -2607,7 +2613,7 @@ static void nft_set_destroy(struct nft_set *set)
2607static void nf_tables_set_destroy(const struct nft_ctx *ctx, struct nft_set *set) 2613static void nf_tables_set_destroy(const struct nft_ctx *ctx, struct nft_set *set)
2608{ 2614{
2609 list_del(&set->list); 2615 list_del(&set->list);
2610 nf_tables_set_notify(ctx, set, NFT_MSG_DELSET); 2616 nf_tables_set_notify(ctx, set, NFT_MSG_DELSET, GFP_ATOMIC);
2611 nft_set_destroy(set); 2617 nft_set_destroy(set);
2612} 2618}
2613 2619
@@ -2642,6 +2648,7 @@ static int nf_tables_delset(struct sock *nlsk, struct sk_buff *skb,
2642 return err; 2648 return err;
2643 2649
2644 list_del(&set->list); 2650 list_del(&set->list);
2651 ctx.table->use--;
2645 return 0; 2652 return 0;
2646} 2653}
2647 2654
@@ -3077,7 +3084,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
3077 goto err4; 3084 goto err4;
3078 3085
3079 nft_trans_elem(trans) = elem; 3086 nft_trans_elem(trans) = elem;
3080 list_add(&trans->list, &ctx->net->nft.commit_list); 3087 list_add_tail(&trans->list, &ctx->net->nft.commit_list);
3081 return 0; 3088 return 0;
3082 3089
3083err4: 3090err4:
@@ -3122,6 +3129,8 @@ static int nf_tables_newsetelem(struct sock *nlsk, struct sk_buff *skb,
3122 err = nft_add_set_elem(&ctx, set, attr); 3129 err = nft_add_set_elem(&ctx, set, attr);
3123 if (err < 0) 3130 if (err < 0)
3124 break; 3131 break;
3132
3133 set->nelems++;
3125 } 3134 }
3126 return err; 3135 return err;
3127} 3136}
@@ -3161,7 +3170,7 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set,
3161 goto err2; 3170 goto err2;
3162 3171
3163 nft_trans_elem(trans) = elem; 3172 nft_trans_elem(trans) = elem;
3164 list_add(&trans->list, &ctx->net->nft.commit_list); 3173 list_add_tail(&trans->list, &ctx->net->nft.commit_list);
3165 3174
3166 nft_data_uninit(&elem.key, NFT_DATA_VALUE); 3175 nft_data_uninit(&elem.key, NFT_DATA_VALUE);
3167 if (set->flags & NFT_SET_MAP) 3176 if (set->flags & NFT_SET_MAP)
@@ -3196,6 +3205,8 @@ static int nf_tables_delsetelem(struct sock *nlsk, struct sk_buff *skb,
3196 err = nft_del_setelem(&ctx, set, attr); 3205 err = nft_del_setelem(&ctx, set, attr);
3197 if (err < 0) 3206 if (err < 0)
3198 break; 3207 break;
3208
3209 set->nelems--;
3199 } 3210 }
3200 return err; 3211 return err;
3201} 3212}
@@ -3361,15 +3372,13 @@ static int nf_tables_commit(struct sk_buff *skb)
3361 case NFT_MSG_NEWCHAIN: 3372 case NFT_MSG_NEWCHAIN:
3362 if (nft_trans_chain_update(trans)) 3373 if (nft_trans_chain_update(trans))
3363 nft_chain_commit_update(trans); 3374 nft_chain_commit_update(trans);
3364 else { 3375 else
3365 trans->ctx.chain->flags &= ~NFT_CHAIN_INACTIVE; 3376 trans->ctx.chain->flags &= ~NFT_CHAIN_INACTIVE;
3366 trans->ctx.table->use++; 3377
3367 }
3368 nf_tables_chain_notify(&trans->ctx, NFT_MSG_NEWCHAIN); 3378 nf_tables_chain_notify(&trans->ctx, NFT_MSG_NEWCHAIN);
3369 nft_trans_destroy(trans); 3379 nft_trans_destroy(trans);
3370 break; 3380 break;
3371 case NFT_MSG_DELCHAIN: 3381 case NFT_MSG_DELCHAIN:
3372 trans->ctx.table->use--;
3373 nf_tables_chain_notify(&trans->ctx, NFT_MSG_DELCHAIN); 3382 nf_tables_chain_notify(&trans->ctx, NFT_MSG_DELCHAIN);
3374 if (!(trans->ctx.table->flags & NFT_TABLE_F_DORMANT) && 3383 if (!(trans->ctx.table->flags & NFT_TABLE_F_DORMANT) &&
3375 trans->ctx.chain->flags & NFT_BASE_CHAIN) { 3384 trans->ctx.chain->flags & NFT_BASE_CHAIN) {
@@ -3392,16 +3401,22 @@ static int nf_tables_commit(struct sk_buff *skb)
3392 break; 3401 break;
3393 case NFT_MSG_NEWSET: 3402 case NFT_MSG_NEWSET:
3394 nft_trans_set(trans)->flags &= ~NFT_SET_INACTIVE; 3403 nft_trans_set(trans)->flags &= ~NFT_SET_INACTIVE;
3404 /* This avoids hitting -EBUSY when deleting the table
3405 * from the transaction.
3406 */
3407 if (nft_trans_set(trans)->flags & NFT_SET_ANONYMOUS &&
3408 !list_empty(&nft_trans_set(trans)->bindings))
3409 trans->ctx.table->use--;
3410
3395 nf_tables_set_notify(&trans->ctx, nft_trans_set(trans), 3411 nf_tables_set_notify(&trans->ctx, nft_trans_set(trans),
3396 NFT_MSG_NEWSET); 3412 NFT_MSG_NEWSET, GFP_KERNEL);
3397 nft_trans_destroy(trans); 3413 nft_trans_destroy(trans);
3398 break; 3414 break;
3399 case NFT_MSG_DELSET: 3415 case NFT_MSG_DELSET:
3400 nf_tables_set_notify(&trans->ctx, nft_trans_set(trans), 3416 nf_tables_set_notify(&trans->ctx, nft_trans_set(trans),
3401 NFT_MSG_DELSET); 3417 NFT_MSG_DELSET, GFP_KERNEL);
3402 break; 3418 break;
3403 case NFT_MSG_NEWSETELEM: 3419 case NFT_MSG_NEWSETELEM:
3404 nft_trans_elem_set(trans)->nelems++;
3405 nf_tables_setelem_notify(&trans->ctx, 3420 nf_tables_setelem_notify(&trans->ctx,
3406 nft_trans_elem_set(trans), 3421 nft_trans_elem_set(trans),
3407 &nft_trans_elem(trans), 3422 &nft_trans_elem(trans),
@@ -3409,7 +3424,6 @@ static int nf_tables_commit(struct sk_buff *skb)
3409 nft_trans_destroy(trans); 3424 nft_trans_destroy(trans);
3410 break; 3425 break;
3411 case NFT_MSG_DELSETELEM: 3426 case NFT_MSG_DELSETELEM:
3412 nft_trans_elem_set(trans)->nelems--;
3413 nf_tables_setelem_notify(&trans->ctx, 3427 nf_tables_setelem_notify(&trans->ctx,
3414 nft_trans_elem_set(trans), 3428 nft_trans_elem_set(trans),
3415 &nft_trans_elem(trans), 3429 &nft_trans_elem(trans),
@@ -3487,6 +3501,7 @@ static int nf_tables_abort(struct sk_buff *skb)
3487 3501
3488 nft_trans_destroy(trans); 3502 nft_trans_destroy(trans);
3489 } else { 3503 } else {
3504 trans->ctx.table->use--;
3490 list_del(&trans->ctx.chain->list); 3505 list_del(&trans->ctx.chain->list);
3491 if (!(trans->ctx.table->flags & NFT_TABLE_F_DORMANT) && 3506 if (!(trans->ctx.table->flags & NFT_TABLE_F_DORMANT) &&
3492 trans->ctx.chain->flags & NFT_BASE_CHAIN) { 3507 trans->ctx.chain->flags & NFT_BASE_CHAIN) {
@@ -3496,38 +3511,46 @@ static int nf_tables_abort(struct sk_buff *skb)
3496 } 3511 }
3497 break; 3512 break;
3498 case NFT_MSG_DELCHAIN: 3513 case NFT_MSG_DELCHAIN:
3514 trans->ctx.table->use++;
3499 list_add_tail(&trans->ctx.chain->list, 3515 list_add_tail(&trans->ctx.chain->list,
3500 &trans->ctx.table->chains); 3516 &trans->ctx.table->chains);
3501 nft_trans_destroy(trans); 3517 nft_trans_destroy(trans);
3502 break; 3518 break;
3503 case NFT_MSG_NEWRULE: 3519 case NFT_MSG_NEWRULE:
3520 trans->ctx.chain->use--;
3504 list_del_rcu(&nft_trans_rule(trans)->list); 3521 list_del_rcu(&nft_trans_rule(trans)->list);
3505 break; 3522 break;
3506 case NFT_MSG_DELRULE: 3523 case NFT_MSG_DELRULE:
3524 trans->ctx.chain->use++;
3507 nft_rule_clear(trans->ctx.net, nft_trans_rule(trans)); 3525 nft_rule_clear(trans->ctx.net, nft_trans_rule(trans));
3508 nft_trans_destroy(trans); 3526 nft_trans_destroy(trans);
3509 break; 3527 break;
3510 case NFT_MSG_NEWSET: 3528 case NFT_MSG_NEWSET:
3529 trans->ctx.table->use--;
3511 list_del(&nft_trans_set(trans)->list); 3530 list_del(&nft_trans_set(trans)->list);
3512 break; 3531 break;
3513 case NFT_MSG_DELSET: 3532 case NFT_MSG_DELSET:
3533 trans->ctx.table->use++;
3514 list_add_tail(&nft_trans_set(trans)->list, 3534 list_add_tail(&nft_trans_set(trans)->list,
3515 &trans->ctx.table->sets); 3535 &trans->ctx.table->sets);
3516 nft_trans_destroy(trans); 3536 nft_trans_destroy(trans);
3517 break; 3537 break;
3518 case NFT_MSG_NEWSETELEM: 3538 case NFT_MSG_NEWSETELEM:
3539 nft_trans_elem_set(trans)->nelems--;
3519 set = nft_trans_elem_set(trans); 3540 set = nft_trans_elem_set(trans);
3520 set->ops->get(set, &nft_trans_elem(trans)); 3541 set->ops->get(set, &nft_trans_elem(trans));
3521 set->ops->remove(set, &nft_trans_elem(trans)); 3542 set->ops->remove(set, &nft_trans_elem(trans));
3522 nft_trans_destroy(trans); 3543 nft_trans_destroy(trans);
3523 break; 3544 break;
3524 case NFT_MSG_DELSETELEM: 3545 case NFT_MSG_DELSETELEM:
3546 nft_trans_elem_set(trans)->nelems++;
3525 nft_trans_destroy(trans); 3547 nft_trans_destroy(trans);
3526 break; 3548 break;
3527 } 3549 }
3528 } 3550 }
3529 3551
3530 list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) { 3552 list_for_each_entry_safe_reverse(trans, next,
3553 &net->nft.commit_list, list) {
3531 list_del(&trans->list); 3554 list_del(&trans->list);
3532 trans->ctx.nla = NULL; 3555 trans->ctx.nla = NULL;
3533 call_rcu(&trans->rcu_head, nf_tables_abort_release_rcu); 3556 call_rcu(&trans->rcu_head, nf_tables_abort_release_rcu);
diff --git a/net/netfilter/nfnetlink_acct.c b/net/netfilter/nfnetlink_acct.c
index 70e86bbb3637..54af9853e2cd 100644
--- a/net/netfilter/nfnetlink_acct.c
+++ b/net/netfilter/nfnetlink_acct.c
@@ -83,7 +83,6 @@ nfnl_acct_new(struct sock *nfnl, struct sk_buff *skb,
83 return -EBUSY; 83 return -EBUSY;
84 } 84 }
85 85
86 nfacct = kzalloc(sizeof(struct nf_acct), GFP_KERNEL);
87 if (tb[NFACCT_FLAGS]) { 86 if (tb[NFACCT_FLAGS]) {
88 flags = ntohl(nla_get_be32(tb[NFACCT_FLAGS])); 87 flags = ntohl(nla_get_be32(tb[NFACCT_FLAGS]));
89 if (flags & ~NFACCT_F_QUOTA) 88 if (flags & ~NFACCT_F_QUOTA)
diff --git a/net/netfilter/nft_rbtree.c b/net/netfilter/nft_rbtree.c
index 072e611e9f71..e1836ff88199 100644
--- a/net/netfilter/nft_rbtree.c
+++ b/net/netfilter/nft_rbtree.c
@@ -18,6 +18,8 @@
18#include <linux/netfilter/nf_tables.h> 18#include <linux/netfilter/nf_tables.h>
19#include <net/netfilter/nf_tables.h> 19#include <net/netfilter/nf_tables.h>
20 20
21static DEFINE_SPINLOCK(nft_rbtree_lock);
22
21struct nft_rbtree { 23struct nft_rbtree {
22 struct rb_root root; 24 struct rb_root root;
23}; 25};
@@ -38,6 +40,7 @@ static bool nft_rbtree_lookup(const struct nft_set *set,
38 const struct rb_node *parent = priv->root.rb_node; 40 const struct rb_node *parent = priv->root.rb_node;
39 int d; 41 int d;
40 42
43 spin_lock_bh(&nft_rbtree_lock);
41 while (parent != NULL) { 44 while (parent != NULL) {
42 rbe = rb_entry(parent, struct nft_rbtree_elem, node); 45 rbe = rb_entry(parent, struct nft_rbtree_elem, node);
43 46
@@ -53,6 +56,8 @@ found:
53 goto out; 56 goto out;
54 if (set->flags & NFT_SET_MAP) 57 if (set->flags & NFT_SET_MAP)
55 nft_data_copy(data, rbe->data); 58 nft_data_copy(data, rbe->data);
59
60 spin_unlock_bh(&nft_rbtree_lock);
56 return true; 61 return true;
57 } 62 }
58 } 63 }
@@ -62,6 +67,7 @@ found:
62 goto found; 67 goto found;
63 } 68 }
64out: 69out:
70 spin_unlock_bh(&nft_rbtree_lock);
65 return false; 71 return false;
66} 72}
67 73
@@ -124,9 +130,12 @@ static int nft_rbtree_insert(const struct nft_set *set,
124 !(rbe->flags & NFT_SET_ELEM_INTERVAL_END)) 130 !(rbe->flags & NFT_SET_ELEM_INTERVAL_END))
125 nft_data_copy(rbe->data, &elem->data); 131 nft_data_copy(rbe->data, &elem->data);
126 132
133 spin_lock_bh(&nft_rbtree_lock);
127 err = __nft_rbtree_insert(set, rbe); 134 err = __nft_rbtree_insert(set, rbe);
128 if (err < 0) 135 if (err < 0)
129 kfree(rbe); 136 kfree(rbe);
137
138 spin_unlock_bh(&nft_rbtree_lock);
130 return err; 139 return err;
131} 140}
132 141
@@ -136,7 +145,9 @@ static void nft_rbtree_remove(const struct nft_set *set,
136 struct nft_rbtree *priv = nft_set_priv(set); 145 struct nft_rbtree *priv = nft_set_priv(set);
137 struct nft_rbtree_elem *rbe = elem->cookie; 146 struct nft_rbtree_elem *rbe = elem->cookie;
138 147
148 spin_lock_bh(&nft_rbtree_lock);
139 rb_erase(&rbe->node, &priv->root); 149 rb_erase(&rbe->node, &priv->root);
150 spin_unlock_bh(&nft_rbtree_lock);
140 kfree(rbe); 151 kfree(rbe);
141} 152}
142 153
@@ -147,6 +158,7 @@ static int nft_rbtree_get(const struct nft_set *set, struct nft_set_elem *elem)
147 struct nft_rbtree_elem *rbe; 158 struct nft_rbtree_elem *rbe;
148 int d; 159 int d;
149 160
161 spin_lock_bh(&nft_rbtree_lock);
150 while (parent != NULL) { 162 while (parent != NULL) {
151 rbe = rb_entry(parent, struct nft_rbtree_elem, node); 163 rbe = rb_entry(parent, struct nft_rbtree_elem, node);
152 164
@@ -161,9 +173,11 @@ static int nft_rbtree_get(const struct nft_set *set, struct nft_set_elem *elem)
161 !(rbe->flags & NFT_SET_ELEM_INTERVAL_END)) 173 !(rbe->flags & NFT_SET_ELEM_INTERVAL_END))
162 nft_data_copy(&elem->data, rbe->data); 174 nft_data_copy(&elem->data, rbe->data);
163 elem->flags = rbe->flags; 175 elem->flags = rbe->flags;
176 spin_unlock_bh(&nft_rbtree_lock);
164 return 0; 177 return 0;
165 } 178 }
166 } 179 }
180 spin_unlock_bh(&nft_rbtree_lock);
167 return -ENOENT; 181 return -ENOENT;
168} 182}
169 183
@@ -176,6 +190,7 @@ static void nft_rbtree_walk(const struct nft_ctx *ctx,
176 struct nft_set_elem elem; 190 struct nft_set_elem elem;
177 struct rb_node *node; 191 struct rb_node *node;
178 192
193 spin_lock_bh(&nft_rbtree_lock);
179 for (node = rb_first(&priv->root); node != NULL; node = rb_next(node)) { 194 for (node = rb_first(&priv->root); node != NULL; node = rb_next(node)) {
180 if (iter->count < iter->skip) 195 if (iter->count < iter->skip)
181 goto cont; 196 goto cont;
@@ -188,11 +203,14 @@ static void nft_rbtree_walk(const struct nft_ctx *ctx,
188 elem.flags = rbe->flags; 203 elem.flags = rbe->flags;
189 204
190 iter->err = iter->fn(ctx, set, iter, &elem); 205 iter->err = iter->fn(ctx, set, iter, &elem);
191 if (iter->err < 0) 206 if (iter->err < 0) {
207 spin_unlock_bh(&nft_rbtree_lock);
192 return; 208 return;
209 }
193cont: 210cont:
194 iter->count++; 211 iter->count++;
195 } 212 }
213 spin_unlock_bh(&nft_rbtree_lock);
196} 214}
197 215
198static unsigned int nft_rbtree_privsize(const struct nlattr * const nla[]) 216static unsigned int nft_rbtree_privsize(const struct nlattr * const nla[])
@@ -216,11 +234,13 @@ static void nft_rbtree_destroy(const struct nft_set *set)
216 struct nft_rbtree_elem *rbe; 234 struct nft_rbtree_elem *rbe;
217 struct rb_node *node; 235 struct rb_node *node;
218 236
237 spin_lock_bh(&nft_rbtree_lock);
219 while ((node = priv->root.rb_node) != NULL) { 238 while ((node = priv->root.rb_node) != NULL) {
220 rb_erase(node, &priv->root); 239 rb_erase(node, &priv->root);
221 rbe = rb_entry(node, struct nft_rbtree_elem, node); 240 rbe = rb_entry(node, struct nft_rbtree_elem, node);
222 nft_rbtree_elem_destroy(set, rbe); 241 nft_rbtree_elem_destroy(set, rbe);
223 } 242 }
243 spin_unlock_bh(&nft_rbtree_lock);
224} 244}
225 245
226static bool nft_rbtree_estimate(const struct nft_set_desc *desc, u32 features, 246static bool nft_rbtree_estimate(const struct nft_set_desc *desc, u32 features,