|
@@ -1598,7 +1598,6 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
|
|
struct nft_base_chain *basechain;
|
|
struct nft_base_chain *basechain;
|
|
struct nft_stats *stats = NULL;
|
|
struct nft_stats *stats = NULL;
|
|
struct nft_chain_hook hook;
|
|
struct nft_chain_hook hook;
|
|
- const struct nlattr *name;
|
|
|
|
struct nf_hook_ops *ops;
|
|
struct nf_hook_ops *ops;
|
|
struct nft_trans *trans;
|
|
struct nft_trans *trans;
|
|
int err;
|
|
int err;
|
|
@@ -1646,12 +1645,11 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
|
|
return PTR_ERR(stats);
|
|
return PTR_ERR(stats);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ err = -ENOMEM;
|
|
trans = nft_trans_alloc(ctx, NFT_MSG_NEWCHAIN,
|
|
trans = nft_trans_alloc(ctx, NFT_MSG_NEWCHAIN,
|
|
sizeof(struct nft_trans_chain));
|
|
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_stats(trans) = stats;
|
|
nft_trans_chain_update(trans) = true;
|
|
nft_trans_chain_update(trans) = true;
|
|
@@ -1661,19 +1659,37 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
|
|
else
|
|
else
|
|
nft_trans_chain_policy(trans) = -1;
|
|
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);
|
|
list_add_tail(&trans->list, &ctx->net->nft.commit_list);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
|
|
+err:
|
|
|
|
+ free_percpu(stats);
|
|
|
|
+ kfree(trans);
|
|
|
|
+ return err;
|
|
}
|
|
}
|
|
|
|
|
|
static int nf_tables_newchain(struct net *net, struct sock *nlsk,
|
|
static int nf_tables_newchain(struct net *net, struct sock *nlsk,
|