|
@@ -75,6 +75,7 @@ static void nft_ctx_init(struct nft_ctx *ctx,
|
|
|
{
|
|
|
ctx->net = net;
|
|
|
ctx->family = family;
|
|
|
+ ctx->level = 0;
|
|
|
ctx->table = table;
|
|
|
ctx->chain = chain;
|
|
|
ctx->nla = nla;
|
|
@@ -1597,7 +1598,6 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
|
|
|
struct nft_base_chain *basechain;
|
|
|
struct nft_stats *stats = NULL;
|
|
|
struct nft_chain_hook hook;
|
|
|
- const struct nlattr *name;
|
|
|
struct nf_hook_ops *ops;
|
|
|
struct nft_trans *trans;
|
|
|
int err;
|
|
@@ -1645,12 +1645,11 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
|
|
|
return PTR_ERR(stats);
|
|
|
}
|
|
|
|
|
|
+ err = -ENOMEM;
|
|
|
trans = nft_trans_alloc(ctx, NFT_MSG_NEWCHAIN,
|
|
|
sizeof(struct nft_trans_chain));
|
|
|
- if (trans == NULL) {
|
|
|
- free_percpu(stats);
|
|
|
- return -ENOMEM;
|
|
|
- }
|
|
|
+ if (trans == NULL)
|
|
|
+ goto err;
|
|
|
|
|
|
nft_trans_chain_stats(trans) = stats;
|
|
|
nft_trans_chain_update(trans) = true;
|
|
@@ -1660,19 +1659,37 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
|
|
|
else
|
|
|
nft_trans_chain_policy(trans) = -1;
|
|
|
|
|
|
- name = nla[NFTA_CHAIN_NAME];
|
|
|
- if (nla[NFTA_CHAIN_HANDLE] && name) {
|
|
|
- nft_trans_chain_name(trans) =
|
|
|
- nla_strdup(name, GFP_KERNEL);
|
|
|
- if (!nft_trans_chain_name(trans)) {
|
|
|
- kfree(trans);
|
|
|
- free_percpu(stats);
|
|
|
- return -ENOMEM;
|
|
|
+ if (nla[NFTA_CHAIN_HANDLE] &&
|
|
|
+ nla[NFTA_CHAIN_NAME]) {
|
|
|
+ struct nft_trans *tmp;
|
|
|
+ char *name;
|
|
|
+
|
|
|
+ err = -ENOMEM;
|
|
|
+ name = nla_strdup(nla[NFTA_CHAIN_NAME], GFP_KERNEL);
|
|
|
+ if (!name)
|
|
|
+ goto err;
|
|
|
+
|
|
|
+ err = -EEXIST;
|
|
|
+ list_for_each_entry(tmp, &ctx->net->nft.commit_list, list) {
|
|
|
+ if (tmp->msg_type == NFT_MSG_NEWCHAIN &&
|
|
|
+ tmp->ctx.table == table &&
|
|
|
+ nft_trans_chain_update(tmp) &&
|
|
|
+ nft_trans_chain_name(tmp) &&
|
|
|
+ strcmp(name, nft_trans_chain_name(tmp)) == 0) {
|
|
|
+ kfree(name);
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+ nft_trans_chain_name(trans) = name;
|
|
|
}
|
|
|
list_add_tail(&trans->list, &ctx->net->nft.commit_list);
|
|
|
|
|
|
return 0;
|
|
|
+err:
|
|
|
+ free_percpu(stats);
|
|
|
+ kfree(trans);
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
static int nf_tables_newchain(struct net *net, struct sock *nlsk,
|
|
@@ -2254,6 +2271,39 @@ done:
|
|
|
return skb->len;
|
|
|
}
|
|
|
|
|
|
+static int nf_tables_dump_rules_start(struct netlink_callback *cb)
|
|
|
+{
|
|
|
+ const struct nlattr * const *nla = cb->data;
|
|
|
+ struct nft_rule_dump_ctx *ctx = NULL;
|
|
|
+
|
|
|
+ if (nla[NFTA_RULE_TABLE] || nla[NFTA_RULE_CHAIN]) {
|
|
|
+ ctx = kzalloc(sizeof(*ctx), GFP_ATOMIC);
|
|
|
+ if (!ctx)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ if (nla[NFTA_RULE_TABLE]) {
|
|
|
+ ctx->table = nla_strdup(nla[NFTA_RULE_TABLE],
|
|
|
+ GFP_ATOMIC);
|
|
|
+ if (!ctx->table) {
|
|
|
+ kfree(ctx);
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (nla[NFTA_RULE_CHAIN]) {
|
|
|
+ ctx->chain = nla_strdup(nla[NFTA_RULE_CHAIN],
|
|
|
+ GFP_ATOMIC);
|
|
|
+ if (!ctx->chain) {
|
|
|
+ kfree(ctx->table);
|
|
|
+ kfree(ctx);
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ cb->data = ctx;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int nf_tables_dump_rules_done(struct netlink_callback *cb)
|
|
|
{
|
|
|
struct nft_rule_dump_ctx *ctx = cb->data;
|
|
@@ -2283,38 +2333,13 @@ static int nf_tables_getrule(struct net *net, struct sock *nlsk,
|
|
|
|
|
|
if (nlh->nlmsg_flags & NLM_F_DUMP) {
|
|
|
struct netlink_dump_control c = {
|
|
|
+ .start= nf_tables_dump_rules_start,
|
|
|
.dump = nf_tables_dump_rules,
|
|
|
.done = nf_tables_dump_rules_done,
|
|
|
.module = THIS_MODULE,
|
|
|
+ .data = (void *)nla,
|
|
|
};
|
|
|
|
|
|
- if (nla[NFTA_RULE_TABLE] || nla[NFTA_RULE_CHAIN]) {
|
|
|
- struct nft_rule_dump_ctx *ctx;
|
|
|
-
|
|
|
- ctx = kzalloc(sizeof(*ctx), GFP_ATOMIC);
|
|
|
- if (!ctx)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- if (nla[NFTA_RULE_TABLE]) {
|
|
|
- ctx->table = nla_strdup(nla[NFTA_RULE_TABLE],
|
|
|
- GFP_ATOMIC);
|
|
|
- if (!ctx->table) {
|
|
|
- kfree(ctx);
|
|
|
- return -ENOMEM;
|
|
|
- }
|
|
|
- }
|
|
|
- if (nla[NFTA_RULE_CHAIN]) {
|
|
|
- ctx->chain = nla_strdup(nla[NFTA_RULE_CHAIN],
|
|
|
- GFP_ATOMIC);
|
|
|
- if (!ctx->chain) {
|
|
|
- kfree(ctx->table);
|
|
|
- kfree(ctx);
|
|
|
- return -ENOMEM;
|
|
|
- }
|
|
|
- }
|
|
|
- c.data = ctx;
|
|
|
- }
|
|
|
-
|
|
|
return nft_netlink_dump_start_rcu(nlsk, skb, nlh, &c);
|
|
|
}
|
|
|
|
|
@@ -2384,6 +2409,9 @@ int nft_chain_validate(const struct nft_ctx *ctx, const struct nft_chain *chain)
|
|
|
struct nft_rule *rule;
|
|
|
int err;
|
|
|
|
|
|
+ if (ctx->level == NFT_JUMP_STACK_SIZE)
|
|
|
+ return -EMLINK;
|
|
|
+
|
|
|
list_for_each_entry(rule, &chain->rules, list) {
|
|
|
if (!nft_is_active_next(ctx->net, rule))
|
|
|
continue;
|
|
@@ -3161,6 +3189,18 @@ done:
|
|
|
return skb->len;
|
|
|
}
|
|
|
|
|
|
+static int nf_tables_dump_sets_start(struct netlink_callback *cb)
|
|
|
+{
|
|
|
+ struct nft_ctx *ctx_dump = NULL;
|
|
|
+
|
|
|
+ ctx_dump = kmemdup(cb->data, sizeof(*ctx_dump), GFP_ATOMIC);
|
|
|
+ if (ctx_dump == NULL)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ cb->data = ctx_dump;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int nf_tables_dump_sets_done(struct netlink_callback *cb)
|
|
|
{
|
|
|
kfree(cb->data);
|
|
@@ -3188,18 +3228,12 @@ static int nf_tables_getset(struct net *net, struct sock *nlsk,
|
|
|
|
|
|
if (nlh->nlmsg_flags & NLM_F_DUMP) {
|
|
|
struct netlink_dump_control c = {
|
|
|
+ .start = nf_tables_dump_sets_start,
|
|
|
.dump = nf_tables_dump_sets,
|
|
|
.done = nf_tables_dump_sets_done,
|
|
|
+ .data = &ctx,
|
|
|
.module = THIS_MODULE,
|
|
|
};
|
|
|
- struct nft_ctx *ctx_dump;
|
|
|
-
|
|
|
- ctx_dump = kmalloc(sizeof(*ctx_dump), GFP_ATOMIC);
|
|
|
- if (ctx_dump == NULL)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- *ctx_dump = ctx;
|
|
|
- c.data = ctx_dump;
|
|
|
|
|
|
return nft_netlink_dump_start_rcu(nlsk, skb, nlh, &c);
|
|
|
}
|
|
@@ -3849,6 +3883,15 @@ nla_put_failure:
|
|
|
return -ENOSPC;
|
|
|
}
|
|
|
|
|
|
+static int nf_tables_dump_set_start(struct netlink_callback *cb)
|
|
|
+{
|
|
|
+ struct nft_set_dump_ctx *dump_ctx = cb->data;
|
|
|
+
|
|
|
+ cb->data = kmemdup(dump_ctx, sizeof(*dump_ctx), GFP_ATOMIC);
|
|
|
+
|
|
|
+ return cb->data ? 0 : -ENOMEM;
|
|
|
+}
|
|
|
+
|
|
|
static int nf_tables_dump_set_done(struct netlink_callback *cb)
|
|
|
{
|
|
|
kfree(cb->data);
|
|
@@ -4002,20 +4045,17 @@ static int nf_tables_getsetelem(struct net *net, struct sock *nlsk,
|
|
|
|
|
|
if (nlh->nlmsg_flags & NLM_F_DUMP) {
|
|
|
struct netlink_dump_control c = {
|
|
|
+ .start = nf_tables_dump_set_start,
|
|
|
.dump = nf_tables_dump_set,
|
|
|
.done = nf_tables_dump_set_done,
|
|
|
.module = THIS_MODULE,
|
|
|
};
|
|
|
- struct nft_set_dump_ctx *dump_ctx;
|
|
|
-
|
|
|
- dump_ctx = kmalloc(sizeof(*dump_ctx), GFP_ATOMIC);
|
|
|
- if (!dump_ctx)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- dump_ctx->set = set;
|
|
|
- dump_ctx->ctx = ctx;
|
|
|
+ struct nft_set_dump_ctx dump_ctx = {
|
|
|
+ .set = set,
|
|
|
+ .ctx = ctx,
|
|
|
+ };
|
|
|
|
|
|
- c.data = dump_ctx;
|
|
|
+ c.data = &dump_ctx;
|
|
|
return nft_netlink_dump_start_rcu(nlsk, skb, nlh, &c);
|
|
|
}
|
|
|
|
|
@@ -4975,38 +5015,42 @@ done:
|
|
|
return skb->len;
|
|
|
}
|
|
|
|
|
|
-static int nf_tables_dump_obj_done(struct netlink_callback *cb)
|
|
|
+static int nf_tables_dump_obj_start(struct netlink_callback *cb)
|
|
|
{
|
|
|
- struct nft_obj_filter *filter = cb->data;
|
|
|
+ const struct nlattr * const *nla = cb->data;
|
|
|
+ struct nft_obj_filter *filter = NULL;
|
|
|
|
|
|
- if (filter) {
|
|
|
- kfree(filter->table);
|
|
|
- kfree(filter);
|
|
|
+ if (nla[NFTA_OBJ_TABLE] || nla[NFTA_OBJ_TYPE]) {
|
|
|
+ filter = kzalloc(sizeof(*filter), GFP_ATOMIC);
|
|
|
+ if (!filter)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ if (nla[NFTA_OBJ_TABLE]) {
|
|
|
+ filter->table = nla_strdup(nla[NFTA_OBJ_TABLE], GFP_ATOMIC);
|
|
|
+ if (!filter->table) {
|
|
|
+ kfree(filter);
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (nla[NFTA_OBJ_TYPE])
|
|
|
+ filter->type = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE]));
|
|
|
}
|
|
|
|
|
|
+ cb->data = filter;
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static struct nft_obj_filter *
|
|
|
-nft_obj_filter_alloc(const struct nlattr * const nla[])
|
|
|
+static int nf_tables_dump_obj_done(struct netlink_callback *cb)
|
|
|
{
|
|
|
- struct nft_obj_filter *filter;
|
|
|
-
|
|
|
- filter = kzalloc(sizeof(*filter), GFP_ATOMIC);
|
|
|
- if (!filter)
|
|
|
- return ERR_PTR(-ENOMEM);
|
|
|
+ struct nft_obj_filter *filter = cb->data;
|
|
|
|
|
|
- if (nla[NFTA_OBJ_TABLE]) {
|
|
|
- filter->table = nla_strdup(nla[NFTA_OBJ_TABLE], GFP_ATOMIC);
|
|
|
- if (!filter->table) {
|
|
|
- kfree(filter);
|
|
|
- return ERR_PTR(-ENOMEM);
|
|
|
- }
|
|
|
+ if (filter) {
|
|
|
+ kfree(filter->table);
|
|
|
+ kfree(filter);
|
|
|
}
|
|
|
- if (nla[NFTA_OBJ_TYPE])
|
|
|
- filter->type = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE]));
|
|
|
|
|
|
- return filter;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
/* called with rcu_read_lock held */
|
|
@@ -5027,21 +5071,13 @@ static int nf_tables_getobj(struct net *net, struct sock *nlsk,
|
|
|
|
|
|
if (nlh->nlmsg_flags & NLM_F_DUMP) {
|
|
|
struct netlink_dump_control c = {
|
|
|
+ .start = nf_tables_dump_obj_start,
|
|
|
.dump = nf_tables_dump_obj,
|
|
|
.done = nf_tables_dump_obj_done,
|
|
|
.module = THIS_MODULE,
|
|
|
+ .data = (void *)nla,
|
|
|
};
|
|
|
|
|
|
- if (nla[NFTA_OBJ_TABLE] ||
|
|
|
- nla[NFTA_OBJ_TYPE]) {
|
|
|
- struct nft_obj_filter *filter;
|
|
|
-
|
|
|
- filter = nft_obj_filter_alloc(nla);
|
|
|
- if (IS_ERR(filter))
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- c.data = filter;
|
|
|
- }
|
|
|
return nft_netlink_dump_start_rcu(nlsk, skb, nlh, &c);
|
|
|
}
|
|
|
|
|
@@ -5320,8 +5356,6 @@ static int nf_tables_flowtable_parse_hook(const struct nft_ctx *ctx,
|
|
|
flowtable->ops[i].priv = &flowtable->data;
|
|
|
flowtable->ops[i].hook = flowtable->data.type->hook;
|
|
|
flowtable->ops[i].dev = dev_array[i];
|
|
|
- flowtable->dev_name[i] = kstrdup(dev_array[i]->name,
|
|
|
- GFP_KERNEL);
|
|
|
}
|
|
|
|
|
|
return err;
|
|
@@ -5479,10 +5513,8 @@ static int nf_tables_newflowtable(struct net *net, struct sock *nlsk,
|
|
|
err6:
|
|
|
i = flowtable->ops_len;
|
|
|
err5:
|
|
|
- for (k = i - 1; k >= 0; k--) {
|
|
|
- kfree(flowtable->dev_name[k]);
|
|
|
+ for (k = i - 1; k >= 0; k--)
|
|
|
nf_unregister_net_hook(net, &flowtable->ops[k]);
|
|
|
- }
|
|
|
|
|
|
kfree(flowtable->ops);
|
|
|
err4:
|
|
@@ -5581,9 +5613,10 @@ static int nf_tables_fill_flowtable_info(struct sk_buff *skb, struct net *net,
|
|
|
goto nla_put_failure;
|
|
|
|
|
|
for (i = 0; i < flowtable->ops_len; i++) {
|
|
|
- if (flowtable->dev_name[i][0] &&
|
|
|
- nla_put_string(skb, NFTA_DEVICE_NAME,
|
|
|
- flowtable->dev_name[i]))
|
|
|
+ const struct net_device *dev = READ_ONCE(flowtable->ops[i].dev);
|
|
|
+
|
|
|
+ if (dev &&
|
|
|
+ nla_put_string(skb, NFTA_DEVICE_NAME, dev->name))
|
|
|
goto nla_put_failure;
|
|
|
}
|
|
|
nla_nest_end(skb, nest_devs);
|
|
@@ -5650,37 +5683,39 @@ done:
|
|
|
return skb->len;
|
|
|
}
|
|
|
|
|
|
-static int nf_tables_dump_flowtable_done(struct netlink_callback *cb)
|
|
|
+static int nf_tables_dump_flowtable_start(struct netlink_callback *cb)
|
|
|
{
|
|
|
- struct nft_flowtable_filter *filter = cb->data;
|
|
|
+ const struct nlattr * const *nla = cb->data;
|
|
|
+ struct nft_flowtable_filter *filter = NULL;
|
|
|
|
|
|
- if (!filter)
|
|
|
- return 0;
|
|
|
+ if (nla[NFTA_FLOWTABLE_TABLE]) {
|
|
|
+ filter = kzalloc(sizeof(*filter), GFP_ATOMIC);
|
|
|
+ if (!filter)
|
|
|
+ return -ENOMEM;
|
|
|
|
|
|
- kfree(filter->table);
|
|
|
- kfree(filter);
|
|
|
+ filter->table = nla_strdup(nla[NFTA_FLOWTABLE_TABLE],
|
|
|
+ GFP_ATOMIC);
|
|
|
+ if (!filter->table) {
|
|
|
+ kfree(filter);
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
+ cb->data = filter;
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static struct nft_flowtable_filter *
|
|
|
-nft_flowtable_filter_alloc(const struct nlattr * const nla[])
|
|
|
+static int nf_tables_dump_flowtable_done(struct netlink_callback *cb)
|
|
|
{
|
|
|
- struct nft_flowtable_filter *filter;
|
|
|
+ struct nft_flowtable_filter *filter = cb->data;
|
|
|
|
|
|
- filter = kzalloc(sizeof(*filter), GFP_ATOMIC);
|
|
|
if (!filter)
|
|
|
- return ERR_PTR(-ENOMEM);
|
|
|
+ return 0;
|
|
|
|
|
|
- if (nla[NFTA_FLOWTABLE_TABLE]) {
|
|
|
- filter->table = nla_strdup(nla[NFTA_FLOWTABLE_TABLE],
|
|
|
- GFP_ATOMIC);
|
|
|
- if (!filter->table) {
|
|
|
- kfree(filter);
|
|
|
- return ERR_PTR(-ENOMEM);
|
|
|
- }
|
|
|
- }
|
|
|
- return filter;
|
|
|
+ kfree(filter->table);
|
|
|
+ kfree(filter);
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
/* called with rcu_read_lock held */
|
|
@@ -5700,20 +5735,13 @@ static int nf_tables_getflowtable(struct net *net, struct sock *nlsk,
|
|
|
|
|
|
if (nlh->nlmsg_flags & NLM_F_DUMP) {
|
|
|
struct netlink_dump_control c = {
|
|
|
+ .start = nf_tables_dump_flowtable_start,
|
|
|
.dump = nf_tables_dump_flowtable,
|
|
|
.done = nf_tables_dump_flowtable_done,
|
|
|
.module = THIS_MODULE,
|
|
|
+ .data = (void *)nla,
|
|
|
};
|
|
|
|
|
|
- if (nla[NFTA_FLOWTABLE_TABLE]) {
|
|
|
- struct nft_flowtable_filter *filter;
|
|
|
-
|
|
|
- filter = nft_flowtable_filter_alloc(nla);
|
|
|
- if (IS_ERR(filter))
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- c.data = filter;
|
|
|
- }
|
|
|
return nft_netlink_dump_start_rcu(nlsk, skb, nlh, &c);
|
|
|
}
|
|
|
|
|
@@ -5783,6 +5811,7 @@ static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable)
|
|
|
kfree(flowtable->name);
|
|
|
flowtable->data.type->free(&flowtable->data);
|
|
|
module_put(flowtable->data.type->owner);
|
|
|
+ kfree(flowtable);
|
|
|
}
|
|
|
|
|
|
static int nf_tables_fill_gen_info(struct sk_buff *skb, struct net *net,
|
|
@@ -5825,7 +5854,6 @@ static void nft_flowtable_event(unsigned long event, struct net_device *dev,
|
|
|
continue;
|
|
|
|
|
|
nf_unregister_net_hook(dev_net(dev), &flowtable->ops[i]);
|
|
|
- flowtable->dev_name[i][0] = '\0';
|
|
|
flowtable->ops[i].dev = NULL;
|
|
|
break;
|
|
|
}
|
|
@@ -6086,6 +6114,9 @@ static void nft_commit_release(struct nft_trans *trans)
|
|
|
case NFT_MSG_DELTABLE:
|
|
|
nf_tables_table_destroy(&trans->ctx);
|
|
|
break;
|
|
|
+ case NFT_MSG_NEWCHAIN:
|
|
|
+ kfree(nft_trans_chain_name(trans));
|
|
|
+ break;
|
|
|
case NFT_MSG_DELCHAIN:
|
|
|
nf_tables_chain_destroy(&trans->ctx);
|
|
|
break;
|
|
@@ -6315,13 +6346,15 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
|
|
|
nf_tables_table_notify(&trans->ctx, NFT_MSG_DELTABLE);
|
|
|
break;
|
|
|
case NFT_MSG_NEWCHAIN:
|
|
|
- if (nft_trans_chain_update(trans))
|
|
|
+ if (nft_trans_chain_update(trans)) {
|
|
|
nft_chain_commit_update(trans);
|
|
|
- else
|
|
|
+ nf_tables_chain_notify(&trans->ctx, NFT_MSG_NEWCHAIN);
|
|
|
+ /* trans destroyed after rcu grace period */
|
|
|
+ } else {
|
|
|
nft_clear(net, trans->ctx.chain);
|
|
|
-
|
|
|
- nf_tables_chain_notify(&trans->ctx, NFT_MSG_NEWCHAIN);
|
|
|
- nft_trans_destroy(trans);
|
|
|
+ nf_tables_chain_notify(&trans->ctx, NFT_MSG_NEWCHAIN);
|
|
|
+ nft_trans_destroy(trans);
|
|
|
+ }
|
|
|
break;
|
|
|
case NFT_MSG_DELCHAIN:
|
|
|
nft_chain_del(trans->ctx.chain);
|
|
@@ -6471,7 +6504,7 @@ static int __nf_tables_abort(struct net *net)
|
|
|
case NFT_MSG_NEWCHAIN:
|
|
|
if (nft_trans_chain_update(trans)) {
|
|
|
free_percpu(nft_trans_chain_stats(trans));
|
|
|
-
|
|
|
+ kfree(nft_trans_chain_name(trans));
|
|
|
nft_trans_destroy(trans);
|
|
|
} else {
|
|
|
trans->ctx.table->use--;
|
|
@@ -6837,13 +6870,6 @@ int nft_validate_register_store(const struct nft_ctx *ctx,
|
|
|
err = nf_tables_check_loops(ctx, data->verdict.chain);
|
|
|
if (err < 0)
|
|
|
return err;
|
|
|
-
|
|
|
- if (ctx->chain->level + 1 >
|
|
|
- data->verdict.chain->level) {
|
|
|
- if (ctx->chain->level + 1 == NFT_JUMP_STACK_SIZE)
|
|
|
- return -EMLINK;
|
|
|
- data->verdict.chain->level = ctx->chain->level + 1;
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
return 0;
|