Allocation will be allowed only when there are conntracks users. By default it's prohibited.
Signed-off-by: Kirill Tkhai <ktk...@virtuozzo.com> --- include/net/net_namespace.h | 10 ++++++++++ include/net/netns/conntrack.h | 1 + net/netfilter/nf_conntrack_core.c | 9 ++++++++- net/netfilter/nf_conntrack_netlink.c | 1 + net/netfilter/nf_synproxy_core.c | 1 + 5 files changed, 21 insertions(+), 1 deletion(-) diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 94a63ea..efd2971 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -296,6 +296,16 @@ static inline struct net *read_pnet(possible_net_t const *pnet) #define __net_initconst __initconst #endif +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) +static inline void allow_conntrack_allocation(struct net *net) +{ + net->ct.can_alloc = true; + smp_wmb(); /* Pairs with rmb in __nf_conntrack_alloc() */ +} +#else +static inline void allow_conntrack_allocation(struct net *net) { } +#endif + int peernet2id_alloc(struct net *net, struct net *peer); int peernet2id(struct net *net, struct net *peer); bool peernet_has_id(struct net *net, struct net *peer); diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h index 4d7de37..0c2a685 100644 --- a/include/net/netns/conntrack.h +++ b/include/net/netns/conntrack.h @@ -74,6 +74,7 @@ struct ct_pcpu { struct netns_ct { atomic_t count; + bool can_alloc; unsigned int max; unsigned int expect_count; unsigned int expect_max; diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 0c94c3a..15e8479 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -841,6 +841,12 @@ __nf_conntrack_alloc(struct net *net, u16 zone, unsigned int ct_max = net->ct.max ? net->ct.max : init_net.ct.max; struct nf_conn *ct; + if (!net->ct.can_alloc) { + /* No rules loaded */ + return NULL; + } + smp_rmb(); /* Pairs with wmb in allow_conntrack_allocation() */ + if (unlikely(!nf_conntrack_hash_rnd)) { init_nf_conntrack_hash_rnd(); /* recompute the hash as nf_conntrack_hash_rnd is initialized */ @@ -963,7 +969,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, ct = __nf_conntrack_alloc(net, zone, tuple, &repl_tuple, GFP_ATOMIC, hash); - if (IS_ERR(ct)) + if (IS_ERR_OR_NULL(ct)) return (struct nf_conntrack_tuple_hash *)ct; if (tmpl && nfct_synproxy(tmpl)) { @@ -1816,6 +1822,7 @@ int nf_conntrack_init_net(struct net *net) int cpu; atomic_set(&net->ct.count, 0); + net->ct.can_alloc = false; net->ct.max = init_net.ct.max; seqcount_init(&net->ct.generation); diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index d6b6465..aad05a0 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1617,6 +1617,7 @@ ctnetlink_create_conntrack(struct net *net, u16 zone, struct nf_conntrack_helper *helper; struct nf_conn_tstamp *tstamp; + allow_conntrack_allocation(net); ct = nf_conntrack_alloc(net, zone, otuple, rtuple, GFP_ATOMIC); if (IS_ERR(ct)) return ERR_PTR(-ENOMEM); diff --git a/net/netfilter/nf_synproxy_core.c b/net/netfilter/nf_synproxy_core.c index 52e20c9..779e5a6 100644 --- a/net/netfilter/nf_synproxy_core.c +++ b/net/netfilter/nf_synproxy_core.c @@ -353,6 +353,7 @@ static int __net_init synproxy_net_init(struct net *net) int err = -ENOMEM; memset(&t, 0, sizeof(t)); + allow_conntrack_allocation(net); ct = nf_conntrack_alloc(net, 0, &t, &t, GFP_KERNEL); if (IS_ERR(ct)) { err = PTR_ERR(ct); _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel