]> git.hungrycats.org Git - linux/commitdiff
ipv6: make exception cache less predictible
authorEric Dumazet <edumazet@google.com>
Sun, 29 Aug 2021 22:16:14 +0000 (15:16 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 2 Nov 2021 17:26:44 +0000 (18:26 +0100)
commit a00df2caffed3883c341d5685f830434312e4a43 upstream.

Even after commit 4785305c05b2 ("ipv6: use siphash in rt6_exception_hash()"),
an attacker can still use brute force to learn some secrets from a victim
linux host.

One way to defeat these attacks is to make the max depth of the hash
table bucket a random value.

Before this patch, each bucket of the hash table used to store exceptions
could contain 6 items under attack.

After the patch, each bucket would contains a random number of items,
between 6 and 10. The attacker can no longer infer secrets.

This is slightly increasing memory size used by the hash table,
we do not expect this to be a problem.

Following patch is dealing with the same issue in IPv4.

Fixes: 35732d01fe31 ("ipv6: introduce a hash table to store dst cache")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: Keyu Man <kman001@ucr.edu>
Cc: Wei Wang <weiwan@google.com>
Cc: Martin KaFai Lau <kafai@fb.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
[OP: adjusted context for 4.19 stable]
Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
net/ipv6/route.c

index 9bc806a4ded6071785af6acd8db43d0ee4d8072a..d04f3951c5fbc75f4d1bc52cda9f19646431d5d3 100644 (file)
@@ -1454,6 +1454,7 @@ static int rt6_insert_exception(struct rt6_info *nrt,
        struct rt6_exception_bucket *bucket;
        struct in6_addr *src_key = NULL;
        struct rt6_exception *rt6_ex;
+       int max_depth;
        int err = 0;
 
        spin_lock_bh(&rt6_exception_lock);
@@ -1515,7 +1516,9 @@ static int rt6_insert_exception(struct rt6_info *nrt,
        bucket->depth++;
        net->ipv6.rt6_stats->fib_rt_cache++;
 
-       if (bucket->depth > FIB6_MAX_DEPTH)
+       /* Randomize max depth to avoid some side channels attacks. */
+       max_depth = FIB6_MAX_DEPTH + prandom_u32_max(FIB6_MAX_DEPTH);
+       while (bucket->depth > max_depth)
                rt6_exception_remove_oldest(bucket);
 
 out: