@@ -222,12 +222,18 @@ static int nft_netdev_register_hooks(struct net *net,
222
222
}
223
223
224
224
static void nft_netdev_unregister_hooks (struct net * net ,
225
- struct list_head * hook_list )
225
+ struct list_head * hook_list ,
226
+ bool release_netdev )
226
227
{
227
- struct nft_hook * hook ;
228
+ struct nft_hook * hook , * next ;
228
229
229
- list_for_each_entry (hook , hook_list , list )
230
+ list_for_each_entry_safe (hook , next , hook_list , list ) {
230
231
nf_unregister_net_hook (net , & hook -> ops );
232
+ if (release_netdev ) {
233
+ list_del (& hook -> list );
234
+ kfree_rcu (hook , rcu );
235
+ }
236
+ }
231
237
}
232
238
233
239
static int nf_tables_register_hook (struct net * net ,
@@ -253,9 +259,10 @@ static int nf_tables_register_hook(struct net *net,
253
259
return nf_register_net_hook (net , & basechain -> ops );
254
260
}
255
261
256
- static void nf_tables_unregister_hook (struct net * net ,
257
- const struct nft_table * table ,
258
- struct nft_chain * chain )
262
+ static void __nf_tables_unregister_hook (struct net * net ,
263
+ const struct nft_table * table ,
264
+ struct nft_chain * chain ,
265
+ bool release_netdev )
259
266
{
260
267
struct nft_base_chain * basechain ;
261
268
const struct nf_hook_ops * ops ;
@@ -270,11 +277,19 @@ static void nf_tables_unregister_hook(struct net *net,
270
277
return basechain -> type -> ops_unregister (net , ops );
271
278
272
279
if (nft_base_chain_netdev (table -> family , basechain -> ops .hooknum ))
273
- nft_netdev_unregister_hooks (net , & basechain -> hook_list );
280
+ nft_netdev_unregister_hooks (net , & basechain -> hook_list ,
281
+ release_netdev );
274
282
else
275
283
nf_unregister_net_hook (net , & basechain -> ops );
276
284
}
277
285
286
+ static void nf_tables_unregister_hook (struct net * net ,
287
+ const struct nft_table * table ,
288
+ struct nft_chain * chain )
289
+ {
290
+ return __nf_tables_unregister_hook (net , table , chain , false);
291
+ }
292
+
278
293
static void nft_trans_commit_list_add_tail (struct net * net , struct nft_trans * trans )
279
294
{
280
295
struct nftables_pernet * nft_net = nft_pernet (net );
@@ -4246,6 +4261,9 @@ static int nft_set_desc_concat_parse(const struct nlattr *attr,
4246
4261
u32 len ;
4247
4262
int err ;
4248
4263
4264
+ if (desc -> field_count >= ARRAY_SIZE (desc -> field_len ))
4265
+ return - E2BIG ;
4266
+
4249
4267
err = nla_parse_nested_deprecated (tb , NFTA_SET_FIELD_MAX , attr ,
4250
4268
nft_concat_policy , NULL );
4251
4269
if (err < 0 )
@@ -4255,9 +4273,8 @@ static int nft_set_desc_concat_parse(const struct nlattr *attr,
4255
4273
return - EINVAL ;
4256
4274
4257
4275
len = ntohl (nla_get_be32 (tb [NFTA_SET_FIELD_LEN ]));
4258
-
4259
- if (len * BITS_PER_BYTE / 32 > NFT_REG32_COUNT )
4260
- return - E2BIG ;
4276
+ if (!len || len > U8_MAX )
4277
+ return - EINVAL ;
4261
4278
4262
4279
desc -> field_len [desc -> field_count ++ ] = len ;
4263
4280
@@ -4268,7 +4285,8 @@ static int nft_set_desc_concat(struct nft_set_desc *desc,
4268
4285
const struct nlattr * nla )
4269
4286
{
4270
4287
struct nlattr * attr ;
4271
- int rem , err ;
4288
+ u32 num_regs = 0 ;
4289
+ int rem , err , i ;
4272
4290
4273
4291
nla_for_each_nested (attr , nla , rem ) {
4274
4292
if (nla_type (attr ) != NFTA_LIST_ELEM )
@@ -4279,6 +4297,12 @@ static int nft_set_desc_concat(struct nft_set_desc *desc,
4279
4297
return err ;
4280
4298
}
4281
4299
4300
+ for (i = 0 ; i < desc -> field_count ; i ++ )
4301
+ num_regs += DIV_ROUND_UP (desc -> field_len [i ], sizeof (u32 ));
4302
+
4303
+ if (num_regs > NFT_REG32_COUNT )
4304
+ return - E2BIG ;
4305
+
4282
4306
return 0 ;
4283
4307
}
4284
4308
@@ -7298,13 +7322,25 @@ static void nft_unregister_flowtable_hook(struct net *net,
7298
7322
FLOW_BLOCK_UNBIND );
7299
7323
}
7300
7324
7301
- static void nft_unregister_flowtable_net_hooks (struct net * net ,
7302
- struct list_head * hook_list )
7325
+ static void __nft_unregister_flowtable_net_hooks (struct net * net ,
7326
+ struct list_head * hook_list ,
7327
+ bool release_netdev )
7303
7328
{
7304
- struct nft_hook * hook ;
7329
+ struct nft_hook * hook , * next ;
7305
7330
7306
- list_for_each_entry (hook , hook_list , list )
7331
+ list_for_each_entry_safe (hook , next , hook_list , list ) {
7307
7332
nf_unregister_net_hook (net , & hook -> ops );
7333
+ if (release_netdev ) {
7334
+ list_del (& hook -> list );
7335
+ kfree_rcu (hook );
7336
+ }
7337
+ }
7338
+ }
7339
+
7340
+ static void nft_unregister_flowtable_net_hooks (struct net * net ,
7341
+ struct list_head * hook_list )
7342
+ {
7343
+ __nft_unregister_flowtable_net_hooks (net , hook_list , false);
7308
7344
}
7309
7345
7310
7346
static int nft_register_flowtable_net_hooks (struct net * net ,
@@ -9746,9 +9782,10 @@ static void __nft_release_hook(struct net *net, struct nft_table *table)
9746
9782
struct nft_chain * chain ;
9747
9783
9748
9784
list_for_each_entry (chain , & table -> chains , list )
9749
- nf_tables_unregister_hook (net , table , chain );
9785
+ __nf_tables_unregister_hook (net , table , chain , true );
9750
9786
list_for_each_entry (flowtable , & table -> flowtables , list )
9751
- nft_unregister_flowtable_net_hooks (net , & flowtable -> hook_list );
9787
+ __nft_unregister_flowtable_net_hooks (net , & flowtable -> hook_list ,
9788
+ true);
9752
9789
}
9753
9790
9754
9791
static void __nft_release_hooks (struct net * net )
@@ -9887,7 +9924,11 @@ static int __net_init nf_tables_init_net(struct net *net)
9887
9924
9888
9925
static void __net_exit nf_tables_pre_exit_net (struct net * net )
9889
9926
{
9927
+ struct nftables_pernet * nft_net = nft_pernet (net );
9928
+
9929
+ mutex_lock (& nft_net -> commit_mutex );
9890
9930
__nft_release_hooks (net );
9931
+ mutex_unlock (& nft_net -> commit_mutex );
9891
9932
}
9892
9933
9893
9934
static void __net_exit nf_tables_exit_net (struct net * net )
0 commit comments