summaryrefslogtreecommitdiff
path: root/net/ipv6/netfilter
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2021-04-21 09:45:40 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2021-04-26 03:20:07 +0200
commitde8c12110a130337c8e7e7b8250de0580e644dee (patch)
tree6cfc80f96c19a60753a15a99e906996e2f0b499c /net/ipv6/netfilter
parente0bb96db96f8ca94349344a2ea7bebc6f8cefdae (diff)
netfilter: disable defrag once its no longer needed
When I changed defrag hooks to no longer get registered by default I intentionally made it so that registration can only be un-done by unloading the nf_defrag_ipv4/6 module. In hindsight this was too conservative; there is no reason to keep defrag on while there is no feature dependency anymore. Moreover, this won't work if user isn't allowed to remove nf_defrag module. This adds the disable() functions for both ipv4 and ipv6 and calls them from conntrack, TPROXY and the xtables socket module. ipvs isn't converted here, it will behave as before this patch and will need module removal. Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/ipv6/netfilter')
-rw-r--r--net/ipv6/netfilter/nf_defrag_ipv6_hooks.c29
1 files changed, 23 insertions, 6 deletions
diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
index 402dc4ca9504..e8a59d8bf2ad 100644
--- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
+++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
@@ -137,14 +137,16 @@ int nf_defrag_ipv6_enable(struct net *net)
struct nft_ct_frag6_pernet *nf_frag = net_generic(net, nf_frag_pernet_id);
int err = 0;
- might_sleep();
-
- if (nf_frag->users)
- return 0;
-
mutex_lock(&defrag6_mutex);
- if (nf_frag->users)
+ if (nf_frag->users == UINT_MAX) {
+ err = -EOVERFLOW;
+ goto out_unlock;
+ }
+
+ if (nf_frag->users) {
+ nf_frag->users++;
goto out_unlock;
+ }
err = nf_register_net_hooks(net, ipv6_defrag_ops,
ARRAY_SIZE(ipv6_defrag_ops));
@@ -157,6 +159,21 @@ int nf_defrag_ipv6_enable(struct net *net)
}
EXPORT_SYMBOL_GPL(nf_defrag_ipv6_enable);
+void nf_defrag_ipv6_disable(struct net *net)
+{
+ struct nft_ct_frag6_pernet *nf_frag = net_generic(net, nf_frag_pernet_id);
+
+ mutex_lock(&defrag6_mutex);
+ if (nf_frag->users) {
+ nf_frag->users--;
+ if (nf_frag->users == 0)
+ nf_unregister_net_hooks(net, ipv6_defrag_ops,
+ ARRAY_SIZE(ipv6_defrag_ops));
+ }
+ mutex_unlock(&defrag6_mutex);
+}
+EXPORT_SYMBOL_GPL(nf_defrag_ipv6_disable);
+
module_init(nf_defrag_init);
module_exit(nf_defrag_fini);