* [PATCH nf,v2] netfilter: nf_nat: unregister and release hooks on error
@ 2026-09-02 23:06 Pablo Neira Ayuso
0 siblings, 0 replies; only message in thread
From: Pablo Neira Ayuso @ 2026-09-02 23:06 UTC (permalink / raw)
To: netfilter-devel
After the base nat hooks are registered, the first nested nat hook is
added through nf_hook_entries_insert_raw() and ->users is bumped.
However, sashiko reports that nf_hook_entries_insert_raw() fails, then
->users count remains at zero and nf_nat_unregister_fn() could hit
WARN_ON() since base nat hooks with no users is unexpected in the
unregistration path.
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>
---
v2: - move common error path handling under goto label
- postpone setting nat_proto_net->nat_hook_ops to decide what to
do in the error path.
net/netfilter/nf_nat_core.c | 43 ++++++++++++++++++++++++-------------
1 file changed, 28 insertions(+), 15 deletions(-)
diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
index 8ac326e1eb5b..de1fa53912c2 100644
--- a/net/netfilter/nf_nat_core.c
+++ b/net/netfilter/nf_nat_core.c
@@ -1224,31 +1224,44 @@ 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;
}
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] only message in thread
only message in thread, other threads:[~2026-09-02 23:06 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-02 23:06 [PATCH nf,v2] netfilter: nf_nat: unregister and release hooks on error Pablo Neira Ayuso
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.