|
|
|
|
@@ -253,8 +253,10 @@ int nf_tables_bind_chain(const struct nft_ctx *ctx, struct nft_chain *chain)
|
|
|
|
|
if (chain->bound)
|
|
|
|
|
return -EBUSY;
|
|
|
|
|
|
|
|
|
|
if (!nft_use_inc(&chain->use))
|
|
|
|
|
return -EMFILE;
|
|
|
|
|
|
|
|
|
|
chain->bound = true;
|
|
|
|
|
chain->use++;
|
|
|
|
|
nft_chain_trans_bind(ctx, chain);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
@@ -437,7 +439,7 @@ static int nft_delchain(struct nft_ctx *ctx)
|
|
|
|
|
if (IS_ERR(trans))
|
|
|
|
|
return PTR_ERR(trans);
|
|
|
|
|
|
|
|
|
|
ctx->table->use--;
|
|
|
|
|
nft_use_dec(&ctx->table->use);
|
|
|
|
|
nft_deactivate_next(ctx->net, ctx->chain);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
@@ -476,7 +478,7 @@ nf_tables_delrule_deactivate(struct nft_ctx *ctx, struct nft_rule *rule)
|
|
|
|
|
/* You cannot delete the same rule twice */
|
|
|
|
|
if (nft_is_active_next(ctx->net, rule)) {
|
|
|
|
|
nft_deactivate_next(ctx->net, rule);
|
|
|
|
|
ctx->chain->use--;
|
|
|
|
|
nft_use_dec(&ctx->chain->use);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return -ENOENT;
|
|
|
|
|
@@ -644,7 +646,7 @@ static int nft_delset(const struct nft_ctx *ctx, struct nft_set *set)
|
|
|
|
|
nft_map_deactivate(ctx, set);
|
|
|
|
|
|
|
|
|
|
nft_deactivate_next(ctx->net, set);
|
|
|
|
|
ctx->table->use--;
|
|
|
|
|
nft_use_dec(&ctx->table->use);
|
|
|
|
|
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
@@ -676,7 +678,7 @@ static int nft_delobj(struct nft_ctx *ctx, struct nft_object *obj)
|
|
|
|
|
return err;
|
|
|
|
|
|
|
|
|
|
nft_deactivate_next(ctx->net, obj);
|
|
|
|
|
ctx->table->use--;
|
|
|
|
|
nft_use_dec(&ctx->table->use);
|
|
|
|
|
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
@@ -711,7 +713,7 @@ static int nft_delflowtable(struct nft_ctx *ctx,
|
|
|
|
|
return err;
|
|
|
|
|
|
|
|
|
|
nft_deactivate_next(ctx->net, flowtable);
|
|
|
|
|
ctx->table->use--;
|
|
|
|
|
nft_use_dec(&ctx->table->use);
|
|
|
|
|
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
@@ -2396,9 +2398,6 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
|
|
|
|
|
struct nft_chain *chain;
|
|
|
|
|
int err;
|
|
|
|
|
|
|
|
|
|
if (table->use == UINT_MAX)
|
|
|
|
|
return -EOVERFLOW;
|
|
|
|
|
|
|
|
|
|
if (nla[NFTA_CHAIN_HOOK]) {
|
|
|
|
|
struct nft_stats __percpu *stats = NULL;
|
|
|
|
|
struct nft_chain_hook hook = {};
|
|
|
|
|
@@ -2494,6 +2493,11 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
|
|
|
|
|
if (err < 0)
|
|
|
|
|
goto err_destroy_chain;
|
|
|
|
|
|
|
|
|
|
if (!nft_use_inc(&table->use)) {
|
|
|
|
|
err = -EMFILE;
|
|
|
|
|
goto err_use;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
trans = nft_trans_chain_add(ctx, NFT_MSG_NEWCHAIN);
|
|
|
|
|
if (IS_ERR(trans)) {
|
|
|
|
|
err = PTR_ERR(trans);
|
|
|
|
|
@@ -2510,10 +2514,11 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
|
|
|
|
|
goto err_unregister_hook;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
table->use++;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
err_unregister_hook:
|
|
|
|
|
nft_use_dec_restore(&table->use);
|
|
|
|
|
err_use:
|
|
|
|
|
nf_tables_unregister_hook(net, table, chain);
|
|
|
|
|
err_destroy_chain:
|
|
|
|
|
nf_tables_chain_destroy(ctx);
|
|
|
|
|
@@ -3840,9 +3845,6 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info,
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
handle = nf_tables_alloc_handle(table);
|
|
|
|
|
|
|
|
|
|
if (chain->use == UINT_MAX)
|
|
|
|
|
return -EOVERFLOW;
|
|
|
|
|
|
|
|
|
|
if (nla[NFTA_RULE_POSITION]) {
|
|
|
|
|
pos_handle = be64_to_cpu(nla_get_be64(nla[NFTA_RULE_POSITION]));
|
|
|
|
|
old_rule = __nft_rule_lookup(chain, pos_handle);
|
|
|
|
|
@@ -3936,6 +3938,11 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!nft_use_inc(&chain->use)) {
|
|
|
|
|
err = -EMFILE;
|
|
|
|
|
goto err_release_rule;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (info->nlh->nlmsg_flags & NLM_F_REPLACE) {
|
|
|
|
|
err = nft_delrule(&ctx, old_rule);
|
|
|
|
|
if (err < 0)
|
|
|
|
|
@@ -3967,7 +3974,6 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
kvfree(expr_info);
|
|
|
|
|
chain->use++;
|
|
|
|
|
|
|
|
|
|
if (flow)
|
|
|
|
|
nft_trans_flow_rule(trans) = flow;
|
|
|
|
|
@@ -3978,6 +3984,7 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info,
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
err_destroy_flow_rule:
|
|
|
|
|
nft_use_dec_restore(&chain->use);
|
|
|
|
|
if (flow)
|
|
|
|
|
nft_flow_rule_destroy(flow);
|
|
|
|
|
err_release_rule:
|
|
|
|
|
@@ -5014,9 +5021,15 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
|
|
|
|
|
alloc_size = sizeof(*set) + size + udlen;
|
|
|
|
|
if (alloc_size < size || alloc_size > INT_MAX)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
|
|
if (!nft_use_inc(&table->use))
|
|
|
|
|
return -EMFILE;
|
|
|
|
|
|
|
|
|
|
set = kvzalloc(alloc_size, GFP_KERNEL_ACCOUNT);
|
|
|
|
|
if (!set)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
if (!set) {
|
|
|
|
|
err = -ENOMEM;
|
|
|
|
|
goto err_alloc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
name = nla_strdup(nla[NFTA_SET_NAME], GFP_KERNEL_ACCOUNT);
|
|
|
|
|
if (!name) {
|
|
|
|
|
@@ -5074,7 +5087,7 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
|
|
|
|
|
goto err_set_expr_alloc;
|
|
|
|
|
|
|
|
|
|
list_add_tail_rcu(&set->list, &table->sets);
|
|
|
|
|
table->use++;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
err_set_expr_alloc:
|
|
|
|
|
@@ -5086,6 +5099,9 @@ err_set_init:
|
|
|
|
|
kfree(set->name);
|
|
|
|
|
err_set_name:
|
|
|
|
|
kvfree(set);
|
|
|
|
|
err_alloc:
|
|
|
|
|
nft_use_dec_restore(&table->use);
|
|
|
|
|
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -5224,9 +5240,6 @@ int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
|
|
|
|
|
struct nft_set_binding *i;
|
|
|
|
|
struct nft_set_iter iter;
|
|
|
|
|
|
|
|
|
|
if (set->use == UINT_MAX)
|
|
|
|
|
return -EOVERFLOW;
|
|
|
|
|
|
|
|
|
|
if (!list_empty(&set->bindings) && nft_set_is_anonymous(set))
|
|
|
|
|
return -EBUSY;
|
|
|
|
|
|
|
|
|
|
@@ -5254,10 +5267,12 @@ int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
|
|
|
|
|
return iter.err;
|
|
|
|
|
}
|
|
|
|
|
bind:
|
|
|
|
|
if (!nft_use_inc(&set->use))
|
|
|
|
|
return -EMFILE;
|
|
|
|
|
|
|
|
|
|
binding->chain = ctx->chain;
|
|
|
|
|
list_add_tail_rcu(&binding->list, &set->bindings);
|
|
|
|
|
nft_set_trans_bind(ctx, set);
|
|
|
|
|
set->use++;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
@@ -5331,7 +5346,7 @@ void nf_tables_activate_set(const struct nft_ctx *ctx, struct nft_set *set)
|
|
|
|
|
nft_clear(ctx->net, set);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set->use++;
|
|
|
|
|
nft_use_inc_restore(&set->use);
|
|
|
|
|
}
|
|
|
|
|
EXPORT_SYMBOL_GPL(nf_tables_activate_set);
|
|
|
|
|
|
|
|
|
|
@@ -5347,7 +5362,7 @@ void nf_tables_deactivate_set(const struct nft_ctx *ctx, struct nft_set *set,
|
|
|
|
|
else
|
|
|
|
|
list_del_rcu(&binding->list);
|
|
|
|
|
|
|
|
|
|
set->use--;
|
|
|
|
|
nft_use_dec(&set->use);
|
|
|
|
|
break;
|
|
|
|
|
case NFT_TRANS_PREPARE:
|
|
|
|
|
if (nft_set_is_anonymous(set)) {
|
|
|
|
|
@@ -5356,7 +5371,7 @@ void nf_tables_deactivate_set(const struct nft_ctx *ctx, struct nft_set *set,
|
|
|
|
|
|
|
|
|
|
nft_deactivate_next(ctx->net, set);
|
|
|
|
|
}
|
|
|
|
|
set->use--;
|
|
|
|
|
nft_use_dec(&set->use);
|
|
|
|
|
return;
|
|
|
|
|
case NFT_TRANS_ABORT:
|
|
|
|
|
case NFT_TRANS_RELEASE:
|
|
|
|
|
@@ -5364,7 +5379,7 @@ void nf_tables_deactivate_set(const struct nft_ctx *ctx, struct nft_set *set,
|
|
|
|
|
set->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
|
|
|
|
|
nft_map_deactivate(ctx, set);
|
|
|
|
|
|
|
|
|
|
set->use--;
|
|
|
|
|
nft_use_dec(&set->use);
|
|
|
|
|
fallthrough;
|
|
|
|
|
default:
|
|
|
|
|
nf_tables_unbind_set(ctx, set, binding,
|
|
|
|
|
@@ -6155,7 +6170,7 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem,
|
|
|
|
|
nft_set_elem_expr_destroy(&ctx, nft_set_ext_expr(ext));
|
|
|
|
|
|
|
|
|
|
if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF))
|
|
|
|
|
(*nft_set_ext_obj(ext))->use--;
|
|
|
|
|
nft_use_dec(&(*nft_set_ext_obj(ext))->use);
|
|
|
|
|
kfree(elem);
|
|
|
|
|
}
|
|
|
|
|
EXPORT_SYMBOL_GPL(nft_set_elem_destroy);
|
|
|
|
|
@@ -6657,8 +6672,16 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
|
|
|
|
|
set->objtype, genmask);
|
|
|
|
|
if (IS_ERR(obj)) {
|
|
|
|
|
err = PTR_ERR(obj);
|
|
|
|
|
obj = NULL;
|
|
|
|
|
goto err_parse_key_end;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!nft_use_inc(&obj->use)) {
|
|
|
|
|
err = -EMFILE;
|
|
|
|
|
obj = NULL;
|
|
|
|
|
goto err_parse_key_end;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = nft_set_ext_add(&tmpl, NFT_SET_EXT_OBJREF);
|
|
|
|
|
if (err < 0)
|
|
|
|
|
goto err_parse_key_end;
|
|
|
|
|
@@ -6727,10 +6750,9 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
|
|
|
|
|
if (flags)
|
|
|
|
|
*nft_set_ext_flags(ext) = flags;
|
|
|
|
|
|
|
|
|
|
if (obj) {
|
|
|
|
|
if (obj)
|
|
|
|
|
*nft_set_ext_obj(ext) = obj;
|
|
|
|
|
obj->use++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ulen > 0) {
|
|
|
|
|
if (nft_set_ext_check(&tmpl, NFT_SET_EXT_USERDATA, ulen) < 0) {
|
|
|
|
|
err = -EINVAL;
|
|
|
|
|
@@ -6798,12 +6820,13 @@ err_element_clash:
|
|
|
|
|
kfree(trans);
|
|
|
|
|
err_elem_free:
|
|
|
|
|
nf_tables_set_elem_destroy(ctx, set, elem.priv);
|
|
|
|
|
if (obj)
|
|
|
|
|
obj->use--;
|
|
|
|
|
err_parse_data:
|
|
|
|
|
if (nla[NFTA_SET_ELEM_DATA] != NULL)
|
|
|
|
|
nft_data_release(&elem.data.val, desc.type);
|
|
|
|
|
err_parse_key_end:
|
|
|
|
|
if (obj)
|
|
|
|
|
nft_use_dec_restore(&obj->use);
|
|
|
|
|
|
|
|
|
|
nft_data_release(&elem.key_end.val, NFT_DATA_VALUE);
|
|
|
|
|
err_parse_key:
|
|
|
|
|
nft_data_release(&elem.key.val, NFT_DATA_VALUE);
|
|
|
|
|
@@ -6883,7 +6906,7 @@ void nft_data_hold(const struct nft_data *data, enum nft_data_types type)
|
|
|
|
|
case NFT_JUMP:
|
|
|
|
|
case NFT_GOTO:
|
|
|
|
|
chain = data->verdict.chain;
|
|
|
|
|
chain->use++;
|
|
|
|
|
nft_use_inc_restore(&chain->use);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -6898,7 +6921,7 @@ static void nft_setelem_data_activate(const struct net *net,
|
|
|
|
|
if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA))
|
|
|
|
|
nft_data_hold(nft_set_ext_data(ext), set->dtype);
|
|
|
|
|
if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF))
|
|
|
|
|
(*nft_set_ext_obj(ext))->use++;
|
|
|
|
|
nft_use_inc_restore(&(*nft_set_ext_obj(ext))->use);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void nft_setelem_data_deactivate(const struct net *net,
|
|
|
|
|
@@ -6910,7 +6933,7 @@ static void nft_setelem_data_deactivate(const struct net *net,
|
|
|
|
|
if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA))
|
|
|
|
|
nft_data_release(nft_set_ext_data(ext), set->dtype);
|
|
|
|
|
if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF))
|
|
|
|
|
(*nft_set_ext_obj(ext))->use--;
|
|
|
|
|
nft_use_dec(&(*nft_set_ext_obj(ext))->use);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set,
|
|
|
|
|
@@ -7453,9 +7476,14 @@ static int nf_tables_newobj(struct sk_buff *skb, const struct nfnl_info *info,
|
|
|
|
|
|
|
|
|
|
nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla);
|
|
|
|
|
|
|
|
|
|
if (!nft_use_inc(&table->use))
|
|
|
|
|
return -EMFILE;
|
|
|
|
|
|
|
|
|
|
type = nft_obj_type_get(net, objtype);
|
|
|
|
|
if (IS_ERR(type))
|
|
|
|
|
return PTR_ERR(type);
|
|
|
|
|
if (IS_ERR(type)) {
|
|
|
|
|
err = PTR_ERR(type);
|
|
|
|
|
goto err_type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
obj = nft_obj_init(&ctx, type, nla[NFTA_OBJ_DATA]);
|
|
|
|
|
if (IS_ERR(obj)) {
|
|
|
|
|
@@ -7489,7 +7517,7 @@ static int nf_tables_newobj(struct sk_buff *skb, const struct nfnl_info *info,
|
|
|
|
|
goto err_obj_ht;
|
|
|
|
|
|
|
|
|
|
list_add_tail_rcu(&obj->list, &table->objects);
|
|
|
|
|
table->use++;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
err_obj_ht:
|
|
|
|
|
/* queued in transaction log */
|
|
|
|
|
@@ -7505,6 +7533,9 @@ err_strdup:
|
|
|
|
|
kfree(obj);
|
|
|
|
|
err_init:
|
|
|
|
|
module_put(type->owner);
|
|
|
|
|
err_type:
|
|
|
|
|
nft_use_dec_restore(&table->use);
|
|
|
|
|
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -7906,7 +7937,7 @@ void nf_tables_deactivate_flowtable(const struct nft_ctx *ctx,
|
|
|
|
|
case NFT_TRANS_PREPARE:
|
|
|
|
|
case NFT_TRANS_ABORT:
|
|
|
|
|
case NFT_TRANS_RELEASE:
|
|
|
|
|
flowtable->use--;
|
|
|
|
|
nft_use_dec(&flowtable->use);
|
|
|
|
|
fallthrough;
|
|
|
|
|
default:
|
|
|
|
|
return;
|
|
|
|
|
@@ -8260,9 +8291,14 @@ static int nf_tables_newflowtable(struct sk_buff *skb,
|
|
|
|
|
|
|
|
|
|
nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla);
|
|
|
|
|
|
|
|
|
|
if (!nft_use_inc(&table->use))
|
|
|
|
|
return -EMFILE;
|
|
|
|
|
|
|
|
|
|
flowtable = kzalloc(sizeof(*flowtable), GFP_KERNEL_ACCOUNT);
|
|
|
|
|
if (!flowtable)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
if (!flowtable) {
|
|
|
|
|
err = -ENOMEM;
|
|
|
|
|
goto flowtable_alloc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
flowtable->table = table;
|
|
|
|
|
flowtable->handle = nf_tables_alloc_handle(table);
|
|
|
|
|
@@ -8317,7 +8353,6 @@ static int nf_tables_newflowtable(struct sk_buff *skb,
|
|
|
|
|
goto err5;
|
|
|
|
|
|
|
|
|
|
list_add_tail_rcu(&flowtable->list, &table->flowtables);
|
|
|
|
|
table->use++;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
err5:
|
|
|
|
|
@@ -8334,6 +8369,9 @@ err2:
|
|
|
|
|
kfree(flowtable->name);
|
|
|
|
|
err1:
|
|
|
|
|
kfree(flowtable);
|
|
|
|
|
flowtable_alloc:
|
|
|
|
|
nft_use_dec_restore(&table->use);
|
|
|
|
|
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -9713,7 +9751,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
|
|
|
|
|
*/
|
|
|
|
|
if (nft_set_is_anonymous(nft_trans_set(trans)) &&
|
|
|
|
|
!list_empty(&nft_trans_set(trans)->bindings))
|
|
|
|
|
trans->ctx.table->use--;
|
|
|
|
|
nft_use_dec(&trans->ctx.table->use);
|
|
|
|
|
}
|
|
|
|
|
nf_tables_set_notify(&trans->ctx, nft_trans_set(trans),
|
|
|
|
|
NFT_MSG_NEWSET, GFP_KERNEL);
|
|
|
|
|
@@ -9943,7 +9981,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
|
|
|
|
|
nft_trans_destroy(trans);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
trans->ctx.table->use--;
|
|
|
|
|
nft_use_dec_restore(&trans->ctx.table->use);
|
|
|
|
|
nft_chain_del(trans->ctx.chain);
|
|
|
|
|
nf_tables_unregister_hook(trans->ctx.net,
|
|
|
|
|
trans->ctx.table,
|
|
|
|
|
@@ -9956,7 +9994,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
|
|
|
|
|
list_splice(&nft_trans_chain_hooks(trans),
|
|
|
|
|
&nft_trans_basechain(trans)->hook_list);
|
|
|
|
|
} else {
|
|
|
|
|
trans->ctx.table->use++;
|
|
|
|
|
nft_use_inc_restore(&trans->ctx.table->use);
|
|
|
|
|
nft_clear(trans->ctx.net, trans->ctx.chain);
|
|
|
|
|
}
|
|
|
|
|
nft_trans_destroy(trans);
|
|
|
|
|
@@ -9966,7 +10004,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
|
|
|
|
|
nft_trans_destroy(trans);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
trans->ctx.chain->use--;
|
|
|
|
|
nft_use_dec_restore(&trans->ctx.chain->use);
|
|
|
|
|
list_del_rcu(&nft_trans_rule(trans)->list);
|
|
|
|
|
nft_rule_expr_deactivate(&trans->ctx,
|
|
|
|
|
nft_trans_rule(trans),
|
|
|
|
|
@@ -9976,7 +10014,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
|
|
|
|
|
break;
|
|
|
|
|
case NFT_MSG_DELRULE:
|
|
|
|
|
case NFT_MSG_DESTROYRULE:
|
|
|
|
|
trans->ctx.chain->use++;
|
|
|
|
|
nft_use_inc_restore(&trans->ctx.chain->use);
|
|
|
|
|
nft_clear(trans->ctx.net, nft_trans_rule(trans));
|
|
|
|
|
nft_rule_expr_activate(&trans->ctx, nft_trans_rule(trans));
|
|
|
|
|
if (trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD)
|
|
|
|
|
@@ -9989,7 +10027,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
|
|
|
|
|
nft_trans_destroy(trans);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
trans->ctx.table->use--;
|
|
|
|
|
nft_use_dec_restore(&trans->ctx.table->use);
|
|
|
|
|
if (nft_trans_set_bound(trans)) {
|
|
|
|
|
nft_trans_destroy(trans);
|
|
|
|
|
break;
|
|
|
|
|
@@ -9998,7 +10036,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
|
|
|
|
|
break;
|
|
|
|
|
case NFT_MSG_DELSET:
|
|
|
|
|
case NFT_MSG_DESTROYSET:
|
|
|
|
|
trans->ctx.table->use++;
|
|
|
|
|
nft_use_inc_restore(&trans->ctx.table->use);
|
|
|
|
|
nft_clear(trans->ctx.net, nft_trans_set(trans));
|
|
|
|
|
if (nft_trans_set(trans)->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
|
|
|
|
|
nft_map_activate(&trans->ctx, nft_trans_set(trans));
|
|
|
|
|
@@ -10042,13 +10080,13 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
|
|
|
|
|
nft_obj_destroy(&trans->ctx, nft_trans_obj_newobj(trans));
|
|
|
|
|
nft_trans_destroy(trans);
|
|
|
|
|
} else {
|
|
|
|
|
trans->ctx.table->use--;
|
|
|
|
|
nft_use_dec_restore(&trans->ctx.table->use);
|
|
|
|
|
nft_obj_del(nft_trans_obj(trans));
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case NFT_MSG_DELOBJ:
|
|
|
|
|
case NFT_MSG_DESTROYOBJ:
|
|
|
|
|
trans->ctx.table->use++;
|
|
|
|
|
nft_use_inc_restore(&trans->ctx.table->use);
|
|
|
|
|
nft_clear(trans->ctx.net, nft_trans_obj(trans));
|
|
|
|
|
nft_trans_destroy(trans);
|
|
|
|
|
break;
|
|
|
|
|
@@ -10057,7 +10095,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
|
|
|
|
|
nft_unregister_flowtable_net_hooks(net,
|
|
|
|
|
&nft_trans_flowtable_hooks(trans));
|
|
|
|
|
} else {
|
|
|
|
|
trans->ctx.table->use--;
|
|
|
|
|
nft_use_dec_restore(&trans->ctx.table->use);
|
|
|
|
|
list_del_rcu(&nft_trans_flowtable(trans)->list);
|
|
|
|
|
nft_unregister_flowtable_net_hooks(net,
|
|
|
|
|
&nft_trans_flowtable(trans)->hook_list);
|
|
|
|
|
@@ -10069,7 +10107,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
|
|
|
|
|
list_splice(&nft_trans_flowtable_hooks(trans),
|
|
|
|
|
&nft_trans_flowtable(trans)->hook_list);
|
|
|
|
|
} else {
|
|
|
|
|
trans->ctx.table->use++;
|
|
|
|
|
nft_use_inc_restore(&trans->ctx.table->use);
|
|
|
|
|
nft_clear(trans->ctx.net, nft_trans_flowtable(trans));
|
|
|
|
|
}
|
|
|
|
|
nft_trans_destroy(trans);
|
|
|
|
|
@@ -10518,8 +10556,9 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
|
|
|
|
|
if (desc->flags & NFT_DATA_DESC_SETELEM &&
|
|
|
|
|
chain->flags & NFT_CHAIN_BINDING)
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
if (!nft_use_inc(&chain->use))
|
|
|
|
|
return -EMFILE;
|
|
|
|
|
|
|
|
|
|
chain->use++;
|
|
|
|
|
data->verdict.chain = chain;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
@@ -10537,7 +10576,7 @@ static void nft_verdict_uninit(const struct nft_data *data)
|
|
|
|
|
case NFT_JUMP:
|
|
|
|
|
case NFT_GOTO:
|
|
|
|
|
chain = data->verdict.chain;
|
|
|
|
|
chain->use--;
|
|
|
|
|
nft_use_dec(&chain->use);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -10706,11 +10745,11 @@ int __nft_release_basechain(struct nft_ctx *ctx)
|
|
|
|
|
nf_tables_unregister_hook(ctx->net, ctx->chain->table, ctx->chain);
|
|
|
|
|
list_for_each_entry_safe(rule, nr, &ctx->chain->rules, list) {
|
|
|
|
|
list_del(&rule->list);
|
|
|
|
|
ctx->chain->use--;
|
|
|
|
|
nft_use_dec(&ctx->chain->use);
|
|
|
|
|
nf_tables_rule_release(ctx, rule);
|
|
|
|
|
}
|
|
|
|
|
nft_chain_del(ctx->chain);
|
|
|
|
|
ctx->table->use--;
|
|
|
|
|
nft_use_dec(&ctx->table->use);
|
|
|
|
|
nf_tables_chain_destroy(ctx);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
@@ -10760,18 +10799,18 @@ static void __nft_release_table(struct net *net, struct nft_table *table)
|
|
|
|
|
ctx.chain = chain;
|
|
|
|
|
list_for_each_entry_safe(rule, nr, &chain->rules, list) {
|
|
|
|
|
list_del(&rule->list);
|
|
|
|
|
chain->use--;
|
|
|
|
|
nft_use_dec(&chain->use);
|
|
|
|
|
nf_tables_rule_release(&ctx, rule);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
list_for_each_entry_safe(flowtable, nf, &table->flowtables, list) {
|
|
|
|
|
list_del(&flowtable->list);
|
|
|
|
|
table->use--;
|
|
|
|
|
nft_use_dec(&table->use);
|
|
|
|
|
nf_tables_flowtable_destroy(flowtable);
|
|
|
|
|
}
|
|
|
|
|
list_for_each_entry_safe(set, ns, &table->sets, list) {
|
|
|
|
|
list_del(&set->list);
|
|
|
|
|
table->use--;
|
|
|
|
|
nft_use_dec(&table->use);
|
|
|
|
|
if (set->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
|
|
|
|
|
nft_map_deactivate(&ctx, set);
|
|
|
|
|
|
|
|
|
|
@@ -10779,13 +10818,13 @@ static void __nft_release_table(struct net *net, struct nft_table *table)
|
|
|
|
|
}
|
|
|
|
|
list_for_each_entry_safe(obj, ne, &table->objects, list) {
|
|
|
|
|
nft_obj_del(obj);
|
|
|
|
|
table->use--;
|
|
|
|
|
nft_use_dec(&table->use);
|
|
|
|
|
nft_obj_destroy(&ctx, obj);
|
|
|
|
|
}
|
|
|
|
|
list_for_each_entry_safe(chain, nc, &table->chains, list) {
|
|
|
|
|
ctx.chain = chain;
|
|
|
|
|
nft_chain_del(chain);
|
|
|
|
|
table->use--;
|
|
|
|
|
nft_use_dec(&table->use);
|
|
|
|
|
nf_tables_chain_destroy(&ctx);
|
|
|
|
|
}
|
|
|
|
|
nf_tables_table_destroy(&ctx);
|
|
|
|
|
|