@@ -1056,6 +1056,9 @@ static int nft_flush_table(struct nft_ctx *ctx)
10561056 if (!nft_is_active_next (ctx -> net , chain ))
10571057 continue ;
10581058
1059+ if (nft_chain_is_bound (chain ))
1060+ continue ;
1061+
10591062 ctx -> chain = chain ;
10601063
10611064 err = nft_delrule_by_chain (ctx );
@@ -1098,6 +1101,9 @@ static int nft_flush_table(struct nft_ctx *ctx)
10981101 if (!nft_is_active_next (ctx -> net , chain ))
10991102 continue ;
11001103
1104+ if (nft_chain_is_bound (chain ))
1105+ continue ;
1106+
11011107 ctx -> chain = chain ;
11021108
11031109 err = nft_delchain (ctx );
@@ -1413,13 +1419,12 @@ static int nf_tables_fill_chain_info(struct sk_buff *skb, struct net *net,
14131419 lockdep_commit_lock_is_held (net ));
14141420 if (nft_dump_stats (skb , stats ))
14151421 goto nla_put_failure ;
1416-
1417- if ((chain -> flags & NFT_CHAIN_HW_OFFLOAD ) &&
1418- nla_put_be32 (skb , NFTA_CHAIN_FLAGS ,
1419- htonl (NFT_CHAIN_HW_OFFLOAD )))
1420- goto nla_put_failure ;
14211422 }
14221423
1424+ if (chain -> flags &&
1425+ nla_put_be32 (skb , NFTA_CHAIN_FLAGS , htonl (chain -> flags )))
1426+ goto nla_put_failure ;
1427+
14231428 if (nla_put_be32 (skb , NFTA_CHAIN_USE , htonl (chain -> use )))
14241429 goto nla_put_failure ;
14251430
@@ -1621,7 +1626,7 @@ static void nf_tables_chain_free_chain_rules(struct nft_chain *chain)
16211626 kvfree (chain -> rules_next );
16221627}
16231628
1624- static void nf_tables_chain_destroy (struct nft_ctx * ctx )
1629+ void nf_tables_chain_destroy (struct nft_ctx * ctx )
16251630{
16261631 struct nft_chain * chain = ctx -> chain ;
16271632 struct nft_hook * hook , * next ;
@@ -1928,6 +1933,8 @@ static int nft_chain_add(struct nft_table *table, struct nft_chain *chain)
19281933 return 0 ;
19291934}
19301935
1936+ static u64 chain_id ;
1937+
19311938static int nf_tables_addchain (struct nft_ctx * ctx , u8 family , u8 genmask ,
19321939 u8 policy , u32 flags )
19331940{
@@ -1936,6 +1943,7 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
19361943 struct nft_base_chain * basechain ;
19371944 struct nft_stats __percpu * stats ;
19381945 struct net * net = ctx -> net ;
1946+ char name [NFT_NAME_MAXLEN ];
19391947 struct nft_trans * trans ;
19401948 struct nft_chain * chain ;
19411949 struct nft_rule * * rules ;
@@ -1947,6 +1955,9 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
19471955 if (nla [NFTA_CHAIN_HOOK ]) {
19481956 struct nft_chain_hook hook ;
19491957
1958+ if (flags & NFT_CHAIN_BINDING )
1959+ return - EOPNOTSUPP ;
1960+
19501961 err = nft_chain_parse_hook (net , nla , & hook , family , true);
19511962 if (err < 0 )
19521963 return err ;
@@ -1976,16 +1987,33 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
19761987 return err ;
19771988 }
19781989 } else {
1990+ if (flags & NFT_CHAIN_BASE )
1991+ return - EINVAL ;
1992+ if (flags & NFT_CHAIN_HW_OFFLOAD )
1993+ return - EOPNOTSUPP ;
1994+
19791995 chain = kzalloc (sizeof (* chain ), GFP_KERNEL );
19801996 if (chain == NULL )
19811997 return - ENOMEM ;
1998+
1999+ chain -> flags = flags ;
19822000 }
19832001 ctx -> chain = chain ;
19842002
19852003 INIT_LIST_HEAD (& chain -> rules );
19862004 chain -> handle = nf_tables_alloc_handle (table );
19872005 chain -> table = table ;
1988- chain -> name = nla_strdup (nla [NFTA_CHAIN_NAME ], GFP_KERNEL );
2006+
2007+ if (nla [NFTA_CHAIN_NAME ]) {
2008+ chain -> name = nla_strdup (nla [NFTA_CHAIN_NAME ], GFP_KERNEL );
2009+ } else {
2010+ if (!(flags & NFT_CHAIN_BINDING ))
2011+ return - EINVAL ;
2012+
2013+ snprintf (name , sizeof (name ), "__chain%llu" , ++ chain_id );
2014+ chain -> name = kstrdup (name , GFP_KERNEL );
2015+ }
2016+
19892017 if (!chain -> name ) {
19902018 err = - ENOMEM ;
19912019 goto err1 ;
@@ -2976,8 +3004,7 @@ static void nf_tables_rule_destroy(const struct nft_ctx *ctx,
29763004 kfree (rule );
29773005}
29783006
2979- static void nf_tables_rule_release (const struct nft_ctx * ctx ,
2980- struct nft_rule * rule )
3007+ void nf_tables_rule_release (const struct nft_ctx * ctx , struct nft_rule * rule )
29813008{
29823009 nft_rule_expr_deactivate (ctx , rule , NFT_TRANS_RELEASE );
29833010 nf_tables_rule_destroy (ctx , rule );
@@ -3075,6 +3102,9 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
30753102 NL_SET_BAD_ATTR (extack , nla [NFTA_RULE_CHAIN ]);
30763103 return PTR_ERR (chain );
30773104 }
3105+ if (nft_chain_is_bound (chain ))
3106+ return - EOPNOTSUPP ;
3107+
30783108 } else if (nla [NFTA_RULE_CHAIN_ID ]) {
30793109 chain = nft_chain_lookup_byid (net , nla [NFTA_RULE_CHAIN_ID ]);
30803110 if (IS_ERR (chain )) {
@@ -3294,6 +3324,8 @@ static int nf_tables_delrule(struct net *net, struct sock *nlsk,
32943324 NL_SET_BAD_ATTR (extack , nla [NFTA_RULE_CHAIN ]);
32953325 return PTR_ERR (chain );
32963326 }
3327+ if (nft_chain_is_bound (chain ))
3328+ return - EOPNOTSUPP ;
32973329 }
32983330
32993331 nft_ctx_init (& ctx , net , skb , nlh , family , table , chain , nla );
@@ -5330,11 +5362,24 @@ static int nf_tables_newsetelem(struct net *net, struct sock *nlsk,
53305362 */
53315363void nft_data_hold (const struct nft_data * data , enum nft_data_types type )
53325364{
5365+ struct nft_chain * chain ;
5366+ struct nft_rule * rule ;
5367+
53335368 if (type == NFT_DATA_VERDICT ) {
53345369 switch (data -> verdict .code ) {
53355370 case NFT_JUMP :
53365371 case NFT_GOTO :
5337- data -> verdict .chain -> use ++ ;
5372+ chain = data -> verdict .chain ;
5373+ chain -> use ++ ;
5374+
5375+ if (!nft_chain_is_bound (chain ))
5376+ break ;
5377+
5378+ chain -> table -> use ++ ;
5379+ list_for_each_entry (rule , & chain -> rules , list )
5380+ chain -> use ++ ;
5381+
5382+ nft_chain_add (chain -> table , chain );
53385383 break ;
53395384 }
53405385 }
@@ -7474,7 +7519,7 @@ static void nft_obj_del(struct nft_object *obj)
74747519 list_del_rcu (& obj -> list );
74757520}
74767521
7477- static void nft_chain_del (struct nft_chain * chain )
7522+ void nft_chain_del (struct nft_chain * chain )
74787523{
74797524 struct nft_table * table = chain -> table ;
74807525
@@ -7825,6 +7870,10 @@ static int __nf_tables_abort(struct net *net, bool autoload)
78257870 kfree (nft_trans_chain_name (trans ));
78267871 nft_trans_destroy (trans );
78277872 } else {
7873+ if (nft_chain_is_bound (trans -> ctx .chain )) {
7874+ nft_trans_destroy (trans );
7875+ break ;
7876+ }
78287877 trans -> ctx .table -> use -- ;
78297878 nft_chain_del (trans -> ctx .chain );
78307879 nf_tables_unregister_hook (trans -> ctx .net ,
@@ -8321,10 +8370,23 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
83218370
83228371static void nft_verdict_uninit (const struct nft_data * data )
83238372{
8373+ struct nft_chain * chain ;
8374+ struct nft_rule * rule ;
8375+
83248376 switch (data -> verdict .code ) {
83258377 case NFT_JUMP :
83268378 case NFT_GOTO :
8327- data -> verdict .chain -> use -- ;
8379+ chain = data -> verdict .chain ;
8380+ chain -> use -- ;
8381+
8382+ if (!nft_chain_is_bound (chain ))
8383+ break ;
8384+
8385+ chain -> table -> use -- ;
8386+ list_for_each_entry (rule , & chain -> rules , list )
8387+ chain -> use -- ;
8388+
8389+ nft_chain_del (chain );
83288390 break ;
83298391 }
83308392}
0 commit comments