2222#include <linux/netfilter_bridge/ebtables.h>
2323#include <linux/netfilter_arp/arp_tables.h>
2424#include <net/netfilter/nf_tables.h>
25+ #include <net/netns/generic.h>
2526
2627struct nft_xt {
2728 struct list_head head ;
@@ -43,6 +44,20 @@ struct nft_xt_match_priv {
4344 void * info ;
4445};
4546
47+ struct nft_compat_net {
48+ struct list_head nft_target_list ;
49+ struct list_head nft_match_list ;
50+ };
51+
52+ static unsigned int nft_compat_net_id __read_mostly ;
53+ static struct nft_expr_type nft_match_type ;
54+ static struct nft_expr_type nft_target_type ;
55+
56+ static struct nft_compat_net * nft_compat_pernet (struct net * net )
57+ {
58+ return net_generic (net , nft_compat_net_id );
59+ }
60+
4661static bool nft_xt_put (struct nft_xt * xt )
4762{
4863 if (refcount_dec_and_test (& xt -> refcnt )) {
@@ -734,10 +749,6 @@ static const struct nfnetlink_subsystem nfnl_compat_subsys = {
734749 .cb = nfnl_nft_compat_cb ,
735750};
736751
737- static LIST_HEAD (nft_match_list );
738-
739- static struct nft_expr_type nft_match_type ;
740-
741752static bool nft_match_cmp (const struct xt_match * match ,
742753 const char * name , u32 rev , u32 family )
743754{
@@ -749,6 +760,7 @@ static const struct nft_expr_ops *
749760nft_match_select_ops (const struct nft_ctx * ctx ,
750761 const struct nlattr * const tb [])
751762{
763+ struct nft_compat_net * cn ;
752764 struct nft_xt * nft_match ;
753765 struct xt_match * match ;
754766 unsigned int matchsize ;
@@ -765,8 +777,10 @@ nft_match_select_ops(const struct nft_ctx *ctx,
765777 rev = ntohl (nla_get_be32 (tb [NFTA_MATCH_REV ]));
766778 family = ctx -> family ;
767779
780+ cn = nft_compat_pernet (ctx -> net );
781+
768782 /* Re-use the existing match if it's already loaded. */
769- list_for_each_entry (nft_match , & nft_match_list , head ) {
783+ list_for_each_entry (nft_match , & cn -> nft_match_list , head ) {
770784 struct xt_match * match = nft_match -> ops .data ;
771785
772786 if (nft_match_cmp (match , mt_name , rev , family ))
@@ -810,7 +824,7 @@ nft_match_select_ops(const struct nft_ctx *ctx,
810824
811825 nft_match -> ops .size = matchsize ;
812826
813- list_add (& nft_match -> head , & nft_match_list );
827+ list_add (& nft_match -> head , & cn -> nft_match_list );
814828
815829 return & nft_match -> ops ;
816830err :
@@ -826,10 +840,6 @@ static struct nft_expr_type nft_match_type __read_mostly = {
826840 .owner = THIS_MODULE ,
827841};
828842
829- static LIST_HEAD (nft_target_list );
830-
831- static struct nft_expr_type nft_target_type ;
832-
833843static bool nft_target_cmp (const struct xt_target * tg ,
834844 const char * name , u32 rev , u32 family )
835845{
@@ -841,6 +851,7 @@ static const struct nft_expr_ops *
841851nft_target_select_ops (const struct nft_ctx * ctx ,
842852 const struct nlattr * const tb [])
843853{
854+ struct nft_compat_net * cn ;
844855 struct nft_xt * nft_target ;
845856 struct xt_target * target ;
846857 char * tg_name ;
@@ -861,8 +872,9 @@ nft_target_select_ops(const struct nft_ctx *ctx,
861872 strcmp (tg_name , "standard" ) == 0 )
862873 return ERR_PTR (- EINVAL );
863874
875+ cn = nft_compat_pernet (ctx -> net );
864876 /* Re-use the existing target if it's already loaded. */
865- list_for_each_entry (nft_target , & nft_target_list , head ) {
877+ list_for_each_entry (nft_target , & cn -> nft_target_list , head ) {
866878 struct xt_target * target = nft_target -> ops .data ;
867879
868880 if (!target -> target )
@@ -907,7 +919,7 @@ nft_target_select_ops(const struct nft_ctx *ctx,
907919 else
908920 nft_target -> ops .eval = nft_target_eval_xt ;
909921
910- list_add (& nft_target -> head , & nft_target_list );
922+ list_add (& nft_target -> head , & cn -> nft_target_list );
911923
912924 return & nft_target -> ops ;
913925err :
@@ -923,13 +935,74 @@ static struct nft_expr_type nft_target_type __read_mostly = {
923935 .owner = THIS_MODULE ,
924936};
925937
938+ static int __net_init nft_compat_init_net (struct net * net )
939+ {
940+ struct nft_compat_net * cn = nft_compat_pernet (net );
941+
942+ INIT_LIST_HEAD (& cn -> nft_target_list );
943+ INIT_LIST_HEAD (& cn -> nft_match_list );
944+
945+ return 0 ;
946+ }
947+
948+ static void __net_exit nft_compat_exit_net (struct net * net )
949+ {
950+ struct nft_compat_net * cn = nft_compat_pernet (net );
951+ struct nft_xt * xt , * next ;
952+
953+ if (list_empty (& cn -> nft_match_list ) &&
954+ list_empty (& cn -> nft_target_list ))
955+ return ;
956+
957+ /* If there was an error that caused nft_xt expr to not be initialized
958+ * fully and noone else requested the same expression later, the lists
959+ * contain 0-refcount entries that still hold module reference.
960+ *
961+ * Clean them here.
962+ */
963+ mutex_lock (& net -> nft .commit_mutex );
964+ list_for_each_entry_safe (xt , next , & cn -> nft_target_list , head ) {
965+ struct xt_target * target = xt -> ops .data ;
966+
967+ list_del_init (& xt -> head );
968+
969+ if (refcount_read (& xt -> refcnt ))
970+ continue ;
971+ module_put (target -> me );
972+ kfree (xt );
973+ }
974+
975+ list_for_each_entry_safe (xt , next , & cn -> nft_match_list , head ) {
976+ struct xt_match * match = xt -> ops .data ;
977+
978+ list_del_init (& xt -> head );
979+
980+ if (refcount_read (& xt -> refcnt ))
981+ continue ;
982+ module_put (match -> me );
983+ kfree (xt );
984+ }
985+ mutex_unlock (& net -> nft .commit_mutex );
986+ }
987+
988+ static struct pernet_operations nft_compat_net_ops = {
989+ .init = nft_compat_init_net ,
990+ .exit = nft_compat_exit_net ,
991+ .id = & nft_compat_net_id ,
992+ .size = sizeof (struct nft_compat_net ),
993+ };
994+
926995static int __init nft_compat_module_init (void )
927996{
928997 int ret ;
929998
999+ ret = register_pernet_subsys (& nft_compat_net_ops );
1000+ if (ret < 0 )
1001+ goto err_target ;
1002+
9301003 ret = nft_register_expr (& nft_match_type );
9311004 if (ret < 0 )
932- return ret ;
1005+ goto err_pernet ;
9331006
9341007 ret = nft_register_expr (& nft_target_type );
9351008 if (ret < 0 )
@@ -942,45 +1015,21 @@ static int __init nft_compat_module_init(void)
9421015 }
9431016
9441017 return ret ;
945-
9461018err_target :
9471019 nft_unregister_expr (& nft_target_type );
9481020err_match :
9491021 nft_unregister_expr (& nft_match_type );
1022+ err_pernet :
1023+ unregister_pernet_subsys (& nft_compat_net_ops );
9501024 return ret ;
9511025}
9521026
9531027static void __exit nft_compat_module_exit (void )
9541028{
955- struct nft_xt * xt , * next ;
956-
957- /* list should be empty here, it can be non-empty only in case there
958- * was an error that caused nft_xt expr to not be initialized fully
959- * and noone else requested the same expression later.
960- *
961- * In this case, the lists contain 0-refcount entries that still
962- * hold module reference.
963- */
964- list_for_each_entry_safe (xt , next , & nft_target_list , head ) {
965- struct xt_target * target = xt -> ops .data ;
966-
967- if (WARN_ON_ONCE (refcount_read (& xt -> refcnt )))
968- continue ;
969- module_put (target -> me );
970- kfree (xt );
971- }
972-
973- list_for_each_entry_safe (xt , next , & nft_match_list , head ) {
974- struct xt_match * match = xt -> ops .data ;
975-
976- if (WARN_ON_ONCE (refcount_read (& xt -> refcnt )))
977- continue ;
978- module_put (match -> me );
979- kfree (xt );
980- }
9811029 nfnetlink_subsys_unregister (& nfnl_compat_subsys );
9821030 nft_unregister_expr (& nft_target_type );
9831031 nft_unregister_expr (& nft_match_type );
1032+ unregister_pernet_subsys (& nft_compat_net_ops );
9841033}
9851034
9861035MODULE_ALIAS_NFNL_SUBSYS (NFNL_SUBSYS_NFT_COMPAT );
0 commit comments