提交 3b8cfaba 编写于 作者: E Eric Dumazet 提交者: Zheng Zengkai

ipv4: make exception cache less predictible

stable inclusion
from stable-5.10.65
commit 5867e20e1808acd0c832ddea2587e5ee49813874
bugzilla: 182361 https://gitee.com/openeuler/kernel/issues/I4EH3U

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=5867e20e1808acd0c832ddea2587e5ee49813874

--------------------------------

[ Upstream commit 67d6d681 ]

Even after commit 6457378f ("ipv4: use siphash instead of Jenkins in
fnhe_hashfun()"), 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,
by 50% in average, we do not expect this to be a problem.

This patch is more complex than the prior one (IPv6 equivalent),
because IPv4 was reusing the oldest entry.
Since we need to be able to evict more than one entry per
update_or_create_fnhe() call, I had to replace
fnhe_oldest() with fnhe_remove_oldest().

Also note that we will queue extra kfree_rcu() calls under stress,
which hopefully wont be a too big issue.

Fixes: 4895c771 ("ipv4: Add FIB nexthop exceptions.")
Signed-off-by: NEric Dumazet <edumazet@google.com>
Reported-by: NKeyu Man <kman001@ucr.edu>
Cc: Willy Tarreau <w@1wt.eu>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
Reviewed-by: NDavid Ahern <dsahern@kernel.org>
Tested-by: NDavid Ahern <dsahern@kernel.org>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
Signed-off-by: NSasha Levin <sashal@kernel.org>
Signed-off-by: NChen Jun <chenjun102@huawei.com>
Acked-by: NWeilong Chen <chenweilong@huawei.com>
Signed-off-by: NChen Jun <chenjun102@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 124802f7
...@@ -610,18 +610,25 @@ static void fnhe_flush_routes(struct fib_nh_exception *fnhe) ...@@ -610,18 +610,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_p = &hash->chain; ; fnhe_p = &fnhe->fnhe_next) {
for (fnhe = rcu_dereference(oldest->fnhe_next); fnhe; fnhe = rcu_dereference_protected(*fnhe_p,
fnhe = rcu_dereference(fnhe->fnhe_next)) { lockdep_is_held(&fnhe_lock));
if (time_before(fnhe->fnhe_stamp, oldest->fnhe_stamp)) if (!fnhe)
break;
if (!oldest ||
time_before(fnhe->fnhe_stamp, oldest->fnhe_stamp)) {
oldest = fnhe; oldest = fnhe;
oldest_p = fnhe_p;
}
} }
fnhe_flush_routes(oldest); fnhe_flush_routes(oldest);
return oldest; *oldest_p = oldest->fnhe_next;
kfree_rcu(oldest, rcu);
} }
static u32 fnhe_hashfun(__be32 daddr) static u32 fnhe_hashfun(__be32 daddr)
...@@ -700,16 +707,21 @@ static void update_or_create_fnhe(struct fib_nh_common *nhc, __be32 daddr, ...@@ -700,16 +707,21 @@ static void update_or_create_fnhe(struct fib_nh_common *nhc, __be32 daddr,
if (rt) if (rt)
fill_route_from_fnhe(rt, fnhe); fill_route_from_fnhe(rt, fnhe);
} else { } else {
if (depth > FNHE_RECLAIM_DEPTH) /* Randomize max depth to avoid some side channels attacks. */
fnhe = fnhe_oldest(hash); int max_depth = FNHE_RECLAIM_DEPTH +
else { prandom_u32_max(FNHE_RECLAIM_DEPTH);
fnhe = kzalloc(sizeof(*fnhe), GFP_ATOMIC);
if (!fnhe) while (depth > max_depth) {
goto out_unlock; fnhe_remove_oldest(hash);
depth--;
fnhe->fnhe_next = hash->chain;
rcu_assign_pointer(hash->chain, fnhe);
} }
fnhe = kzalloc(sizeof(*fnhe), GFP_ATOMIC);
if (!fnhe)
goto out_unlock;
fnhe->fnhe_next = hash->chain;
fnhe->fnhe_genid = genid; fnhe->fnhe_genid = genid;
fnhe->fnhe_daddr = daddr; fnhe->fnhe_daddr = daddr;
fnhe->fnhe_gw = gw; fnhe->fnhe_gw = gw;
...@@ -717,6 +729,8 @@ static void update_or_create_fnhe(struct fib_nh_common *nhc, __be32 daddr, ...@@ -717,6 +729,8 @@ static void update_or_create_fnhe(struct fib_nh_common *nhc, __be32 daddr,
fnhe->fnhe_mtu_locked = lock; fnhe->fnhe_mtu_locked = lock;
fnhe->fnhe_expires = max(1UL, expires); fnhe->fnhe_expires = max(1UL, expires);
rcu_assign_pointer(hash->chain, fnhe);
/* Exception created; mark the cached routes for the nexthop /* Exception created; mark the cached routes for the nexthop
* stale, so anyone caching it rechecks if this exception * stale, so anyone caching it rechecks if this exception
* applies to them. * applies to them.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
新手
引导
客服 返回
顶部