@@ -561,6 +561,58 @@ static int nft_trans_set_add(const struct nft_ctx *ctx, int msg_type,
561561 return __nft_trans_set_add (ctx , msg_type , set , NULL );
562562}
563563
564+ static void nft_setelem_data_deactivate (const struct net * net ,
565+ const struct nft_set * set ,
566+ struct nft_set_elem * elem );
567+
568+ static int nft_mapelem_deactivate (const struct nft_ctx * ctx ,
569+ struct nft_set * set ,
570+ const struct nft_set_iter * iter ,
571+ struct nft_set_elem * elem )
572+ {
573+ nft_setelem_data_deactivate (ctx -> net , set , elem );
574+
575+ return 0 ;
576+ }
577+
578+ struct nft_set_elem_catchall {
579+ struct list_head list ;
580+ struct rcu_head rcu ;
581+ void * elem ;
582+ };
583+
584+ static void nft_map_catchall_deactivate (const struct nft_ctx * ctx ,
585+ struct nft_set * set )
586+ {
587+ u8 genmask = nft_genmask_next (ctx -> net );
588+ struct nft_set_elem_catchall * catchall ;
589+ struct nft_set_elem elem ;
590+ struct nft_set_ext * ext ;
591+
592+ list_for_each_entry (catchall , & set -> catchall_list , list ) {
593+ ext = nft_set_elem_ext (set , catchall -> elem );
594+ if (!nft_set_elem_active (ext , genmask ))
595+ continue ;
596+
597+ elem .priv = catchall -> elem ;
598+ nft_setelem_data_deactivate (ctx -> net , set , & elem );
599+ break ;
600+ }
601+ }
602+
603+ static void nft_map_deactivate (const struct nft_ctx * ctx , struct nft_set * set )
604+ {
605+ struct nft_set_iter iter = {
606+ .genmask = nft_genmask_next (ctx -> net ),
607+ .fn = nft_mapelem_deactivate ,
608+ };
609+
610+ set -> ops -> walk (ctx , set , & iter );
611+ WARN_ON_ONCE (iter .err );
612+
613+ nft_map_catchall_deactivate (ctx , set );
614+ }
615+
564616static int nft_delset (const struct nft_ctx * ctx , struct nft_set * set )
565617{
566618 int err ;
@@ -569,6 +621,9 @@ static int nft_delset(const struct nft_ctx *ctx, struct nft_set *set)
569621 if (err < 0 )
570622 return err ;
571623
624+ if (set -> flags & (NFT_SET_MAP | NFT_SET_OBJECT ))
625+ nft_map_deactivate (ctx , set );
626+
572627 nft_deactivate_next (ctx -> net , set );
573628 ctx -> table -> use -- ;
574629
@@ -3438,12 +3493,6 @@ int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set,
34383493 return 0 ;
34393494}
34403495
3441- struct nft_set_elem_catchall {
3442- struct list_head list ;
3443- struct rcu_head rcu ;
3444- void * elem ;
3445- };
3446-
34473496int nft_set_catchall_validate (const struct nft_ctx * ctx , struct nft_set * set )
34483497{
34493498 u8 genmask = nft_genmask_next (ctx -> net );
@@ -4774,7 +4823,7 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
47744823 for (i = 0 ; i < set -> num_exprs ; i ++ )
47754824 nft_expr_destroy (& ctx , set -> exprs [i ]);
47764825err_set_destroy :
4777- ops -> destroy (set );
4826+ ops -> destroy (& ctx , set );
47784827err_set_init :
47794828 kfree (set -> name );
47804829err_set_name :
@@ -4789,7 +4838,7 @@ static void nft_set_catchall_destroy(const struct nft_ctx *ctx,
47894838
47904839 list_for_each_entry_safe (catchall , next , & set -> catchall_list , list ) {
47914840 list_del_rcu (& catchall -> list );
4792- nft_set_elem_destroy ( set , catchall -> elem , true );
4841+ nf_tables_set_elem_destroy ( ctx , set , catchall -> elem );
47934842 kfree_rcu (catchall , rcu );
47944843 }
47954844}
@@ -4804,7 +4853,7 @@ static void nft_set_destroy(const struct nft_ctx *ctx, struct nft_set *set)
48044853 for (i = 0 ; i < set -> num_exprs ; i ++ )
48054854 nft_expr_destroy (ctx , set -> exprs [i ]);
48064855
4807- set -> ops -> destroy (set );
4856+ set -> ops -> destroy (ctx , set );
48084857 nft_set_catchall_destroy (ctx , set );
48094858 kfree (set -> name );
48104859 kvfree (set );
@@ -4969,10 +5018,60 @@ static void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
49695018 }
49705019}
49715020
5021+ static void nft_setelem_data_activate (const struct net * net ,
5022+ const struct nft_set * set ,
5023+ struct nft_set_elem * elem );
5024+
5025+ static int nft_mapelem_activate (const struct nft_ctx * ctx ,
5026+ struct nft_set * set ,
5027+ const struct nft_set_iter * iter ,
5028+ struct nft_set_elem * elem )
5029+ {
5030+ nft_setelem_data_activate (ctx -> net , set , elem );
5031+
5032+ return 0 ;
5033+ }
5034+
5035+ static void nft_map_catchall_activate (const struct nft_ctx * ctx ,
5036+ struct nft_set * set )
5037+ {
5038+ u8 genmask = nft_genmask_next (ctx -> net );
5039+ struct nft_set_elem_catchall * catchall ;
5040+ struct nft_set_elem elem ;
5041+ struct nft_set_ext * ext ;
5042+
5043+ list_for_each_entry (catchall , & set -> catchall_list , list ) {
5044+ ext = nft_set_elem_ext (set , catchall -> elem );
5045+ if (!nft_set_elem_active (ext , genmask ))
5046+ continue ;
5047+
5048+ elem .priv = catchall -> elem ;
5049+ nft_setelem_data_activate (ctx -> net , set , & elem );
5050+ break ;
5051+ }
5052+ }
5053+
5054+ static void nft_map_activate (const struct nft_ctx * ctx , struct nft_set * set )
5055+ {
5056+ struct nft_set_iter iter = {
5057+ .genmask = nft_genmask_next (ctx -> net ),
5058+ .fn = nft_mapelem_activate ,
5059+ };
5060+
5061+ set -> ops -> walk (ctx , set , & iter );
5062+ WARN_ON_ONCE (iter .err );
5063+
5064+ nft_map_catchall_activate (ctx , set );
5065+ }
5066+
49725067void nf_tables_activate_set (const struct nft_ctx * ctx , struct nft_set * set )
49735068{
4974- if (nft_set_is_anonymous (set ))
5069+ if (nft_set_is_anonymous (set )) {
5070+ if (set -> flags & (NFT_SET_MAP | NFT_SET_OBJECT ))
5071+ nft_map_activate (ctx , set );
5072+
49755073 nft_clear (ctx -> net , set );
5074+ }
49765075
49775076 set -> use ++ ;
49785077}
@@ -4993,13 +5092,20 @@ void nf_tables_deactivate_set(const struct nft_ctx *ctx, struct nft_set *set,
49935092 set -> use -- ;
49945093 break ;
49955094 case NFT_TRANS_PREPARE :
4996- if (nft_set_is_anonymous (set ))
4997- nft_deactivate_next (ctx -> net , set );
5095+ if (nft_set_is_anonymous (set )) {
5096+ if (set -> flags & (NFT_SET_MAP | NFT_SET_OBJECT ))
5097+ nft_map_deactivate (ctx , set );
49985098
5099+ nft_deactivate_next (ctx -> net , set );
5100+ }
49995101 set -> use -- ;
50005102 return ;
50015103 case NFT_TRANS_ABORT :
50025104 case NFT_TRANS_RELEASE :
5105+ if (nft_set_is_anonymous (set ) &&
5106+ set -> flags & (NFT_SET_MAP | NFT_SET_OBJECT ))
5107+ nft_map_deactivate (ctx , set );
5108+
50035109 set -> use -- ;
50045110 fallthrough ;
50055111 default :
@@ -5774,6 +5880,7 @@ static void nft_set_elem_expr_destroy(const struct nft_ctx *ctx,
57745880 __nft_set_elem_expr_destroy (ctx , expr );
57755881}
57765882
5883+ /* Drop references and destroy. Called from gc, dynset and abort path. */
57775884void nft_set_elem_destroy (const struct nft_set * set , void * elem ,
57785885 bool destroy_expr )
57795886{
@@ -5795,11 +5902,11 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem,
57955902}
57965903EXPORT_SYMBOL_GPL (nft_set_elem_destroy );
57975904
5798- /* Only called from commit path, nft_setelem_data_deactivate() already deals
5799- * with the refcounting from the preparation phase .
5905+ /* Destroy element. References have been already dropped in the preparation
5906+ * path via nft_setelem_data_deactivate() .
58005907 */
5801- static void nf_tables_set_elem_destroy (const struct nft_ctx * ctx ,
5802- const struct nft_set * set , void * elem )
5908+ void nf_tables_set_elem_destroy (const struct nft_ctx * ctx ,
5909+ const struct nft_set * set , void * elem )
58035910{
58045911 struct nft_set_ext * ext = nft_set_elem_ext (set , elem );
58055912
@@ -6432,7 +6539,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
64326539 if (obj )
64336540 obj -> use -- ;
64346541err_elem_userdata :
6435- nf_tables_set_elem_destroy ( ctx , set , elem .priv );
6542+ nft_set_elem_destroy ( set , elem .priv , true );
64366543err_parse_data :
64376544 if (nla [NFTA_SET_ELEM_DATA ] != NULL )
64386545 nft_data_release (& elem .data .val , desc .type );
@@ -9508,6 +9615,9 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
95089615 case NFT_MSG_DESTROYSET :
95099616 trans -> ctx .table -> use ++ ;
95109617 nft_clear (trans -> ctx .net , nft_trans_set (trans ));
9618+ if (nft_trans_set (trans )-> flags & (NFT_SET_MAP | NFT_SET_OBJECT ))
9619+ nft_map_activate (& trans -> ctx , nft_trans_set (trans ));
9620+
95119621 nft_trans_destroy (trans );
95129622 break ;
95139623 case NFT_MSG_NEWSETELEM :
@@ -10274,6 +10384,9 @@ static void __nft_release_table(struct net *net, struct nft_table *table)
1027410384 list_for_each_entry_safe (set , ns , & table -> sets , list ) {
1027510385 list_del (& set -> list );
1027610386 table -> use -- ;
10387+ if (set -> flags & (NFT_SET_MAP | NFT_SET_OBJECT ))
10388+ nft_map_deactivate (& ctx , set );
10389+
1027710390 nft_set_destroy (& ctx , set );
1027810391 }
1027910392 list_for_each_entry_safe (obj , ne , & table -> objects , list ) {
0 commit comments