Skip to content

Commit 3e86638

Browse files
Florian Westphalummakynes
authored andcommitted
netfilter: conntrack: consider ct netns in early_drop logic
When iterating, skip conntrack entries living in a different netns. We could ignore netns and kill some other non-assured one, but it has two problems: - a netns can kill non-assured conntracks in other namespace - we would start to 'over-subscribe' the affected/overlimit netns. Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
1 parent 56d52d4 commit 3e86638

File tree

1 file changed

+25
-18
lines changed

1 file changed

+25
-18
lines changed

net/netfilter/nf_conntrack_core.c

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -764,18 +764,20 @@ static noinline int early_drop(struct net *net, unsigned int _hash)
764764
{
765765
/* Use oldest entry, which is roughly LRU */
766766
struct nf_conntrack_tuple_hash *h;
767-
struct nf_conn *ct = NULL, *tmp;
767+
struct nf_conn *tmp;
768768
struct hlist_nulls_node *n;
769-
unsigned int i = 0, cnt = 0;
770-
int dropped = 0;
771-
unsigned int hash, sequence;
769+
unsigned int i, hash, sequence;
770+
struct nf_conn *ct = NULL;
772771
spinlock_t *lockp;
772+
bool ret = false;
773+
774+
i = 0;
773775

774776
local_bh_disable();
775777
restart:
776778
sequence = read_seqcount_begin(&nf_conntrack_generation);
777-
hash = scale_hash(_hash);
778-
for (; i < nf_conntrack_htable_size; i++) {
779+
for (; i < NF_CT_EVICTION_RANGE; i++) {
780+
hash = scale_hash(_hash++);
779781
lockp = &nf_conntrack_locks[hash % CONNTRACK_LOCKS];
780782
nf_conntrack_lock(lockp);
781783
if (read_seqcount_retry(&nf_conntrack_generation, sequence)) {
@@ -785,35 +787,40 @@ static noinline int early_drop(struct net *net, unsigned int _hash)
785787
hlist_nulls_for_each_entry_rcu(h, n, &nf_conntrack_hash[hash],
786788
hnnode) {
787789
tmp = nf_ct_tuplehash_to_ctrack(h);
788-
if (!test_bit(IPS_ASSURED_BIT, &tmp->status) &&
789-
!nf_ct_is_dying(tmp) &&
790-
atomic_inc_not_zero(&tmp->ct_general.use)) {
790+
791+
if (test_bit(IPS_ASSURED_BIT, &tmp->status) ||
792+
!net_eq(nf_ct_net(tmp), net) ||
793+
nf_ct_is_dying(tmp))
794+
continue;
795+
796+
if (atomic_inc_not_zero(&tmp->ct_general.use)) {
791797
ct = tmp;
792798
break;
793799
}
794-
cnt++;
795800
}
796801

797-
hash = (hash + 1) % nf_conntrack_htable_size;
798802
spin_unlock(lockp);
799-
800-
if (ct || cnt >= NF_CT_EVICTION_RANGE)
803+
if (ct)
801804
break;
802-
803805
}
806+
804807
local_bh_enable();
805808

806809
if (!ct)
807-
return dropped;
810+
return false;
808811

809-
if (del_timer(&ct->timeout)) {
812+
/* kill only if in same netns -- might have moved due to
813+
* SLAB_DESTROY_BY_RCU rules
814+
*/
815+
if (net_eq(nf_ct_net(ct), net) && del_timer(&ct->timeout)) {
810816
if (nf_ct_delete(ct, 0, 0)) {
811-
dropped = 1;
812817
NF_CT_STAT_INC_ATOMIC(net, early_drop);
818+
ret = true;
813819
}
814820
}
821+
815822
nf_ct_put(ct);
816-
return dropped;
823+
return ret;
817824
}
818825

819826
static struct nf_conn *

0 commit comments

Comments
 (0)