aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/netfilter/nf_tables_api.c40
1 files changed, 31 insertions, 9 deletions
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 4fffa3680d42..dbf823634669 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;
@@ -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:
@@ -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
@@ -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}
@@ -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,6 +3401,13 @@ 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);
3397 nft_trans_destroy(trans); 3413 nft_trans_destroy(trans);
@@ -3401,7 +3417,6 @@ static int nf_tables_commit(struct sk_buff *skb)
3401 NFT_MSG_DELSET); 3417 NFT_MSG_DELSET);
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,32 +3511,39 @@ 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 }