Skip to content

Commit e0c7d47

Browse files
Florian Westphalummakynes
authored andcommitted
netfilter: conntrack: check netns when comparing conntrack objects
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 <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent 245cfdc commit e0c7d47

File tree

3 files changed

+22
-12
lines changed

3 files changed

+22
-12
lines changed

net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ static inline void ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
115115
#endif
116116

117117
static bool ct_seq_should_skip(const struct nf_conn *ct,
118+
const struct net *net,
118119
const struct nf_conntrack_tuple_hash *hash)
119120
{
120121
/* we only want to print DIR_ORIGINAL */
@@ -124,6 +125,9 @@ static bool ct_seq_should_skip(const struct nf_conn *ct,
124125
if (nf_ct_l3num(ct) != AF_INET)
125126
return true;
126127

128+
if (!net_eq(nf_ct_net(ct), net))
129+
return true;
130+
127131
return false;
128132
}
129133

@@ -136,15 +140,15 @@ static int ct_seq_show(struct seq_file *s, void *v)
136140
int ret = 0;
137141

138142
NF_CT_ASSERT(ct);
139-
if (ct_seq_should_skip(ct, hash))
143+
if (ct_seq_should_skip(ct, seq_file_net(s), hash))
140144
return 0;
141145

142146
if (unlikely(!atomic_inc_not_zero(&ct->ct_general.use)))
143147
return 0;
144148

145149
/* check if we raced w. object reuse */
146150
if (!nf_ct_is_confirmed(ct) ||
147-
ct_seq_should_skip(ct, hash))
151+
ct_seq_should_skip(ct, seq_file_net(s), hash))
148152
goto release;
149153

150154
l3proto = __nf_ct_l3proto_find(nf_ct_l3num(ct));

net/netfilter/nf_conntrack_core.c

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,8 @@ static void death_by_timeout(unsigned long ul_conntrack)
447447
static inline bool
448448
nf_ct_key_equal(struct nf_conntrack_tuple_hash *h,
449449
const struct nf_conntrack_tuple *tuple,
450-
const struct nf_conntrack_zone *zone)
450+
const struct nf_conntrack_zone *zone,
451+
const struct net *net)
451452
{
452453
struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
453454

@@ -456,7 +457,8 @@ nf_ct_key_equal(struct nf_conntrack_tuple_hash *h,
456457
*/
457458
return nf_ct_tuple_equal(tuple, &h->tuple) &&
458459
nf_ct_zone_equal(ct, zone, NF_CT_DIRECTION(h)) &&
459-
nf_ct_is_confirmed(ct);
460+
nf_ct_is_confirmed(ct) &&
461+
net_eq(net, nf_ct_net(ct));
460462
}
461463

462464
/*
@@ -481,7 +483,7 @@ ____nf_conntrack_find(struct net *net, const struct nf_conntrack_zone *zone,
481483
} while (read_seqcount_retry(&nf_conntrack_generation, sequence));
482484

483485
hlist_nulls_for_each_entry_rcu(h, n, &ct_hash[bucket], hnnode) {
484-
if (nf_ct_key_equal(h, tuple, zone)) {
486+
if (nf_ct_key_equal(h, tuple, zone, net)) {
485487
NF_CT_STAT_INC_ATOMIC(net, found);
486488
return h;
487489
}
@@ -517,7 +519,7 @@ __nf_conntrack_find_get(struct net *net, const struct nf_conntrack_zone *zone,
517519
!atomic_inc_not_zero(&ct->ct_general.use)))
518520
h = NULL;
519521
else {
520-
if (unlikely(!nf_ct_key_equal(h, tuple, zone))) {
522+
if (unlikely(!nf_ct_key_equal(h, tuple, zone, net))) {
521523
nf_ct_put(ct);
522524
goto begin;
523525
}
@@ -573,12 +575,12 @@ nf_conntrack_hash_check_insert(struct nf_conn *ct)
573575
/* See if there's one in the list already, including reverse */
574576
hlist_nulls_for_each_entry(h, n, &net->ct.hash[hash], hnnode)
575577
if (nf_ct_key_equal(h, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
576-
zone))
578+
zone, net))
577579
goto out;
578580

579581
hlist_nulls_for_each_entry(h, n, &net->ct.hash[reply_hash], hnnode)
580582
if (nf_ct_key_equal(h, &ct->tuplehash[IP_CT_DIR_REPLY].tuple,
581-
zone))
583+
zone, net))
582584
goto out;
583585

584586
add_timer(&ct->timeout);
@@ -663,12 +665,12 @@ __nf_conntrack_confirm(struct sk_buff *skb)
663665
not in the hash. If there is, we lost race. */
664666
hlist_nulls_for_each_entry(h, n, &net->ct.hash[hash], hnnode)
665667
if (nf_ct_key_equal(h, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
666-
zone))
668+
zone, net))
667669
goto out;
668670

669671
hlist_nulls_for_each_entry(h, n, &net->ct.hash[reply_hash], hnnode)
670672
if (nf_ct_key_equal(h, &ct->tuplehash[IP_CT_DIR_REPLY].tuple,
671-
zone))
673+
zone, net))
672674
goto out;
673675

674676
/* Timer relative to confirmation time, not original
@@ -740,7 +742,7 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple,
740742
hlist_nulls_for_each_entry_rcu(h, n, &ct_hash[hash], hnnode) {
741743
ct = nf_ct_tuplehash_to_ctrack(h);
742744
if (ct != ignored_conntrack &&
743-
nf_ct_key_equal(h, tuple, zone)) {
745+
nf_ct_key_equal(h, tuple, zone, net)) {
744746
NF_CT_STAT_INC_ATOMIC(net, found);
745747
rcu_read_unlock();
746748
return 1;
@@ -1383,7 +1385,8 @@ get_next_corpse(struct net *net, int (*iter)(struct nf_conn *i, void *data),
13831385
if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL)
13841386
continue;
13851387
ct = nf_ct_tuplehash_to_ctrack(h);
1386-
if (iter(ct, data))
1388+
if (net_eq(nf_ct_net(ct), net) &&
1389+
iter(ct, data))
13871390
goto found;
13881391
}
13891392
}

net/netfilter/nf_conntrack_netlink.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -837,6 +837,9 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
837837
if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL)
838838
continue;
839839
ct = nf_ct_tuplehash_to_ctrack(h);
840+
if (!net_eq(net, nf_ct_net(ct)))
841+
continue;
842+
840843
/* Dump entries of a given L3 protocol number.
841844
* If it is not specified, ie. l3proto == 0,
842845
* then dump everything. */

0 commit comments

Comments
 (0)