@@ -3841,9 +3841,9 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
3841
3841
3842
3842
nla_nest_end (skb , nest );
3843
3843
3844
- if (set -> expr ) {
3844
+ if (set -> num_exprs == 1 ) {
3845
3845
nest = nla_nest_start_noflag (skb , NFTA_SET_EXPR );
3846
- if (nf_tables_fill_expr_info (skb , set -> expr ) < 0 )
3846
+ if (nf_tables_fill_expr_info (skb , set -> exprs [ 0 ] ) < 0 )
3847
3847
goto nla_put_failure ;
3848
3848
3849
3849
nla_nest_end (skb , nest );
@@ -4279,6 +4279,8 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
4279
4279
err = PTR_ERR (expr );
4280
4280
goto err_set_alloc_name ;
4281
4281
}
4282
+ set -> exprs [0 ] = expr ;
4283
+ set -> num_exprs ++ ;
4282
4284
}
4283
4285
4284
4286
udata = NULL ;
@@ -4296,7 +4298,6 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
4296
4298
set -> dtype = dtype ;
4297
4299
set -> objtype = objtype ;
4298
4300
set -> dlen = desc .dlen ;
4299
- set -> expr = expr ;
4300
4301
set -> flags = flags ;
4301
4302
set -> size = desc .size ;
4302
4303
set -> policy = policy ;
@@ -4325,8 +4326,8 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
4325
4326
err_set_trans :
4326
4327
ops -> destroy (set );
4327
4328
err_set_init :
4328
- if ( expr )
4329
- nft_expr_destroy (& ctx , expr );
4329
+ for ( i = 0 ; i < set -> num_exprs ; i ++ )
4330
+ nft_expr_destroy (& ctx , set -> exprs [ i ] );
4330
4331
err_set_alloc_name :
4331
4332
kfree (set -> name );
4332
4333
err_set_name :
@@ -4336,11 +4337,13 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
4336
4337
4337
4338
static void nft_set_destroy (const struct nft_ctx * ctx , struct nft_set * set )
4338
4339
{
4340
+ int i ;
4341
+
4339
4342
if (WARN_ON (set -> use > 0 ))
4340
4343
return ;
4341
4344
4342
- if ( set -> expr )
4343
- nft_expr_destroy (ctx , set -> expr );
4345
+ for ( i = 0 ; i < set -> num_exprs ; i ++ )
4346
+ nft_expr_destroy (ctx , set -> exprs [ i ] );
4344
4347
4345
4348
set -> ops -> destroy (set );
4346
4349
kfree (set -> name );
@@ -5139,17 +5142,46 @@ static void nf_tables_set_elem_destroy(const struct nft_ctx *ctx,
5139
5142
kfree (elem );
5140
5143
}
5141
5144
5145
+ static int nft_set_elem_expr_clone (const struct nft_ctx * ctx ,
5146
+ struct nft_set * set ,
5147
+ struct nft_expr * expr_array [])
5148
+ {
5149
+ struct nft_expr * expr ;
5150
+ int err , i , k ;
5151
+
5152
+ for (i = 0 ; i < set -> num_exprs ; i ++ ) {
5153
+ expr = kzalloc (set -> exprs [i ]-> ops -> size , GFP_KERNEL );
5154
+ if (!expr )
5155
+ goto err_expr ;
5156
+
5157
+ err = nft_expr_clone (expr , set -> exprs [i ]);
5158
+ if (err < 0 ) {
5159
+ nft_expr_destroy (ctx , expr );
5160
+ goto err_expr ;
5161
+ }
5162
+ expr_array [i ] = expr ;
5163
+ }
5164
+
5165
+ return 0 ;
5166
+
5167
+ err_expr :
5168
+ for (k = i - 1 ; k >= 0 ; k ++ )
5169
+ nft_expr_destroy (ctx , expr_array [i ]);
5170
+
5171
+ return - ENOMEM ;
5172
+ }
5173
+
5142
5174
static int nft_add_set_elem (struct nft_ctx * ctx , struct nft_set * set ,
5143
5175
const struct nlattr * attr , u32 nlmsg_flags )
5144
5176
{
5177
+ struct nft_expr * expr_array [NFT_SET_EXPR_MAX ] = {};
5145
5178
struct nlattr * nla [NFTA_SET_ELEM_MAX + 1 ];
5146
5179
u8 genmask = nft_genmask_next (ctx -> net );
5147
5180
struct nft_set_ext_tmpl tmpl ;
5148
5181
struct nft_set_ext * ext , * ext2 ;
5149
5182
struct nft_set_elem elem ;
5150
5183
struct nft_set_binding * binding ;
5151
5184
struct nft_object * obj = NULL ;
5152
- struct nft_expr * expr = NULL ;
5153
5185
struct nft_userdata * udata ;
5154
5186
struct nft_data_desc desc ;
5155
5187
enum nft_registers dreg ;
@@ -5158,7 +5190,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
5158
5190
u64 timeout ;
5159
5191
u64 expiration ;
5160
5192
u8 ulen ;
5161
- int err ;
5193
+ int err , i ;
5162
5194
5163
5195
err = nla_parse_nested_deprecated (nla , NFTA_SET_ELEM_MAX , attr ,
5164
5196
nft_set_elem_policy , NULL );
@@ -5216,23 +5248,27 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
5216
5248
return err ;
5217
5249
}
5218
5250
5219
- if (nla [NFTA_SET_ELEM_EXPR ] != NULL ) {
5251
+ if (nla [NFTA_SET_ELEM_EXPR ]) {
5252
+ struct nft_expr * expr ;
5253
+
5254
+ if (set -> num_exprs != 1 )
5255
+ return - EOPNOTSUPP ;
5256
+
5220
5257
expr = nft_set_elem_expr_alloc (ctx , set ,
5221
5258
nla [NFTA_SET_ELEM_EXPR ]);
5222
5259
if (IS_ERR (expr ))
5223
5260
return PTR_ERR (expr );
5224
5261
5225
- err = - EOPNOTSUPP ;
5226
- if (set -> expr && set -> expr -> ops != expr -> ops )
5227
- goto err_set_elem_expr ;
5228
- } else if (set -> expr ) {
5229
- expr = kzalloc (set -> expr -> ops -> size , GFP_KERNEL );
5230
- if (!expr )
5231
- return - ENOMEM ;
5262
+ expr_array [0 ] = expr ;
5232
5263
5233
- err = nft_expr_clone ( expr , set -> expr );
5234
- if ( err < 0 )
5264
+ if ( set -> exprs [ 0 ] && set -> exprs [ 0 ] -> ops != expr -> ops ) {
5265
+ err = - EOPNOTSUPP ;
5235
5266
goto err_set_elem_expr ;
5267
+ }
5268
+ } else if (set -> num_exprs > 0 ) {
5269
+ err = nft_set_elem_expr_clone (ctx , set , expr_array );
5270
+ if (err < 0 )
5271
+ goto err_set_elem_expr_clone ;
5236
5272
}
5237
5273
5238
5274
err = nft_setelem_parse_key (ctx , set , & elem .key .val ,
@@ -5257,9 +5293,9 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
5257
5293
nft_set_ext_add (& tmpl , NFT_SET_EXT_TIMEOUT );
5258
5294
}
5259
5295
5260
- if (expr )
5296
+ if (set -> num_exprs == 1 )
5261
5297
nft_set_ext_add_length (& tmpl , NFT_SET_EXT_EXPR ,
5262
- expr -> ops -> size );
5298
+ expr_array [ 0 ] -> ops -> size );
5263
5299
5264
5300
if (nla [NFTA_SET_ELEM_OBJREF ] != NULL ) {
5265
5301
if (!(set -> flags & NFT_SET_OBJECT )) {
@@ -5341,10 +5377,12 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
5341
5377
* nft_set_ext_obj (ext ) = obj ;
5342
5378
obj -> use ++ ;
5343
5379
}
5344
- if (expr ) {
5380
+ if (set -> num_exprs == 1 ) {
5381
+ struct nft_expr * expr = expr_array [0 ];
5382
+
5345
5383
memcpy (nft_set_ext_expr (ext ), expr , expr -> ops -> size );
5346
5384
kfree (expr );
5347
- expr = NULL ;
5385
+ expr_array [ 0 ] = NULL ;
5348
5386
}
5349
5387
5350
5388
trans = nft_trans_elem_alloc (ctx , NFT_MSG_NEWSETELEM , set );
@@ -5406,9 +5444,9 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
5406
5444
err_parse_key :
5407
5445
nft_data_release (& elem .key .val , NFT_DATA_VALUE );
5408
5446
err_set_elem_expr :
5409
- if ( expr != NULL )
5410
- nft_expr_destroy (ctx , expr );
5411
-
5447
+ for ( i = 0 ; i < set -> num_exprs && expr_array [ i ]; i ++ )
5448
+ nft_expr_destroy (ctx , expr_array [ i ] );
5449
+ err_set_elem_expr_clone :
5412
5450
return err ;
5413
5451
}
5414
5452
0 commit comments