diff options
-rw-r--r-- | net/netfilter/nf_tables_api.c | 59 | ||||
-rw-r--r-- | net/netfilter/nfnetlink_acct.c | 1 | ||||
-rw-r--r-- | net/netfilter/nft_rbtree.c | 22 |
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 | ||
554 | static void nf_tables_table_destroy(struct nft_ctx *ctx) | 553 | static 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; |
1133 | err2: | 1135 | err2: |
@@ -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 | ||
1819 | err3: | 1823 | err3: |
@@ -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 | ||
2187 | static int nf_tables_set_notify(const struct nft_ctx *ctx, | 2192 | static 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); |
2212 | err: | 2217 | err: |
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 | ||
2593 | err2: | 2599 | err2: |
@@ -2607,7 +2613,7 @@ static void nft_set_destroy(struct nft_set *set) | |||
2607 | static void nf_tables_set_destroy(const struct nft_ctx *ctx, struct nft_set *set) | 2613 | static 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 | ||
3083 | err4: | 3090 | err4: |
@@ -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 | ||
21 | static DEFINE_SPINLOCK(nft_rbtree_lock); | ||
22 | |||
21 | struct nft_rbtree { | 23 | struct 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 | } |
64 | out: | 69 | out: |
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 | } | ||
193 | cont: | 210 | cont: |
194 | iter->count++; | 211 | iter->count++; |
195 | } | 212 | } |
213 | spin_unlock_bh(&nft_rbtree_lock); | ||
196 | } | 214 | } |
197 | 215 | ||
198 | static unsigned int nft_rbtree_privsize(const struct nlattr * const nla[]) | 216 | static 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 | ||
226 | static bool nft_rbtree_estimate(const struct nft_set_desc *desc, u32 features, | 246 | static bool nft_rbtree_estimate(const struct nft_set_desc *desc, u32 features, |