Skip to content

Commit 6eda0d7

Browse files
committed
netfilter: nat: use kfree_rcu to release ops
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: e2cf17d ("netfilter: add new hook nfnl subsystem") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
1 parent b6fe26f commit 6eda0d7

3 files changed

Lines changed: 10 additions & 8 deletions

File tree

net/ipv4/netfilter/iptable_nat.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ static int ipt_nat_register_lookups(struct net *net)
7979
while (i)
8080
nf_nat_ipv4_unregister_fn(net, &ops[--i]);
8181

82-
kfree(ops);
82+
kfree_rcu(ops, rcu);
8383
return ret;
8484
}
8585
}
@@ -100,7 +100,7 @@ static void ipt_nat_unregister_lookups(struct net *net)
100100
for (i = 0; i < ARRAY_SIZE(nf_nat_ipv4_ops); i++)
101101
nf_nat_ipv4_unregister_fn(net, &ops[i]);
102102

103-
kfree(ops);
103+
kfree_rcu(ops, rcu);
104104
}
105105

106106
static int iptable_nat_table_init(struct net *net)

net/ipv6/netfilter/ip6table_nat.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ static int ip6t_nat_register_lookups(struct net *net)
8181
while (i)
8282
nf_nat_ipv6_unregister_fn(net, &ops[--i]);
8383

84-
kfree(ops);
84+
kfree_rcu(ops, rcu);
8585
return ret;
8686
}
8787
}
@@ -102,7 +102,7 @@ static void ip6t_nat_unregister_lookups(struct net *net)
102102
for (i = 0; i < ARRAY_SIZE(nf_nat_ipv6_ops); i++)
103103
nf_nat_ipv6_unregister_fn(net, &ops[i]);
104104

105-
kfree(ops);
105+
kfree_rcu(ops, rcu);
106106
}
107107

108108
static int ip6table_nat_table_init(struct net *net)

net/netfilter/nf_nat_core.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,9 +1222,11 @@ int nf_nat_register_fn(struct net *net, u8 pf, const struct nf_hook_ops *ops,
12221222
ret = nf_register_net_hooks(net, nat_ops, ops_count);
12231223
if (ret < 0) {
12241224
mutex_unlock(&nf_nat_proto_mutex);
1225-
for (i = 0; i < ops_count; i++)
1226-
kfree(nat_ops[i].priv);
1227-
kfree(nat_ops);
1225+
for (i = 0; i < ops_count; i++) {
1226+
priv = nat_ops[i].priv;
1227+
kfree_rcu(priv, rcu_head);
1228+
}
1229+
kfree_rcu(nat_ops, rcu);
12281230
return ret;
12291231
}
12301232

@@ -1288,7 +1290,7 @@ void nf_nat_unregister_fn(struct net *net, u8 pf, const struct nf_hook_ops *ops,
12881290
}
12891291

12901292
nat_proto_net->nat_hook_ops = NULL;
1291-
kfree(nat_ops);
1293+
kfree_rcu(nat_ops, rcu);
12921294
}
12931295
unlock:
12941296
mutex_unlock(&nf_nat_proto_mutex);

0 commit comments

Comments
 (0)