Skip to content

Commit

Permalink
netfilter: conntrack: check netns when comparing conntrack objects
Browse files Browse the repository at this point in the history
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 <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
  • Loading branch information
Florian Westphal authored and Pablo Neira Ayuso committed May 5, 2016
1 parent 245cfdc commit e0c7d47
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 12 deletions.
8 changes: 6 additions & 2 deletions net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ static inline void 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 */
Expand All @@ -124,6 +125,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;
}

Expand All @@ -136,15 +140,15 @@ 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)))
return 0;

/* 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));
Expand Down
23 changes: 13 additions & 10 deletions net/netfilter/nf_conntrack_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,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);

Expand All @@ -456,7 +457,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));
}

/*
Expand All @@ -481,7 +483,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_ATOMIC(net, found);
return h;
}
Expand Down Expand Up @@ -517,7 +519,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;
}
Expand Down Expand Up @@ -573,12 +575,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);
Expand Down Expand Up @@ -663,12 +665,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
Expand Down Expand Up @@ -740,7 +742,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)) {
NF_CT_STAT_INC_ATOMIC(net, found);
rcu_read_unlock();
return 1;
Expand Down Expand Up @@ -1383,7 +1385,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;
}
}
Expand Down
3 changes: 3 additions & 0 deletions net/netfilter/nf_conntrack_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -837,6 +837,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. */
Expand Down

0 comments on commit e0c7d47

Please sign in to comment.