mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-24 03:19:46 -04:00
netfilter: synproxy: add mutex to guard hook reference counting
As the synproxy infrastructure register netfilter hooks on-demand when a
user adds the first iptables target or nftables expression, if done
concurrently they can race each other.
Introduce a mutex to serialize the refcount control blocks access from
both frontends. While a per namespace mutex might be more efficient, it
is not needed for target/expression like SYNPROXY.
Fixes: ad49d86e07 ("netfilter: nf_tables: Add synproxy support")
Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
committed by
Pablo Neira Ayuso
parent
36d29ceec3
commit
2fcba19caa
@@ -22,6 +22,8 @@
|
||||
#include <net/netfilter/nf_conntrack_zones.h>
|
||||
#include <net/netfilter/nf_synproxy.h>
|
||||
|
||||
static DEFINE_MUTEX(synproxy_mutex);
|
||||
|
||||
unsigned int synproxy_net_id;
|
||||
EXPORT_SYMBOL_GPL(synproxy_net_id);
|
||||
|
||||
@@ -769,26 +771,31 @@ static const struct nf_hook_ops ipv4_synproxy_ops[] = {
|
||||
|
||||
int nf_synproxy_ipv4_init(struct synproxy_net *snet, struct net *net)
|
||||
{
|
||||
int err;
|
||||
int err = 0;
|
||||
|
||||
mutex_lock(&synproxy_mutex);
|
||||
if (snet->hook_ref4 == 0) {
|
||||
err = nf_register_net_hooks(net, ipv4_synproxy_ops,
|
||||
ARRAY_SIZE(ipv4_synproxy_ops));
|
||||
if (err)
|
||||
return err;
|
||||
goto out;
|
||||
}
|
||||
|
||||
snet->hook_ref4++;
|
||||
return 0;
|
||||
out:
|
||||
mutex_unlock(&synproxy_mutex);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_synproxy_ipv4_init);
|
||||
|
||||
void nf_synproxy_ipv4_fini(struct synproxy_net *snet, struct net *net)
|
||||
{
|
||||
mutex_lock(&synproxy_mutex);
|
||||
snet->hook_ref4--;
|
||||
if (snet->hook_ref4 == 0)
|
||||
nf_unregister_net_hooks(net, ipv4_synproxy_ops,
|
||||
ARRAY_SIZE(ipv4_synproxy_ops));
|
||||
mutex_unlock(&synproxy_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_synproxy_ipv4_fini);
|
||||
|
||||
@@ -1193,27 +1200,32 @@ static const struct nf_hook_ops ipv6_synproxy_ops[] = {
|
||||
int
|
||||
nf_synproxy_ipv6_init(struct synproxy_net *snet, struct net *net)
|
||||
{
|
||||
int err;
|
||||
int err = 0;
|
||||
|
||||
mutex_lock(&synproxy_mutex);
|
||||
if (snet->hook_ref6 == 0) {
|
||||
err = nf_register_net_hooks(net, ipv6_synproxy_ops,
|
||||
ARRAY_SIZE(ipv6_synproxy_ops));
|
||||
if (err)
|
||||
return err;
|
||||
goto out;
|
||||
}
|
||||
|
||||
snet->hook_ref6++;
|
||||
return 0;
|
||||
out:
|
||||
mutex_unlock(&synproxy_mutex);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_synproxy_ipv6_init);
|
||||
|
||||
void
|
||||
nf_synproxy_ipv6_fini(struct synproxy_net *snet, struct net *net)
|
||||
{
|
||||
mutex_lock(&synproxy_mutex);
|
||||
snet->hook_ref6--;
|
||||
if (snet->hook_ref6 == 0)
|
||||
nf_unregister_net_hooks(net, ipv6_synproxy_ops,
|
||||
ARRAY_SIZE(ipv6_synproxy_ops));
|
||||
mutex_unlock(&synproxy_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_synproxy_ipv6_fini);
|
||||
#endif /* CONFIG_IPV6 */
|
||||
|
||||
Reference in New Issue
Block a user