@@ -37,10 +37,16 @@ enum {
37
37
NFT_VALIDATE_DO ,
38
38
};
39
39
40
+ static struct rhltable nft_objname_ht ;
41
+
40
42
static u32 nft_chain_hash (const void * data , u32 len , u32 seed );
41
43
static u32 nft_chain_hash_obj (const void * data , u32 len , u32 seed );
42
44
static int nft_chain_hash_cmp (struct rhashtable_compare_arg * , const void * );
43
45
46
+ static u32 nft_objname_hash (const void * data , u32 len , u32 seed );
47
+ static u32 nft_objname_hash_obj (const void * data , u32 len , u32 seed );
48
+ static int nft_objname_hash_cmp (struct rhashtable_compare_arg * , const void * );
49
+
44
50
static const struct rhashtable_params nft_chain_ht_params = {
45
51
.head_offset = offsetof(struct nft_chain , rhlhead ),
46
52
.key_offset = offsetof(struct nft_chain , name ),
@@ -51,6 +57,15 @@ static const struct rhashtable_params nft_chain_ht_params = {
51
57
.automatic_shrinking = true,
52
58
};
53
59
60
+ static const struct rhashtable_params nft_objname_ht_params = {
61
+ .head_offset = offsetof(struct nft_object , rhlhead ),
62
+ .key_offset = offsetof(struct nft_object , key ),
63
+ .hashfn = nft_objname_hash ,
64
+ .obj_hashfn = nft_objname_hash_obj ,
65
+ .obj_cmpfn = nft_objname_hash_cmp ,
66
+ .automatic_shrinking = true,
67
+ };
68
+
54
69
static void nft_validate_state_update (struct net * net , u8 new_validate_state )
55
70
{
56
71
switch (net -> nft .validate_state ) {
@@ -814,6 +829,34 @@ static int nft_chain_hash_cmp(struct rhashtable_compare_arg *arg,
814
829
return strcmp (chain -> name , name );
815
830
}
816
831
832
+ static u32 nft_objname_hash (const void * data , u32 len , u32 seed )
833
+ {
834
+ const struct nft_object_hash_key * k = data ;
835
+
836
+ seed ^= hash_ptr (k -> table , 32 );
837
+
838
+ return jhash (k -> name , strlen (k -> name ), seed );
839
+ }
840
+
841
+ static u32 nft_objname_hash_obj (const void * data , u32 len , u32 seed )
842
+ {
843
+ const struct nft_object * obj = data ;
844
+
845
+ return nft_objname_hash (& obj -> key , 0 , seed );
846
+ }
847
+
848
+ static int nft_objname_hash_cmp (struct rhashtable_compare_arg * arg ,
849
+ const void * ptr )
850
+ {
851
+ const struct nft_object_hash_key * k = arg -> key ;
852
+ const struct nft_object * obj = ptr ;
853
+
854
+ if (obj -> key .table != k -> table )
855
+ return -1 ;
856
+
857
+ return strcmp (obj -> key .name , k -> name );
858
+ }
859
+
817
860
static int nf_tables_newtable (struct net * net , struct sock * nlsk ,
818
861
struct sk_buff * skb , const struct nlmsghdr * nlh ,
819
862
const struct nlattr * const nla [],
@@ -1070,7 +1113,7 @@ nft_chain_lookup_byhandle(const struct nft_table *table, u64 handle, u8 genmask)
1070
1113
return ERR_PTR (- ENOENT );
1071
1114
}
1072
1115
1073
- static bool lockdep_commit_lock_is_held (struct net * net )
1116
+ static bool lockdep_commit_lock_is_held (const struct net * net )
1074
1117
{
1075
1118
#ifdef CONFIG_PROVE_LOCKING
1076
1119
return lockdep_is_held (& net -> nft .commit_mutex );
@@ -4386,7 +4429,8 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
4386
4429
err = - EINVAL ;
4387
4430
goto err2 ;
4388
4431
}
4389
- obj = nft_obj_lookup (ctx -> table , nla [NFTA_SET_ELEM_OBJREF ],
4432
+ obj = nft_obj_lookup (ctx -> net , ctx -> table ,
4433
+ nla [NFTA_SET_ELEM_OBJREF ],
4390
4434
set -> objtype , genmask );
4391
4435
if (IS_ERR (obj )) {
4392
4436
err = PTR_ERR (obj );
@@ -4819,18 +4863,36 @@ void nft_unregister_obj(struct nft_object_type *obj_type)
4819
4863
}
4820
4864
EXPORT_SYMBOL_GPL (nft_unregister_obj );
4821
4865
4822
- struct nft_object * nft_obj_lookup (const struct nft_table * table ,
4866
+ struct nft_object * nft_obj_lookup (const struct net * net ,
4867
+ const struct nft_table * table ,
4823
4868
const struct nlattr * nla , u32 objtype ,
4824
4869
u8 genmask )
4825
4870
{
4871
+ struct nft_object_hash_key k = { .table = table };
4872
+ char search [NFT_OBJ_MAXNAMELEN ];
4873
+ struct rhlist_head * tmp , * list ;
4826
4874
struct nft_object * obj ;
4827
4875
4828
- list_for_each_entry_rcu (obj , & table -> objects , list ) {
4829
- if (!nla_strcmp (nla , obj -> key .name ) &&
4830
- objtype == obj -> ops -> type -> type &&
4831
- nft_active_genmask (obj , genmask ))
4876
+ nla_strlcpy (search , nla , sizeof (search ));
4877
+ k .name = search ;
4878
+
4879
+ WARN_ON_ONCE (!rcu_read_lock_held () &&
4880
+ !lockdep_commit_lock_is_held (net ));
4881
+
4882
+ rcu_read_lock ();
4883
+ list = rhltable_lookup (& nft_objname_ht , & k , nft_objname_ht_params );
4884
+ if (!list )
4885
+ goto out ;
4886
+
4887
+ rhl_for_each_entry_rcu (obj , tmp , list , rhlhead ) {
4888
+ if (objtype == obj -> ops -> type -> type &&
4889
+ nft_active_genmask (obj , genmask )) {
4890
+ rcu_read_unlock ();
4832
4891
return obj ;
4892
+ }
4833
4893
}
4894
+ out :
4895
+ rcu_read_unlock ();
4834
4896
return ERR_PTR (- ENOENT );
4835
4897
}
4836
4898
EXPORT_SYMBOL_GPL (nft_obj_lookup );
@@ -4988,7 +5050,7 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk,
4988
5050
}
4989
5051
4990
5052
objtype = ntohl (nla_get_be32 (nla [NFTA_OBJ_TYPE ]));
4991
- obj = nft_obj_lookup (table , nla [NFTA_OBJ_NAME ], objtype , genmask );
5053
+ obj = nft_obj_lookup (net , table , nla [NFTA_OBJ_NAME ], objtype , genmask );
4992
5054
if (IS_ERR (obj )) {
4993
5055
err = PTR_ERR (obj );
4994
5056
if (err != - ENOENT ) {
@@ -5027,9 +5089,18 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk,
5027
5089
if (err < 0 )
5028
5090
goto err3 ;
5029
5091
5092
+ err = rhltable_insert (& nft_objname_ht , & obj -> rhlhead ,
5093
+ nft_objname_ht_params );
5094
+ if (err < 0 )
5095
+ goto err4 ;
5096
+
5030
5097
list_add_tail_rcu (& obj -> list , & table -> objects );
5031
5098
table -> use ++ ;
5032
5099
return 0 ;
5100
+ err4 :
5101
+ /* queued in transaction log */
5102
+ INIT_LIST_HEAD (& obj -> list );
5103
+ return err ;
5033
5104
err3 :
5034
5105
kfree (obj -> key .name );
5035
5106
err2 :
@@ -5215,7 +5286,7 @@ static int nf_tables_getobj(struct net *net, struct sock *nlsk,
5215
5286
}
5216
5287
5217
5288
objtype = ntohl (nla_get_be32 (nla [NFTA_OBJ_TYPE ]));
5218
- obj = nft_obj_lookup (table , nla [NFTA_OBJ_NAME ], objtype , genmask );
5289
+ obj = nft_obj_lookup (net , table , nla [NFTA_OBJ_NAME ], objtype , genmask );
5219
5290
if (IS_ERR (obj )) {
5220
5291
NL_SET_BAD_ATTR (extack , nla [NFTA_OBJ_NAME ]);
5221
5292
return PTR_ERR (obj );
@@ -5280,7 +5351,7 @@ static int nf_tables_delobj(struct net *net, struct sock *nlsk,
5280
5351
obj = nft_obj_lookup_byhandle (table , attr , objtype , genmask );
5281
5352
} else {
5282
5353
attr = nla [NFTA_OBJ_NAME ];
5283
- obj = nft_obj_lookup (table , attr , objtype , genmask );
5354
+ obj = nft_obj_lookup (net , table , attr , objtype , genmask );
5284
5355
}
5285
5356
5286
5357
if (IS_ERR (obj )) {
@@ -6406,6 +6477,7 @@ static void nf_tables_commit_chain(struct net *net, struct nft_chain *chain)
6406
6477
6407
6478
static void nft_obj_del (struct nft_object * obj )
6408
6479
{
6480
+ rhltable_remove (& nft_objname_ht , & obj -> rhlhead , nft_objname_ht_params );
6409
6481
list_del_rcu (& obj -> list );
6410
6482
}
6411
6483
@@ -6721,7 +6793,7 @@ static int __nf_tables_abort(struct net *net)
6721
6793
break ;
6722
6794
case NFT_MSG_NEWOBJ :
6723
6795
trans -> ctx .table -> use -- ;
6724
- list_del_rcu ( & nft_trans_obj (trans )-> list );
6796
+ nft_obj_del ( nft_trans_obj (trans ));
6725
6797
break ;
6726
6798
case NFT_MSG_DELOBJ :
6727
6799
trans -> ctx .table -> use ++ ;
@@ -7397,12 +7469,18 @@ static int __init nf_tables_module_init(void)
7397
7469
if (err < 0 )
7398
7470
goto err3 ;
7399
7471
7472
+ err = rhltable_init (& nft_objname_ht , & nft_objname_ht_params );
7473
+ if (err < 0 )
7474
+ goto err4 ;
7475
+
7400
7476
/* must be last */
7401
7477
err = nfnetlink_subsys_register (& nf_tables_subsys );
7402
7478
if (err < 0 )
7403
- goto err4 ;
7479
+ goto err5 ;
7404
7480
7405
7481
return err ;
7482
+ err5 :
7483
+ rhltable_destroy (& nft_objname_ht );
7406
7484
err4 :
7407
7485
unregister_netdevice_notifier (& nf_tables_flowtable_notifier );
7408
7486
err3 :
@@ -7422,6 +7500,7 @@ static void __exit nf_tables_module_exit(void)
7422
7500
unregister_pernet_subsys (& nf_tables_net_ops );
7423
7501
cancel_work_sync (& trans_destroy_work );
7424
7502
rcu_barrier ();
7503
+ rhltable_destroy (& nft_objname_ht );
7425
7504
nf_tables_core_module_exit ();
7426
7505
}
7427
7506
0 commit comments