Skip to content

Commit 767d121

Browse files
committedFeb 3, 2021
netfilter: nftables: fix possible UAF over chains from packet path in netns
Although hooks are released via call_rcu(), chain and rule objects are immediately released while packets are still walking over these bits. This patch adds the .pre_exit callback which is invoked before synchronize_rcu() in the netns framework to stay safe. Remove a comment which is not valid anymore since the core does not use synchronize_net() anymore since 8c873e2 ("netfilter: core: free hooks with call_rcu"). Suggested-by: Florian Westphal <fw@strlen.de> Fixes: df05ef8 ("netfilter: nf_tables: release objects on netns destruction") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
1 parent a3005b0 commit 767d121

File tree

1 file changed

+19
-6
lines changed

1 file changed

+19
-6
lines changed
 

‎net/netfilter/nf_tables_api.c

+19-6
Original file line numberDiff line numberDiff line change
@@ -8949,6 +8949,17 @@ int __nft_release_basechain(struct nft_ctx *ctx)
89498949
}
89508950
EXPORT_SYMBOL_GPL(__nft_release_basechain);
89518951

8952+
static void __nft_release_hooks(struct net *net)
8953+
{
8954+
struct nft_table *table;
8955+
struct nft_chain *chain;
8956+
8957+
list_for_each_entry(table, &net->nft.tables, list) {
8958+
list_for_each_entry(chain, &table->chains, list)
8959+
nf_tables_unregister_hook(net, table, chain);
8960+
}
8961+
}
8962+
89528963
static void __nft_release_tables(struct net *net)
89538964
{
89548965
struct nft_flowtable *flowtable, *nf;
@@ -8964,10 +8975,6 @@ static void __nft_release_tables(struct net *net)
89648975

89658976
list_for_each_entry_safe(table, nt, &net->nft.tables, list) {
89668977
ctx.family = table->family;
8967-
8968-
list_for_each_entry(chain, &table->chains, list)
8969-
nf_tables_unregister_hook(net, table, chain);
8970-
/* No packets are walking on these chains anymore. */
89718978
ctx.table = table;
89728979
list_for_each_entry(chain, &table->chains, list) {
89738980
ctx.chain = chain;
@@ -9016,6 +9023,11 @@ static int __net_init nf_tables_init_net(struct net *net)
90169023
return 0;
90179024
}
90189025

9026+
static void __net_exit nf_tables_pre_exit_net(struct net *net)
9027+
{
9028+
__nft_release_hooks(net);
9029+
}
9030+
90199031
static void __net_exit nf_tables_exit_net(struct net *net)
90209032
{
90219033
mutex_lock(&net->nft.commit_mutex);
@@ -9029,8 +9041,9 @@ static void __net_exit nf_tables_exit_net(struct net *net)
90299041
}
90309042

90319043
static struct pernet_operations nf_tables_net_ops = {
9032-
.init = nf_tables_init_net,
9033-
.exit = nf_tables_exit_net,
9044+
.init = nf_tables_init_net,
9045+
.pre_exit = nf_tables_pre_exit_net,
9046+
.exit = nf_tables_exit_net,
90349047
};
90359048

90369049
static int __init nf_tables_module_init(void)

0 commit comments

Comments
 (0)
Please sign in to comment.