[rh7,11/19] ms/netfilter: conntrack: fix calculation of next bucket number in early_drop

Submitted by Konstantin Khorenko on May 22, 2020, 8:10 a.m.

Details

Message ID 20200522081056.28326-12-khorenko@virtuozzo.com
State New
Series "netfilter: conntrack: fix false-positive compiler warning in early_drop()"
Headers show

Commit Message

Konstantin Khorenko May 22, 2020, 8:10 a.m.
From: Vasily Khoruzhick <vasilykh@arista.com>

If there's no entry to drop in bucket that corresponds to the hash,
early_drop() should look for it in other buckets. But since it increments
hash instead of bucket number, it actually looks in the same bucket 8
times: hsize is 16k by default (14 bits) and hash is 32-bit value, so
reciprocal_scale(hash, hsize) returns the same value for hash..hash+7 in
most cases.

Fix it by increasing bucket number instead of hash and rename _hash
to bucket to avoid future confusion.

Fixes: 3e86638e9a0b ("netfilter: conntrack: consider ct netns in early_drop logic")
Cc: <stable@vger.kernel.org> # v4.7+
Signed-off-by: Vasily Khoruzhick <vasilykh@arista.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

https://jira.sw.ru/browse/PSBM-103515

(cherry picked from commit f393808dc64149ccd0e5a8427505ba2974a59854)
Signed-off-by: Konstantin Khorenko <khorenko@virtuozzo.com>
---
 net/netfilter/nf_conntrack_core.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

Patch hide | download patch | download mbox

diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 91f0940bac57a..aca113963fed9 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -887,13 +887,13 @@  EXPORT_SYMBOL_GPL(nf_conntrack_tuple_taken);
 
 /* There's a small race here where we may free a just-assured
    connection.  Too bad: we're in trouble anyway. */
-static noinline int early_drop(struct net *net, unsigned int _hash)
+static noinline int early_drop(struct net *net, unsigned int hash)
 {
 	/* Use oldest entry, which is roughly LRU */
 	struct nf_conntrack_tuple_hash *h;
 	struct nf_conn *tmp;
 	struct hlist_nulls_node *n;
-	unsigned int i, hash, sequence;
+	unsigned int i, bucket, sequence;
 	struct nf_conn *ct = NULL;
 	spinlock_t *lockp;
 	bool ret = false;
@@ -904,14 +904,18 @@  static noinline int early_drop(struct net *net, unsigned int _hash)
 restart:
 	sequence = read_seqcount_begin(&nf_conntrack_generation);
 	for (; i < NF_CT_EVICTION_RANGE; i++) {
-		hash = scale_hash(_hash++);
-		lockp = &nf_conntrack_locks[hash % CONNTRACK_LOCKS];
+		if (!i)
+			bucket = scale_hash(hash++);
+		else
+			bucket = (bucket + 1) % nf_conntrack_htable_size;
+
+		lockp = &nf_conntrack_locks[bucket % CONNTRACK_LOCKS];
 		spin_lock(lockp);
 		if (read_seqcount_retry(&nf_conntrack_generation, sequence)) {
 			spin_unlock(lockp);
 			goto restart;
 		}
-		hlist_nulls_for_each_entry_rcu(h, n, &nf_conntrack_hash[hash],
+		hlist_nulls_for_each_entry_rcu(h, n, &nf_conntrack_hash[bucket],
 					       hnnode) {
 			tmp = nf_ct_tuplehash_to_ctrack(h);