@@ -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+
43914444static 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,
46534683err_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 );
46584688err_set_init :
46594689 kfree (set -> name );
0 commit comments