Commit 63cad4c7 authored by David S. Miller's avatar David S. Miller

Merge branch 'inet-exceptions-less-predictable'

Eric Dumazet says:

====================
inet: make exception handling less predictible

This second round of patches is addressing Keyu Man recommendations
to make linux hosts more robust against a class of brute force attacks.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 9dfa859d 67d6d681
......@@ -587,18 +587,25 @@ static void fnhe_flush_routes(struct fib_nh_exception *fnhe)
}
}
static struct fib_nh_exception *fnhe_oldest(struct fnhe_hash_bucket *hash)
static void fnhe_remove_oldest(struct fnhe_hash_bucket *hash)
{
struct fib_nh_exception *fnhe, *oldest;
struct fib_nh_exception __rcu **fnhe_p, **oldest_p;
struct fib_nh_exception *fnhe, *oldest = NULL;
oldest = rcu_dereference(hash->chain);
for (fnhe = rcu_dereference(oldest->fnhe_next); fnhe;
fnhe = rcu_dereference(fnhe->fnhe_next)) {
if (time_before(fnhe->fnhe_stamp, oldest->fnhe_stamp))
for (fnhe_p = &hash->chain; ; fnhe_p = &fnhe->fnhe_next) {
fnhe = rcu_dereference_protected(*fnhe_p,
lockdep_is_held(&fnhe_lock));
if (!fnhe)
break;
if (!oldest ||
time_before(fnhe->fnhe_stamp, oldest->fnhe_stamp)) {
oldest = fnhe;
oldest_p = fnhe_p;
}
}
fnhe_flush_routes(oldest);
return oldest;
*oldest_p = oldest->fnhe_next;
kfree_rcu(oldest, rcu);
}
static u32 fnhe_hashfun(__be32 daddr)
......@@ -677,16 +684,21 @@ static void update_or_create_fnhe(struct fib_nh_common *nhc, __be32 daddr,
if (rt)
fill_route_from_fnhe(rt, fnhe);
} else {
if (depth > FNHE_RECLAIM_DEPTH)
fnhe = fnhe_oldest(hash);
else {
fnhe = kzalloc(sizeof(*fnhe), GFP_ATOMIC);
if (!fnhe)
goto out_unlock;
fnhe->fnhe_next = hash->chain;
rcu_assign_pointer(hash->chain, fnhe);
/* Randomize max depth to avoid some side channels attacks. */
int max_depth = FNHE_RECLAIM_DEPTH +
prandom_u32_max(FNHE_RECLAIM_DEPTH);
while (depth > max_depth) {
fnhe_remove_oldest(hash);
depth--;
}
fnhe = kzalloc(sizeof(*fnhe), GFP_ATOMIC);
if (!fnhe)
goto out_unlock;
fnhe->fnhe_next = hash->chain;
fnhe->fnhe_genid = genid;
fnhe->fnhe_daddr = daddr;
fnhe->fnhe_gw = gw;
......@@ -694,6 +706,8 @@ static void update_or_create_fnhe(struct fib_nh_common *nhc, __be32 daddr,
fnhe->fnhe_mtu_locked = lock;
fnhe->fnhe_expires = max(1UL, expires);
rcu_assign_pointer(hash->chain, fnhe);
/* Exception created; mark the cached routes for the nexthop
* stale, so anyone caching it rechecks if this exception
* applies to them.
......
......@@ -1657,6 +1657,7 @@ static int rt6_insert_exception(struct rt6_info *nrt,
struct in6_addr *src_key = NULL;
struct rt6_exception *rt6_ex;
struct fib6_nh *nh = res->nh;
int max_depth;
int err = 0;
spin_lock_bh(&rt6_exception_lock);
......@@ -1711,7 +1712,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:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment