2828
2929#define NFT_MODULE_AUTOLOAD_LIMIT (MODULE_NAME_LEN - sizeof("nft-expr-255-"))
3030
31+ unsigned int nf_tables_net_id __read_mostly ;
32+ EXPORT_SYMBOL_GPL (nf_tables_net_id );
33+
3134static LIST_HEAD (nf_tables_expressions );
3235static LIST_HEAD (nf_tables_objects );
3336static LIST_HEAD (nf_tables_flowtables );
@@ -3593,8 +3596,8 @@ static struct nft_set *nft_set_lookup_byid(const struct net *net,
35933596 const struct nft_table * table ,
35943597 const struct nlattr * nla , u8 genmask )
35953598{
3596- struct nft_trans * trans ;
35973599 u32 id = ntohl (nla_get_be32 (nla ));
3600+ struct nft_trans * trans ;
35983601
35993602 list_for_each_entry (trans , & net -> nft .commit_list , list ) {
36003603 if (trans -> msg_type == NFT_MSG_NEWSET ) {
@@ -3837,8 +3840,8 @@ static void nf_tables_set_notify(const struct nft_ctx *ctx,
38373840 const struct nft_set * set , int event ,
38383841 gfp_t gfp_flags )
38393842{
3840- u32 portid = ctx -> portid ;
38413843 struct sk_buff * skb ;
3844+ u32 portid = ctx -> portid ;
38423845 u16 flags = 0 ;
38433846 int err ;
38443847
@@ -4786,7 +4789,7 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
47864789 rcu_read_lock ();
47874790 cb -> seq = READ_ONCE (net -> nft .base_seq );
47884791
4789- list_for_each_entry_rcu (table , & net -> nft .tables , list ) {
4792+ list_for_each_entry_rcu (table , & net -> nft .tables , list ) {
47904793 if (dump_ctx -> ctx .family != NFPROTO_UNSPEC &&
47914794 dump_ctx -> ctx .family != table -> family )
47924795 continue ;
@@ -7955,14 +7958,31 @@ static void nft_set_commit_update(struct list_head *set_update_list)
79557958 }
79567959}
79577960
7961+ static unsigned int nft_gc_seq_begin (struct nftables_pernet * nft_net )
7962+ {
7963+ unsigned int gc_seq ;
7964+
7965+ /* Bump gc counter, it becomes odd, this is the busy mark. */
7966+ gc_seq = READ_ONCE (nft_net -> gc_seq );
7967+ WRITE_ONCE (nft_net -> gc_seq , ++ gc_seq );
7968+
7969+ return gc_seq ;
7970+ }
7971+
7972+ static void nft_gc_seq_end (struct nftables_pernet * nft_net , unsigned int gc_seq )
7973+ {
7974+ WRITE_ONCE (nft_net -> gc_seq , ++ gc_seq );
7975+ }
7976+
79587977static int nf_tables_commit (struct net * net , struct sk_buff * skb )
79597978{
7979+ struct nftables_pernet * nft_net = nft_pernet (net );
79607980 struct nft_trans * trans , * next ;
7981+ unsigned int base_seq , gc_seq ;
79617982 LIST_HEAD (set_update_list );
79627983 struct nft_trans_elem * te ;
79637984 struct nft_chain * chain ;
79647985 struct nft_table * table ;
7965- unsigned int base_seq ;
79667986 LIST_HEAD (adl );
79677987 int err ;
79687988
@@ -8013,6 +8033,8 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
80138033
80148034 WRITE_ONCE (net -> nft .base_seq , base_seq );
80158035
8036+ gc_seq = nft_gc_seq_begin (nft_net );
8037+
80168038 /* step 3. Start new generation, rules_gen_X now in use. */
80178039 net -> nft .gencursor = nft_gencursor_next (net );
80188040
@@ -8391,18 +8413,25 @@ static void nf_tables_cleanup(struct net *net)
83918413static int nf_tables_abort (struct net * net , struct sk_buff * skb ,
83928414 enum nfnl_abort_action action )
83938415{
8394- int ret = __nf_tables_abort (net , action );
8416+ struct nftables_pernet * nft_net = nft_pernet (net );
8417+ unsigned int gc_seq ;
8418+ int ret ;
83958419
8420+ gc_seq = nft_gc_seq_begin (nft_net );
8421+ ret = __nf_tables_abort (net , action );
8422+ nft_gc_seq_end (nft_net , gc_seq );
83968423 mutex_unlock (& net -> nft_commit_mutex );
83978424
83988425 return ret ;
83998426}
84008427
84018428static bool nf_tables_valid_genid (struct net * net , u32 genid )
84028429{
8430+ struct nftables_pernet * nft_net = nft_pernet (net );
84038431 bool genid_ok ;
84048432
84058433 mutex_lock (& net -> nft_commit_mutex );
8434+ nft_net -> tstamp = get_jiffies_64 ();
84068435
84078436 genid_ok = genid == 0 || net -> nft .base_seq == genid ;
84088437 if (!genid_ok )
@@ -9012,13 +9041,16 @@ static void __nft_release_tables(struct net *net)
90129041
90139042static int __net_init nf_tables_init_net (struct net * net )
90149043{
9044+ struct nftables_pernet * nft_net = nft_pernet (net );
9045+
90159046 INIT_LIST_HEAD (& net -> nft .tables );
90169047 INIT_LIST_HEAD (& net -> nft .commit_list );
90179048 INIT_LIST_HEAD (& net -> nft_module_list );
90189049 INIT_LIST_HEAD (& net -> nft_notify_list );
90199050 mutex_init (& net -> nft_commit_mutex );
90209051 net -> nft .base_seq = 1 ;
90219052 net -> nft .validate_state = NFT_VALIDATE_SKIP ;
9053+ nft_net -> gc_seq = 0 ;
90229054
90239055 return 0 ;
90249056}
@@ -9032,11 +9064,21 @@ static void __net_exit nf_tables_pre_exit_net(struct net *net)
90329064
90339065static void __net_exit nf_tables_exit_net (struct net * net )
90349066{
9067+ struct nftables_pernet * nft_net = nft_pernet (net );
9068+ unsigned int gc_seq ;
9069+
90359070 mutex_lock (& net -> nft_commit_mutex );
9071+
9072+ gc_seq = nft_gc_seq_begin (nft_net );
9073+
90369074 if (!list_empty (& net -> nft .commit_list ) ||
90379075 !list_empty (& net -> nft_module_list ))
90389076 __nf_tables_abort (net , NFNL_ABORT_NONE );
9077+
90399078 __nft_release_tables (net );
9079+
9080+ nft_gc_seq_end (nft_net , gc_seq );
9081+
90409082 mutex_unlock (& net -> nft_commit_mutex );
90419083 WARN_ON_ONCE (!list_empty (& net -> nft .tables ));
90429084 WARN_ON_ONCE (!list_empty (& net -> nft_module_list ));
0 commit comments