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
@@ -4783,7 +4786,7 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
47834786 rcu_read_lock ();
47844787 cb -> seq = READ_ONCE (net -> nft .base_seq );
47854788
4786- list_for_each_entry_rcu (table , & net -> nft .tables , list ) {
4789+ list_for_each_entry_rcu (table , & net -> nft .tables , list ) {
47874790 if (dump_ctx -> ctx .family != NFPROTO_UNSPEC &&
47884791 dump_ctx -> ctx .family != table -> family )
47894792 continue ;
@@ -7957,14 +7960,31 @@ static void nft_set_commit_update(struct list_head *set_update_list)
79577960 }
79587961}
79597962
7963+ static unsigned int nft_gc_seq_begin (struct nftables_pernet * nft_net )
7964+ {
7965+ unsigned int gc_seq ;
7966+
7967+ /* Bump gc counter, it becomes odd, this is the busy mark. */
7968+ gc_seq = READ_ONCE (nft_net -> gc_seq );
7969+ WRITE_ONCE (nft_net -> gc_seq , ++ gc_seq );
7970+
7971+ return gc_seq ;
7972+ }
7973+
7974+ static void nft_gc_seq_end (struct nftables_pernet * nft_net , unsigned int gc_seq )
7975+ {
7976+ WRITE_ONCE (nft_net -> gc_seq , ++ gc_seq );
7977+ }
7978+
79607979static int nf_tables_commit (struct net * net , struct sk_buff * skb )
79617980{
7981+ struct nftables_pernet * nft_net = nft_pernet (net );
79627982 struct nft_trans * trans , * next ;
7983+ unsigned int base_seq , gc_seq ;
79637984 LIST_HEAD (set_update_list );
79647985 struct nft_trans_elem * te ;
79657986 struct nft_chain * chain ;
79667987 struct nft_table * table ;
7967- unsigned int base_seq ;
79687988 LIST_HEAD (adl );
79697989 int err ;
79707990
@@ -8015,6 +8035,8 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
80158035
80168036 WRITE_ONCE (net -> nft .base_seq , base_seq );
80178037
8038+ gc_seq = nft_gc_seq_begin (nft_net );
8039+
80188040 /* step 3. Start new generation, rules_gen_X now in use. */
80198041 net -> nft .gencursor = nft_gencursor_next (net );
80208042
@@ -8393,18 +8415,25 @@ static void nf_tables_cleanup(struct net *net)
83938415static int nf_tables_abort (struct net * net , struct sk_buff * skb ,
83948416 enum nfnl_abort_action action )
83958417{
8396- int ret = __nf_tables_abort (net , action );
8418+ struct nftables_pernet * nft_net = nft_pernet (net );
8419+ unsigned int gc_seq ;
8420+ int ret ;
83978421
8422+ gc_seq = nft_gc_seq_begin (nft_net );
8423+ ret = __nf_tables_abort (net , action );
8424+ nft_gc_seq_end (nft_net , gc_seq );
83988425 mutex_unlock (& net -> nft_commit_mutex );
83998426
84008427 return ret ;
84018428}
84028429
84038430static bool nf_tables_valid_genid (struct net * net , u32 genid )
84048431{
8432+ struct nftables_pernet * nft_net = nft_pernet (net );
84058433 bool genid_ok ;
84068434
84078435 mutex_lock (& net -> nft_commit_mutex );
8436+ nft_net -> tstamp = get_jiffies_64 ();
84088437
84098438 genid_ok = genid == 0 || net -> nft .base_seq == genid ;
84108439 if (!genid_ok )
@@ -9014,13 +9043,16 @@ static void __nft_release_tables(struct net *net)
90149043
90159044static int __net_init nf_tables_init_net (struct net * net )
90169045{
9046+ struct nftables_pernet * nft_net = nft_pernet (net );
9047+
90179048 INIT_LIST_HEAD (& net -> nft .tables );
90189049 INIT_LIST_HEAD (& net -> nft .commit_list );
90199050 INIT_LIST_HEAD (& net -> nft_module_list );
90209051 INIT_LIST_HEAD (& net -> nft_notify_list );
90219052 mutex_init (& net -> nft_commit_mutex );
90229053 net -> nft .base_seq = 1 ;
90239054 net -> nft .validate_state = NFT_VALIDATE_SKIP ;
9055+ nft_net -> gc_seq = 0 ;
90249056
90259057 return 0 ;
90269058}
@@ -9034,11 +9066,21 @@ static void __net_exit nf_tables_pre_exit_net(struct net *net)
90349066
90359067static void __net_exit nf_tables_exit_net (struct net * net )
90369068{
9069+ struct nftables_pernet * nft_net = nft_pernet (net );
9070+ unsigned int gc_seq ;
9071+
90379072 mutex_lock (& net -> nft_commit_mutex );
9073+
9074+ gc_seq = nft_gc_seq_begin (nft_net );
9075+
90389076 if (!list_empty (& net -> nft .commit_list ) ||
90399077 !list_empty (& net -> nft_module_list ))
90409078 __nf_tables_abort (net , NFNL_ABORT_NONE );
9079+
90419080 __nft_release_tables (net );
9081+
9082+ nft_gc_seq_end (nft_net , gc_seq );
9083+
90429084 mutex_unlock (& net -> nft_commit_mutex );
90439085 WARN_ON_ONCE (!list_empty (& net -> nft .tables ));
90449086 WARN_ON_ONCE (!list_empty (& net -> nft_module_list ));
0 commit comments