Skip to content

Commit a8fe415

Browse files
committed
netfilter: nf_tables: add function to create set stateful expressions
Add a helper function to allocate and initialize the stateful expressions that are defined in a set. This patch allows to reuse this code from the set update path, to check that type of the update matches the existing set in the kernel. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
1 parent bed4a63 commit a8fe415

File tree

1 file changed

+68
-38
lines changed

1 file changed

+68
-38
lines changed

net/netfilter/nf_tables_api.c

Lines changed: 68 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4388,21 +4388,74 @@ static int nf_tables_set_desc_parse(struct nft_set_desc *desc,
43884388
return err;
43894389
}
43904390

4391+
static int nft_set_expr_alloc(struct nft_ctx *ctx, struct nft_set *set,
4392+
const struct nlattr * const *nla,
4393+
struct nft_expr **exprs, int *num_exprs,
4394+
u32 flags)
4395+
{
4396+
struct nft_expr *expr;
4397+
int err, i;
4398+
4399+
if (nla[NFTA_SET_EXPR]) {
4400+
expr = nft_set_elem_expr_alloc(ctx, set, nla[NFTA_SET_EXPR]);
4401+
if (IS_ERR(expr)) {
4402+
err = PTR_ERR(expr);
4403+
goto err_set_expr_alloc;
4404+
}
4405+
exprs[0] = expr;
4406+
(*num_exprs)++;
4407+
} else if (nla[NFTA_SET_EXPRESSIONS]) {
4408+
struct nlattr *tmp;
4409+
int left;
4410+
4411+
if (!(flags & NFT_SET_EXPR)) {
4412+
err = -EINVAL;
4413+
goto err_set_expr_alloc;
4414+
}
4415+
i = 0;
4416+
nla_for_each_nested(tmp, nla[NFTA_SET_EXPRESSIONS], left) {
4417+
if (i == NFT_SET_EXPR_MAX) {
4418+
err = -E2BIG;
4419+
goto err_set_expr_alloc;
4420+
}
4421+
if (nla_type(tmp) != NFTA_LIST_ELEM) {
4422+
err = -EINVAL;
4423+
goto err_set_expr_alloc;
4424+
}
4425+
expr = nft_set_elem_expr_alloc(ctx, set, tmp);
4426+
if (IS_ERR(expr)) {
4427+
err = PTR_ERR(expr);
4428+
goto err_set_expr_alloc;
4429+
}
4430+
exprs[i++] = expr;
4431+
(*num_exprs)++;
4432+
}
4433+
}
4434+
4435+
return 0;
4436+
4437+
err_set_expr_alloc:
4438+
for (i = 0; i < *num_exprs; i++)
4439+
nft_expr_destroy(ctx, exprs[i]);
4440+
4441+
return err;
4442+
}
4443+
43914444
static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
43924445
const struct nlattr * const nla[])
43934446
{
43944447
struct netlink_ext_ack *extack = info->extack;
43954448
u8 genmask = nft_genmask_next(info->net);
43964449
u8 family = info->nfmsg->nfgen_family;
43974450
const struct nft_set_ops *ops;
4398-
struct nft_expr *expr = NULL;
43994451
struct net *net = info->net;
44004452
struct nft_set_desc desc;
44014453
struct nft_table *table;
44024454
unsigned char *udata;
44034455
struct nft_set *set;
44044456
struct nft_ctx ctx;
44054457
size_t alloc_size;
4458+
int num_exprs = 0;
44064459
char *name;
44074460
int err, i;
44084461
u16 udlen;
@@ -4529,13 +4582,22 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
45294582
return PTR_ERR(set);
45304583
}
45314584
} else {
4585+
struct nft_expr *exprs[NFT_SET_EXPR_MAX] = {};
4586+
45324587
if (info->nlh->nlmsg_flags & NLM_F_EXCL) {
45334588
NL_SET_BAD_ATTR(extack, nla[NFTA_SET_NAME]);
45344589
return -EEXIST;
45354590
}
45364591
if (info->nlh->nlmsg_flags & NLM_F_REPLACE)
45374592
return -EOPNOTSUPP;
45384593

4594+
err = nft_set_expr_alloc(&ctx, set, nla, exprs, &num_exprs, flags);
4595+
if (err < 0)
4596+
return err;
4597+
4598+
for (i = 0; i < num_exprs; i++)
4599+
nft_expr_destroy(&ctx, exprs[i]);
4600+
45394601
return 0;
45404602
}
45414603

@@ -4603,43 +4665,11 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
46034665
if (err < 0)
46044666
goto err_set_init;
46054667

4606-
if (nla[NFTA_SET_EXPR]) {
4607-
expr = nft_set_elem_expr_alloc(&ctx, set, nla[NFTA_SET_EXPR]);
4608-
if (IS_ERR(expr)) {
4609-
err = PTR_ERR(expr);
4610-
goto err_set_expr_alloc;
4611-
}
4612-
set->exprs[0] = expr;
4613-
set->num_exprs++;
4614-
} else if (nla[NFTA_SET_EXPRESSIONS]) {
4615-
struct nft_expr *expr;
4616-
struct nlattr *tmp;
4617-
int left;
4618-
4619-
if (!(flags & NFT_SET_EXPR)) {
4620-
err = -EINVAL;
4621-
goto err_set_expr_alloc;
4622-
}
4623-
i = 0;
4624-
nla_for_each_nested(tmp, nla[NFTA_SET_EXPRESSIONS], left) {
4625-
if (i == NFT_SET_EXPR_MAX) {
4626-
err = -E2BIG;
4627-
goto err_set_expr_alloc;
4628-
}
4629-
if (nla_type(tmp) != NFTA_LIST_ELEM) {
4630-
err = -EINVAL;
4631-
goto err_set_expr_alloc;
4632-
}
4633-
expr = nft_set_elem_expr_alloc(&ctx, set, tmp);
4634-
if (IS_ERR(expr)) {
4635-
err = PTR_ERR(expr);
4636-
goto err_set_expr_alloc;
4637-
}
4638-
set->exprs[i++] = expr;
4639-
set->num_exprs++;
4640-
}
4641-
}
4668+
err = nft_set_expr_alloc(&ctx, set, nla, set->exprs, &num_exprs, flags);
4669+
if (err < 0)
4670+
goto err_set_destroy;
46424671

4672+
set->num_exprs = num_exprs;
46434673
set->handle = nf_tables_alloc_handle(table);
46444674

46454675
err = nft_trans_set_add(&ctx, NFT_MSG_NEWSET, set);
@@ -4653,7 +4683,7 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
46534683
err_set_expr_alloc:
46544684
for (i = 0; i < set->num_exprs; i++)
46554685
nft_expr_destroy(&ctx, set->exprs[i]);
4656-
4686+
err_set_destroy:
46574687
ops->destroy(set);
46584688
err_set_init:
46594689
kfree(set->name);

0 commit comments

Comments
 (0)