Skip to content

Commit c9c3b68

Browse files
Florian Westphalummakynes
authored andcommitted
netfilter: conntrack: make max chain length random
Similar to commit 67d6d68 ("ipv4: make exception cache less predictible"): Use a random drop length to make it harder to detect when entries were hashed to same bucket list. Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
1 parent 310e2d4 commit c9c3b68

File tree

1 file changed

+11
-6
lines changed

1 file changed

+11
-6
lines changed

net/netfilter/nf_conntrack_core.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ static __read_mostly bool nf_conntrack_locks_all;
7777
#define GC_SCAN_INTERVAL (120u * HZ)
7878
#define GC_SCAN_MAX_DURATION msecs_to_jiffies(10)
7979

80-
#define MAX_CHAINLEN 64u
80+
#define MIN_CHAINLEN 8u
81+
#define MAX_CHAINLEN (32u - MIN_CHAINLEN)
8182

8283
static struct conntrack_gc_work conntrack_gc_work;
8384

@@ -842,6 +843,7 @@ nf_conntrack_hash_check_insert(struct nf_conn *ct)
842843
unsigned int hash, reply_hash;
843844
struct nf_conntrack_tuple_hash *h;
844845
struct hlist_nulls_node *n;
846+
unsigned int max_chainlen;
845847
unsigned int chainlen = 0;
846848
unsigned int sequence;
847849
int err = -EEXIST;
@@ -857,13 +859,15 @@ nf_conntrack_hash_check_insert(struct nf_conn *ct)
857859
&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
858860
} while (nf_conntrack_double_lock(net, hash, reply_hash, sequence));
859861

862+
max_chainlen = MIN_CHAINLEN + prandom_u32_max(MAX_CHAINLEN);
863+
860864
/* See if there's one in the list already, including reverse */
861865
hlist_nulls_for_each_entry(h, n, &nf_conntrack_hash[hash], hnnode) {
862866
if (nf_ct_key_equal(h, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
863867
zone, net))
864868
goto out;
865869

866-
if (chainlen++ > MAX_CHAINLEN)
870+
if (chainlen++ > max_chainlen)
867871
goto chaintoolong;
868872
}
869873

@@ -873,7 +877,7 @@ nf_conntrack_hash_check_insert(struct nf_conn *ct)
873877
if (nf_ct_key_equal(h, &ct->tuplehash[IP_CT_DIR_REPLY].tuple,
874878
zone, net))
875879
goto out;
876-
if (chainlen++ > MAX_CHAINLEN)
880+
if (chainlen++ > max_chainlen)
877881
goto chaintoolong;
878882
}
879883

@@ -1103,8 +1107,8 @@ nf_ct_resolve_clash(struct sk_buff *skb, struct nf_conntrack_tuple_hash *h,
11031107
int
11041108
__nf_conntrack_confirm(struct sk_buff *skb)
11051109
{
1110+
unsigned int chainlen = 0, sequence, max_chainlen;
11061111
const struct nf_conntrack_zone *zone;
1107-
unsigned int chainlen = 0, sequence;
11081112
unsigned int hash, reply_hash;
11091113
struct nf_conntrack_tuple_hash *h;
11101114
struct nf_conn *ct;
@@ -1168,14 +1172,15 @@ __nf_conntrack_confirm(struct sk_buff *skb)
11681172
goto dying;
11691173
}
11701174

1175+
max_chainlen = MIN_CHAINLEN + prandom_u32_max(MAX_CHAINLEN);
11711176
/* See if there's one in the list already, including reverse:
11721177
NAT could have grabbed it without realizing, since we're
11731178
not in the hash. If there is, we lost race. */
11741179
hlist_nulls_for_each_entry(h, n, &nf_conntrack_hash[hash], hnnode) {
11751180
if (nf_ct_key_equal(h, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
11761181
zone, net))
11771182
goto out;
1178-
if (chainlen++ > MAX_CHAINLEN)
1183+
if (chainlen++ > max_chainlen)
11791184
goto chaintoolong;
11801185
}
11811186

@@ -1184,7 +1189,7 @@ __nf_conntrack_confirm(struct sk_buff *skb)
11841189
if (nf_ct_key_equal(h, &ct->tuplehash[IP_CT_DIR_REPLY].tuple,
11851190
zone, net))
11861191
goto out;
1187-
if (chainlen++ > MAX_CHAINLEN) {
1192+
if (chainlen++ > max_chainlen) {
11881193
chaintoolong:
11891194
nf_ct_add_to_dying_list(ct);
11901195
NF_CT_STAT_INC(net, chaintoolong);

0 commit comments

Comments
 (0)