summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorInseo An <y0un9sa@gmail.com>2026-02-17 15:14:40 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-02-27 01:59:39 +0300
commitdbd0af8083dd201f07c49110b2ee93710abdff28 (patch)
treefca29ca3db7e64deadb4bfd82ed0bbf158068951
parent50422613185d505201167e8bdd2f2700790d5db6 (diff)
downloadlinux-dbd0af8083dd201f07c49110b2ee93710abdff28.tar.xz
netfilter: nf_tables: fix use-after-free in nf_tables_addchain()
[ Upstream commit 71e99ee20fc3f662555118cf1159443250647533 ] nf_tables_addchain() publishes the chain to table->chains via list_add_tail_rcu() (in nft_chain_add()) before registering hooks. If nf_tables_register_hook() then fails, the error path calls nft_chain_del() (list_del_rcu()) followed by nf_tables_chain_destroy() with no RCU grace period in between. This creates two use-after-free conditions: 1) Control-plane: nf_tables_dump_chains() traverses table->chains under rcu_read_lock(). A concurrent dump can still be walking the chain when the error path frees it. 2) Packet path: for NFPROTO_INET, nf_register_net_hook() briefly installs the IPv4 hook before IPv6 registration fails. Packets entering nft_do_chain() via the transient IPv4 hook can still be dereferencing chain->blob_gen_X when the error path frees the chain. Add synchronize_rcu() between nft_chain_del() and the chain destroy so that all RCU readers -- both dump threads and in-flight packet evaluation -- have finished before the chain is freed. Fixes: 91c7b38dc9f0 ("netfilter: nf_tables: use new transaction infrastructure to handle chain") Signed-off-by: Inseo An <y0un9sa@gmail.com> Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--net/netfilter/nf_tables_api.c1
1 files changed, 1 insertions, 0 deletions
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 9051f2c3595a..df367638cdef 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -2822,6 +2822,7 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 policy,
err_register_hook:
nft_chain_del(chain);
+ synchronize_rcu();
err_chain_add:
nft_trans_destroy(trans);
err_trans: