From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D6CC533F8B2; Sat, 17 Oct 2026 16:20:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792254022; cv=none; b=DtZJtNUkWiudLha2BEOQSolcYi+VTUqzJgdhH5jqDbAkxE0Ur9PFbzsbFgkhI9ud1Xh1T9tmE6z9cSLTdRpRqzztQeFQPReAxyGDnjaKGcEFH7BqiU4ZbrXuWmmgmvxFtDpkn43xjkgwNwdgXPkQ75GuDcB7aJOv8GNq57tP9+4= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792254022; c=relaxed/simple; bh=zUxUTze5xZV+uvx7hOyfCHNM9Vu6jmku1RHmhUqlFiA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=UgwRNai4Qni+BwOPZ76uDNoJ1wOgWv2tEztIjLpxSKqoT6kk/OMwCfuWzFDpIIdLKjlTJixpBbDN+viD2oYvxtLUzDwB46xcLS1rJnR9dJDTttUtBj1ufF+y3JeTChnanZqfLn3RBKMNcEZ5tPm/E34tEABN5VMaaNKsU8BAc/c= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b=LKex86UP; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b="LKex86UP" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2D90A1F000C4; Sat, 17 Oct 2026 16:20:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1792254021; bh=HEja6dTaqqrQgixmOvbp/l4HZxjm5Q5BVJ+LXLYbrG8=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=LKex86UPsa0W0koT9wMb/s1hjBBSAN9iB1ahLyMhl1NWN9coHlAg9JH+bg0T9LR0/ rQqrnAryKCvePQg7CEQDxPa8hhDyZCLwBB8d3ZynaRNW/CVe1rGupOQN5jo1GM1dPU TZqkQmSjrasX7G29R+BDP53mxI3eT8Zm7P6jfwGM= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Pablo Neira Ayuso , Sasha Levin Subject: [PATCH 6.12 310/869] netfilter: nat: use kfree_rcu to release ops Date: Sat, 17 Oct 2026 17:52:31 +0200 Message-ID: <20261017160045.024710005@linuxfoundation.org> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261017160036.979869304@linuxfoundation.org> References: <20261017160036.979869304@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 6.12-stable review patch. If anyone has any objections, please let me know. ------------------ From: Pablo Neira Ayuso [ Upstream commit 6eda0d771f94267f73f57c94630aa47e90957915 ] Florian Westphal says: "Historically this is not an issue, even for normal base hooks: the data path doesn't use the original nf_hook_ops that are used to register the callbacks. However, in v5.14 I added the ability to dump the active netfilter hooks from userspace. This code will peek back into the nf_hook_ops that are available at the tail of the pointer-array blob used by the datapath. The nat hooks are special, because they are called indirectly from the central nat dispatcher hook. They are currently invisible to the nfnl hook dump subsystem though. But once that changes the nat ops structures have to be deferred too." Update nf_nat_register_fn() to deal with partial exposition of the hooks from error path which can be also an issue for nfnetlink_hook. Fixes: e2cf17d3774c ("netfilter: add new hook nfnl subsystem") Signed-off-by: Pablo Neira Ayuso Signed-off-by: Sasha Levin --- include/linux/netfilter.h | 2 ++ net/ipv4/netfilter/iptable_nat.c | 4 ++-- net/ipv6/netfilter/ip6table_nat.c | 4 ++-- net/netfilter/nf_nat_core.c | 10 ++++++---- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 2b8aac2c70ada..9b3357d8d8c3e 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -95,6 +95,8 @@ enum nf_hook_ops_type { }; struct nf_hook_ops { + struct rcu_head rcu; + /* User fills in from here down. */ nf_hookfn *hook; struct net_device *dev; diff --git a/net/ipv4/netfilter/iptable_nat.c b/net/ipv4/netfilter/iptable_nat.c index a5db7c67d61be..625a1ca13b1ba 100644 --- a/net/ipv4/netfilter/iptable_nat.c +++ b/net/ipv4/netfilter/iptable_nat.c @@ -79,7 +79,7 @@ static int ipt_nat_register_lookups(struct net *net) while (i) nf_nat_ipv4_unregister_fn(net, &ops[--i]); - kfree(ops); + kfree_rcu(ops, rcu); return ret; } } @@ -100,7 +100,7 @@ static void ipt_nat_unregister_lookups(struct net *net) for (i = 0; i < ARRAY_SIZE(nf_nat_ipv4_ops); i++) nf_nat_ipv4_unregister_fn(net, &ops[i]); - kfree(ops); + kfree_rcu(ops, rcu); } static int iptable_nat_table_init(struct net *net) diff --git a/net/ipv6/netfilter/ip6table_nat.c b/net/ipv6/netfilter/ip6table_nat.c index e119d4f090cc8..5be723232df8f 100644 --- a/net/ipv6/netfilter/ip6table_nat.c +++ b/net/ipv6/netfilter/ip6table_nat.c @@ -81,7 +81,7 @@ static int ip6t_nat_register_lookups(struct net *net) while (i) nf_nat_ipv6_unregister_fn(net, &ops[--i]); - kfree(ops); + kfree_rcu(ops, rcu); return ret; } } @@ -102,7 +102,7 @@ static void ip6t_nat_unregister_lookups(struct net *net) for (i = 0; i < ARRAY_SIZE(nf_nat_ipv6_ops); i++) nf_nat_ipv6_unregister_fn(net, &ops[i]); - kfree(ops); + kfree_rcu(ops, rcu); } static int ip6table_nat_table_init(struct net *net) diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c index 34e1ff930e28d..109c12fdc57d7 100644 --- a/net/netfilter/nf_nat_core.c +++ b/net/netfilter/nf_nat_core.c @@ -1247,9 +1247,11 @@ int nf_nat_register_fn(struct net *net, u8 pf, const struct nf_hook_ops *ops, ret = nf_register_net_hooks(net, nat_ops, ops_count); if (ret < 0) { mutex_unlock(&nf_nat_proto_mutex); - for (i = 0; i < ops_count; i++) - kfree(nat_ops[i].priv); - kfree(nat_ops); + for (i = 0; i < ops_count; i++) { + priv = nat_ops[i].priv; + kfree_rcu(priv, rcu_head); + } + kfree_rcu(nat_ops, rcu); return ret; } @@ -1313,7 +1315,7 @@ void nf_nat_unregister_fn(struct net *net, u8 pf, const struct nf_hook_ops *ops, } nat_proto_net->nat_hook_ops = NULL; - kfree(nat_ops); + kfree_rcu(nat_ops, rcu); } unlock: mutex_unlock(&nf_nat_proto_mutex); -- 2.53.0