From: Florian Westphal <f...@strlen.de> Once we place all conntracks in the same hash table we must also compare the netns pointer to skip conntracks that belong to a different namespace.
Signed-off-by: Florian Westphal <f...@strlen.de> Signed-off-by: Pablo Neira Ayuso <pa...@netfilter.org> https://jira.sw.ru/browse/PSBM-103515 (cherry picked from commit e0c7d47221883966d930fa7335b3ca295bc316b2) Signed-off-by: Konstantin Khorenko <khore...@virtuozzo.com> --- .../netfilter/nf_conntrack_l3proto_ipv4_compat.c | 8 ++++++-- net/netfilter/nf_conntrack_core.c | 23 ++++++++++++---------- net/netfilter/nf_conntrack_netlink.c | 3 +++ 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c index 7ac69de208868..2082e52cb5d9e 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c @@ -117,6 +117,7 @@ static inline int ct_show_secctx(struct seq_file *s, const struct nf_conn *ct) #endif static bool ct_seq_should_skip(const struct nf_conn *ct, + const struct net *net, const struct nf_conntrack_tuple_hash *hash) { /* we only want to print DIR_ORIGINAL */ @@ -126,6 +127,9 @@ static bool ct_seq_should_skip(const struct nf_conn *ct, if (nf_ct_l3num(ct) != AF_INET) return true; + if (!net_eq(nf_ct_net(ct), net)) + return true; + return false; } @@ -138,7 +142,7 @@ static int ct_seq_show(struct seq_file *s, void *v) int ret = 0; NF_CT_ASSERT(ct); - if (ct_seq_should_skip(ct, hash)) + if (ct_seq_should_skip(ct, seq_file_net(s), hash)) return 0; if (unlikely(!atomic_inc_not_zero(&ct->ct_general.use))) @@ -146,7 +150,7 @@ static int ct_seq_show(struct seq_file *s, void *v) /* check if we raced w. object reuse */ if (!nf_ct_is_confirmed(ct) || - ct_seq_should_skip(ct, hash)) + ct_seq_should_skip(ct, seq_file_net(s), hash)) goto release; l3proto = __nf_ct_l3proto_find(nf_ct_l3num(ct)); diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index c42074f98d155..67037c1fa3bac 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -463,7 +463,8 @@ static void death_by_timeout(unsigned long ul_conntrack) static inline bool nf_ct_key_equal(struct nf_conntrack_tuple_hash *h, const struct nf_conntrack_tuple *tuple, - const struct nf_conntrack_zone *zone) + const struct nf_conntrack_zone *zone, + const struct net *net) { struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h); @@ -472,7 +473,8 @@ nf_ct_key_equal(struct nf_conntrack_tuple_hash *h, */ return nf_ct_tuple_equal(tuple, &h->tuple) && nf_ct_zone_equal(ct, zone, NF_CT_DIRECTION(h)) && - nf_ct_is_confirmed(ct); + nf_ct_is_confirmed(ct) && + net_eq(net, nf_ct_net(ct)); } static inline bool @@ -529,7 +531,7 @@ ____nf_conntrack_find(struct net *net, const struct nf_conntrack_zone *zone, } while (read_seqcount_retry(&nf_conntrack_generation, sequence)); hlist_nulls_for_each_entry_rcu(h, n, &ct_hash[bucket], hnnode) { - if (nf_ct_key_equal(h, tuple, zone)) { + if (nf_ct_key_equal(h, tuple, zone, net)) { NF_CT_STAT_INC(net, found); local_bh_enable(); return h; @@ -567,7 +569,7 @@ __nf_conntrack_find_get(struct net *net, const struct nf_conntrack_zone *zone, !atomic_inc_not_zero(&ct->ct_general.use))) h = NULL; else { - if (unlikely(!nf_ct_key_equal(h, tuple, zone))) { + if (unlikely(!nf_ct_key_equal(h, tuple, zone, net))) { nf_ct_put(ct); goto begin; } @@ -623,12 +625,12 @@ nf_conntrack_hash_check_insert(struct nf_conn *ct) /* See if there's one in the list already, including reverse */ hlist_nulls_for_each_entry(h, n, &net->ct.hash[hash], hnnode) if (nf_ct_key_equal(h, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, - zone)) + zone, net)) goto out; hlist_nulls_for_each_entry(h, n, &net->ct.hash[reply_hash], hnnode) if (nf_ct_key_equal(h, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, - zone)) + zone, net)) goto out; add_timer(&ct->timeout); @@ -772,12 +774,12 @@ __nf_conntrack_confirm(struct sk_buff *skb) not in the hash. If there is, we lost race. */ hlist_nulls_for_each_entry(h, n, &net->ct.hash[hash], hnnode) if (nf_ct_key_equal(h, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, - zone)) + zone, net)) goto out; hlist_nulls_for_each_entry(h, n, &net->ct.hash[reply_hash], hnnode) if (nf_ct_key_equal(h, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, - zone)) + zone, net)) goto out; /* Timer relative to confirmation time, not original @@ -854,7 +856,7 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple, hlist_nulls_for_each_entry_rcu(h, n, &ct_hash[hash], hnnode) { ct = nf_ct_tuplehash_to_ctrack(h); if (ct != ignored_conntrack && - nf_ct_key_equal(h, tuple, zone)) { + nf_ct_key_equal(h, tuple, zone, net)) { /* Tuple is taken already, so caller will need to find * a new source port to use. * @@ -1530,7 +1532,8 @@ get_next_corpse(struct net *net, int (*iter)(struct nf_conn *i, void *data), if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL) continue; ct = nf_ct_tuplehash_to_ctrack(h); - if (iter(ct, data)) + if (net_eq(nf_ct_net(ct), net) && + iter(ct, data)) goto found; } } diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index fd52f90c17373..62fb00ac575fc 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -827,6 +827,9 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL) continue; ct = nf_ct_tuplehash_to_ctrack(h); + if (!net_eq(net, nf_ct_net(ct))) + continue; + /* Dump entries of a given L3 protocol number. * If it is not specified, ie. l3proto == 0, * then dump everything. */ -- 2.15.1 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel