mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-08-09 06:14:34 +02:00
netfilter: synproxy: add mutex to guard hook reference counting
[ Upstream commit2fcba19caa] 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> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
7d4f500451
commit
debc57b83d
@@ -21,6 +21,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);
|
||||
|
||||
@@ -768,26 +770,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);
|
||||
|
||||
@@ -1192,27 +1199,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