* [PATCH net,v2 0/4] Netfilter fixes for net
@ 2026-09-11 11:21 Pablo Neira Ayuso
2026-09-11 11:21 ` [PATCH net 1/4] netfilter: nft_nat: fully initialise new_addr in netmap setup Pablo Neira Ayuso
` (3 more replies)
0 siblings, 4 replies; 6+ messages in thread
From: Pablo Neira Ayuso @ 2026-09-11 11:21 UTC (permalink / raw)
To: netfilter-devel
v2: - reword the commit description of the nf_nat_register_fn() to
explicitly refer to the memleak, so LLM does not get confused.
- drop the xt_IDLETIMER and module = THIS_MODULE in netlink_dump.
- keep back IPVS fix as Julian prefer to send a v2.
-o-
Hi,
The following patchset contains Netfilter fixes for net:
1) Fix KMSAN reports an uninit-value in nf_nat_setup_info() for netmap,
from Theodor Arsenij Larionov Trichkine.
2) Restrict deletion of netdevice in basechain and flowtable to exact
matching only, from Fernando F. Mancera.
3) Fix nf_nat_register_fn() error path allowing for a memleak.
4) Hold reference on ct until flow is released to address, otherwise
access to release ct->ext or different ct due to typesafe RCU
semantics.
Please, pull these changes from:
git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf.git nf-26-09-11
Thanks.
----------------------------------------------------------------
The following changes since commit 78445023439506ebd83b86d40b1e428a3b309d4a:
Merge tag 'net-7.3-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net (2026-09-10 14:07:48 -0700)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf.git nf-26-09-11
for you to fetch changes up to e75a9fa1d44bcbd66ea02e8781bcca6ea4076e0d:
netfilter: flowtable: hold reference on ct until flow is released (2026-09-11 13:04:15 +0200)
----------------------------------------------------------------
netfilter pull request 26-09-11
----------------------------------------------------------------
Fernando Fernandez Mancera (1):
netfilter: nf_tables: fix device name and prefix match in hook lookup
Pablo Neira Ayuso (2):
netfilter: nf_nat: unregister and release hooks on error
netfilter: flowtable: hold reference on ct until flow is released
Theodor Arsenij Larionov Trichkine (1):
netfilter: nft_nat: fully initialise new_addr in netmap setup
net/netfilter/nf_flow_table_core.c | 12 ++++++++--
net/netfilter/nf_nat_core.c | 46 +++++++++++++++++++++++++-------------
net/netfilter/nf_tables_api.c | 22 ++++++++++--------
net/netfilter/nft_nat.c | 2 +-
4 files changed, 54 insertions(+), 28 deletions(-)
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH net 1/4] netfilter: nft_nat: fully initialise new_addr in netmap setup
2026-09-11 11:21 [PATCH net,v2 0/4] Netfilter fixes for net Pablo Neira Ayuso
@ 2026-09-11 11:21 ` Pablo Neira Ayuso
2026-09-11 11:21 ` [PATCH net 2/4] netfilter: nf_tables: fix device name and prefix match in hook lookup Pablo Neira Ayuso
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Pablo Neira Ayuso @ 2026-09-11 11:21 UTC (permalink / raw)
To: netfilter-devel
From: Theodor Arsenij Larionov Trichkine <theodorlarionov@gmail.com>
nft_nat_setup_netmap() builds the mapped address in an on-stack
union nf_inet_addr. For an IPv4 mapping it writes only the 4-byte .ip
member and the loop runs a single 32-bit iteration, but it then copies
the whole 16-byte union into range->min_addr and range->max_addr, so the
upper 12 bytes reach nf_nat_setup_info() uninitialised.
KMSAN reports an uninit-value in nf_nat_setup_info() reached from
nft_nat_eval(). The IPv6 path fills all 16 bytes and is not affected.
Zero-initialise new_addr.
Fixes: 3ff7ddb1353d ("netfilter: nft_nat: add netmap support")
Signed-off-by: Theodor Arsenij Larionov Trichkine <theodorlarionov@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nft_nat.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/netfilter/nft_nat.c b/net/netfilter/nft_nat.c
index e32cd9fbc7c2..cdbd800cac96 100644
--- a/net/netfilter/nft_nat.c
+++ b/net/netfilter/nft_nat.c
@@ -64,8 +64,8 @@ static void nft_nat_setup_netmap(struct nf_nat_range2 *range,
const struct nft_pktinfo *pkt,
const struct nft_nat *priv)
{
+ union nf_inet_addr new_addr = {};
struct sk_buff *skb = pkt->skb;
- union nf_inet_addr new_addr;
__be32 netmask;
int i, len = 0;
--
2.47.3
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH net 2/4] netfilter: nf_tables: fix device name and prefix match in hook lookup
2026-09-11 11:21 [PATCH net,v2 0/4] Netfilter fixes for net Pablo Neira Ayuso
2026-09-11 11:21 ` [PATCH net 1/4] netfilter: nft_nat: fully initialise new_addr in netmap setup Pablo Neira Ayuso
@ 2026-09-11 11:21 ` Pablo Neira Ayuso
2026-09-11 11:21 ` [PATCH net 3/4] netfilter: nf_nat: unregister and release hooks on error Pablo Neira Ayuso
2026-09-11 11:21 ` [PATCH net 4/4] netfilter: flowtable: hold reference on ct until flow is released Pablo Neira Ayuso
3 siblings, 0 replies; 6+ messages in thread
From: Pablo Neira Ayuso @ 2026-09-11 11:21 UTC (permalink / raw)
To: netfilter-devel
From: Fernando Fernandez Mancera <fmancera@suse.de>
Currently, a netdev chain or flowtable hooked to a device prefix can be
unintentionally deleted by a control-plane request targeting an exact
device name or even a shorter one due to the usage of min() to calculate
the length to match.
Fix this by making sure an exact device match never matches a prefix and
that both the target and the candidate have the same length during
delete operation. The add and update paths retain the existing overlap
matching to prevent a single device from matching multiple hooks.
Reported-by: Wei Fang <void0red@gmail.com>
Closes: https://lore.kernel.org/netfilter-devel/CANE+tVrDeNCHQVmsqkV2ozeBqyE3GtRDMhZgsg1bhw10yGNTRQ@mail.gmail.com/
Fixes: 6d07a289504a ("netfilter: nf_tables: Support wildcard netdev hook specs")
Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nf_tables_api.c | 22 +++++++++++++---------
1 file changed, 13 insertions(+), 9 deletions(-)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 31fbd5a28937..c0b754a2d45b 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -2440,11 +2440,14 @@ static struct nft_hook *nft_netdev_hook_alloc(struct net *net,
}
static struct nft_hook *nft_hook_list_find(struct list_head *hook_list,
- const struct nft_hook *this)
+ const struct nft_hook *this,
+ bool strict)
{
struct nft_hook *hook;
list_for_each_entry(hook, hook_list, list) {
+ if (strict && hook->ifnamelen != this->ifnamelen)
+ continue;
if (!strncmp(hook->ifname, this->ifname,
min(hook->ifnamelen, this->ifnamelen))) {
if (hook->flags & NFT_HOOK_REMOVE)
@@ -2486,7 +2489,7 @@ static int nf_tables_parse_netdev_hooks(struct net *net,
err = PTR_ERR(hook);
goto err_hook;
}
- if (nft_hook_list_find(hook_list, hook)) {
+ if (nft_hook_list_find(hook_list, hook, false)) {
NL_SET_BAD_ATTR(extack, tmp);
nft_netdev_hook_free(hook);
err = -EEXIST;
@@ -2943,7 +2946,7 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
ops->hook = basechain->ops.hook;
}
- if (nft_hook_list_find(&basechain->hook_list, h)) {
+ if (nft_hook_list_find(&basechain->hook_list, h, false)) {
list_del(&h->list);
nft_netdev_hook_free(h);
continue;
@@ -2956,7 +2959,8 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
!nft_trans_chain_update(trans))
continue;
- if (nft_hook_list_find(&nft_trans_chain_hooks(trans), h)) {
+ if (nft_hook_list_find(&nft_trans_chain_hooks(trans),
+ h, false)) {
nft_chain_release_hook(&hook);
return -EEXIST;
}
@@ -3257,7 +3261,7 @@ static int nft_delchain_hook(struct nft_ctx *ctx,
return err;
list_for_each_entry(this, &chain_hook.list, list) {
- hook = nft_hook_list_find(&basechain->hook_list, this);
+ hook = nft_hook_list_find(&basechain->hook_list, this, true);
if (!hook) {
err = -ENOENT;
goto err_chain_del_hook;
@@ -9053,7 +9057,7 @@ static int nft_register_flowtable_net_hooks(struct net *net,
if (!nft_is_active_next(net, ft))
continue;
- if (nft_hook_list_find(&ft->hook_list, hook)) {
+ if (nft_hook_list_find(&ft->hook_list, hook, false)) {
err = -EEXIST;
goto err_unregister_net_hooks;
}
@@ -9130,7 +9134,7 @@ static int nft_flowtable_update(struct nft_ctx *ctx, const struct nlmsghdr *nlh,
return err;
list_for_each_entry_safe(hook, next, &flowtable_hook.list, list) {
- if (nft_hook_list_find(&flowtable->hook_list, hook)) {
+ if (nft_hook_list_find(&flowtable->hook_list, hook, false)) {
list_del(&hook->list);
nft_netdev_hook_free(hook);
continue;
@@ -9143,7 +9147,7 @@ static int nft_flowtable_update(struct nft_ctx *ctx, const struct nlmsghdr *nlh,
!nft_trans_flowtable_update(trans))
continue;
- if (nft_hook_list_find(&nft_trans_flowtable_hooks(trans), hook)) {
+ if (nft_hook_list_find(&nft_trans_flowtable_hooks(trans), hook, false)) {
err = -EEXIST;
goto err_flowtable_update_hook;
}
@@ -9363,7 +9367,7 @@ static int nft_delflowtable_hook(struct nft_ctx *ctx,
return err;
list_for_each_entry(this, &flowtable_hook.list, list) {
- hook = nft_hook_list_find(&flowtable->hook_list, this);
+ hook = nft_hook_list_find(&flowtable->hook_list, this, true);
if (!hook) {
err = -ENOENT;
goto err_flowtable_del_hook;
--
2.47.3
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH net 3/4] netfilter: nf_nat: unregister and release hooks on error
2026-09-11 11:21 [PATCH net,v2 0/4] Netfilter fixes for net Pablo Neira Ayuso
2026-09-11 11:21 ` [PATCH net 1/4] netfilter: nft_nat: fully initialise new_addr in netmap setup Pablo Neira Ayuso
2026-09-11 11:21 ` [PATCH net 2/4] netfilter: nf_tables: fix device name and prefix match in hook lookup Pablo Neira Ayuso
@ 2026-09-11 11:21 ` Pablo Neira Ayuso
2026-09-11 11:21 ` [PATCH net 4/4] netfilter: flowtable: hold reference on ct until flow is released Pablo Neira Ayuso
3 siblings, 0 replies; 6+ messages in thread
From: Pablo Neira Ayuso @ 2026-09-11 11:21 UTC (permalink / raw)
To: netfilter-devel
If nf_hook_entries_insert_raw() fails, the NAT hooks get never released,
resulting in a memleak.
Postpone setting nat_proto_net->nat_hook_ops when the hooks are
registered to simplify the error path to decide whether the nat hooks
need unwinding.
Fixes: 1cd472bf036c ("netfilter: nf_nat: add nat hook register functions to nf_nat")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nf_nat_core.c | 46 ++++++++++++++++++++++++-------------
1 file changed, 30 insertions(+), 16 deletions(-)
diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
index 8ac326e1eb5b..a4858c2b2d65 100644
--- a/net/netfilter/nf_nat_core.c
+++ b/net/netfilter/nf_nat_core.c
@@ -1224,31 +1224,45 @@ 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++) {
- priv = nat_ops[i].priv;
- kfree_rcu(priv, rcu_head);
- }
- kfree_rcu(nat_ops, rcu);
- return ret;
- }
-
- nat_proto_net->nat_hook_ops = nat_ops;
+ if (ret < 0)
+ goto err_free_hooks;
+ } else {
+ nat_ops = nat_proto_net->nat_hook_ops;
}
- nat_ops = nat_proto_net->nat_hook_ops;
priv = nat_ops[hooknum].priv;
if (WARN_ON_ONCE(!priv)) {
- mutex_unlock(&nf_nat_proto_mutex);
- return -EOPNOTSUPP;
+ ret = -EOPNOTSUPP;
+ goto err_unregister_hooks;
}
ret = nf_hook_entries_insert_raw(&priv->entries, ops);
- if (ret == 0)
- nat_proto_net->users++;
+ if (ret)
+ goto err_unregister_hooks;
+
+ if (!nat_proto_net->nat_hook_ops)
+ nat_proto_net->nat_hook_ops = nat_ops;
+
+ nat_proto_net->users++;
mutex_unlock(&nf_nat_proto_mutex);
+
+ return 0;
+
+err_unregister_hooks:
+ if (nat_proto_net->nat_hook_ops) {
+ mutex_unlock(&nf_nat_proto_mutex);
+ return ret;
+ }
+ nf_unregister_net_hooks(net, nat_ops, ops_count);
+err_free_hooks:
+ mutex_unlock(&nf_nat_proto_mutex);
+ for (i = 0; i < ops_count; i++) {
+ priv = nat_ops[i].priv;
+ kfree_rcu(priv, rcu_head);
+ }
+ kfree_rcu(nat_ops, rcu);
+
return ret;
}
--
2.47.3
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH net 4/4] netfilter: flowtable: hold reference on ct until flow is released
2026-09-11 11:21 [PATCH net,v2 0/4] Netfilter fixes for net Pablo Neira Ayuso
` (2 preceding siblings ...)
2026-09-11 11:21 ` [PATCH net 3/4] netfilter: nf_nat: unregister and release hooks on error Pablo Neira Ayuso
@ 2026-09-11 11:21 ` Pablo Neira Ayuso
3 siblings, 0 replies; 6+ messages in thread
From: Pablo Neira Ayuso @ 2026-09-11 11:21 UTC (permalink / raw)
To: netfilter-devel
nf_ct_put() releases the ct->ext area inmediately, the rcu typesafe
semantics also allow to refer to the wrong conntrack from the flowtable
datapath. Hold reference on ct until flow is released after rcu grace
period.
Add rcu_barrier() on module exit path, to ensure pending flow entries
are release before module goes away.
Fixes: 0ff90b6c2034 ("netfilter: nf_flow_offload: fix use-after-free and a resource leak")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nf_flow_table_core.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c
index 03241d4bfd5e..934c6151f558 100644
--- a/net/netfilter/nf_flow_table_core.c
+++ b/net/netfilter/nf_flow_table_core.c
@@ -258,6 +258,14 @@ static void flow_offload_route_release(struct flow_offload *flow)
nft_flow_dst_release(flow, FLOW_OFFLOAD_DIR_REPLY);
}
+static void flow_offload_free_rcu(struct rcu_head *rcu_head)
+{
+ struct flow_offload *flow = container_of(rcu_head, struct flow_offload, rcu_head);
+
+ nf_ct_put(flow->ct);
+ kfree(flow);
+}
+
void flow_offload_free(struct flow_offload *flow)
{
switch (flow->type) {
@@ -267,8 +275,7 @@ void flow_offload_free(struct flow_offload *flow)
default:
break;
}
- nf_ct_put(flow->ct);
- kfree_rcu(flow, rcu_head);
+ call_rcu(&flow->rcu_head, flow_offload_free_rcu);
}
EXPORT_SYMBOL_GPL(flow_offload_free);
@@ -854,6 +861,7 @@ static int __init nf_flow_table_module_init(void)
static void __exit nf_flow_table_module_exit(void)
{
+ rcu_barrier();
nf_flow_table_offload_exit();
unregister_pernet_subsys(&nf_flow_table_net_ops);
kmem_cache_destroy(flow_offload_cachep);
--
2.47.3
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH net 1/4] netfilter: nft_nat: fully initialise new_addr in netmap setup
2026-09-13 20:54 [PATCH net,v2 0/4 RESEND] Netfilter fixes for net Pablo Neira Ayuso
@ 2026-09-13 20:54 ` Pablo Neira Ayuso
0 siblings, 0 replies; 6+ messages in thread
From: Pablo Neira Ayuso @ 2026-09-13 20:54 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev, kuba, pabeni, edumazet, horms, fw, ja
From: Theodor Arsenij Larionov Trichkine <theodorlarionov@gmail.com>
nft_nat_setup_netmap() builds the mapped address in an on-stack
union nf_inet_addr. For an IPv4 mapping it writes only the 4-byte .ip
member and the loop runs a single 32-bit iteration, but it then copies
the whole 16-byte union into range->min_addr and range->max_addr, so the
upper 12 bytes reach nf_nat_setup_info() uninitialised.
KMSAN reports an uninit-value in nf_nat_setup_info() reached from
nft_nat_eval(). The IPv6 path fills all 16 bytes and is not affected.
Zero-initialise new_addr.
Fixes: 3ff7ddb1353d ("netfilter: nft_nat: add netmap support")
Signed-off-by: Theodor Arsenij Larionov Trichkine <theodorlarionov@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nft_nat.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/netfilter/nft_nat.c b/net/netfilter/nft_nat.c
index e32cd9fbc7c2..cdbd800cac96 100644
--- a/net/netfilter/nft_nat.c
+++ b/net/netfilter/nft_nat.c
@@ -64,8 +64,8 @@ static void nft_nat_setup_netmap(struct nf_nat_range2 *range,
const struct nft_pktinfo *pkt,
const struct nft_nat *priv)
{
+ union nf_inet_addr new_addr = {};
struct sk_buff *skb = pkt->skb;
- union nf_inet_addr new_addr;
__be32 netmask;
int i, len = 0;
--
2.47.3
^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-09-13 20:55 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-11 11:21 [PATCH net,v2 0/4] Netfilter fixes for net Pablo Neira Ayuso
2026-09-11 11:21 ` [PATCH net 1/4] netfilter: nft_nat: fully initialise new_addr in netmap setup Pablo Neira Ayuso
2026-09-11 11:21 ` [PATCH net 2/4] netfilter: nf_tables: fix device name and prefix match in hook lookup Pablo Neira Ayuso
2026-09-11 11:21 ` [PATCH net 3/4] netfilter: nf_nat: unregister and release hooks on error Pablo Neira Ayuso
2026-09-11 11:21 ` [PATCH net 4/4] netfilter: flowtable: hold reference on ct until flow is released Pablo Neira Ayuso
-- strict thread matches above, loose matches on Subject: below --
2026-09-13 20:54 [PATCH net,v2 0/4 RESEND] Netfilter fixes for net Pablo Neira Ayuso
2026-09-13 20:54 ` [PATCH net 1/4] netfilter: nft_nat: fully initialise new_addr in netmap setup Pablo Neira Ayuso
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox