| From b6f9837c1843d6dc02ae03942ad6fd2d9b8df2ff Mon Sep 17 00:00:00 2001 |
| From: Eric Dumazet <edumazet@google.com> |
| Date: Wed, 27 Mar 2019 08:21:30 -0700 |
| Subject: netns: provide pure entropy for net_hash_mix() |
| |
| [ Upstream commit 355b98553789b646ed97ad801a619ff898471b92 ] |
| |
| net_hash_mix() currently uses kernel address of a struct net, |
| and is used in many places that could be used to reveal this |
| address to a patient attacker, thus defeating KASLR, for |
| the typical case (initial net namespace, &init_net is |
| not dynamically allocated) |
| |
| I believe the original implementation tried to avoid spending |
| too many cycles in this function, but security comes first. |
| |
| Also provide entropy regardless of CONFIG_NET_NS. |
| |
| Fixes: 0b4419162aa6 ("netns: introduce the net_hash_mix "salt" for hashes") |
| Signed-off-by: Eric Dumazet <edumazet@google.com> |
| Reported-by: Amit Klein <aksecurity@gmail.com> |
| Reported-by: Benny Pinkas <benny@pinkas.net> |
| Cc: Pavel Emelyanov <xemul@openvz.org> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| include/net/net_namespace.h | 1 + |
| include/net/netns/hash.h | 10 ++-------- |
| net/core/net_namespace.c | 1 + |
| 3 files changed, 4 insertions(+), 8 deletions(-) |
| |
| diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h |
| index 99d4148e0f90..1c3126c14930 100644 |
| --- a/include/net/net_namespace.h |
| +++ b/include/net/net_namespace.h |
| @@ -58,6 +58,7 @@ struct net { |
| */ |
| spinlock_t rules_mod_lock; |
| |
| + u32 hash_mix; |
| atomic64_t cookie_gen; |
| |
| struct list_head list; /* list of network namespaces */ |
| diff --git a/include/net/netns/hash.h b/include/net/netns/hash.h |
| index 16a842456189..d9b665151f3d 100644 |
| --- a/include/net/netns/hash.h |
| +++ b/include/net/netns/hash.h |
| @@ -2,16 +2,10 @@ |
| #ifndef __NET_NS_HASH_H__ |
| #define __NET_NS_HASH_H__ |
| |
| -#include <asm/cache.h> |
| - |
| -struct net; |
| +#include <net/net_namespace.h> |
| |
| static inline u32 net_hash_mix(const struct net *net) |
| { |
| -#ifdef CONFIG_NET_NS |
| - return (u32)(((unsigned long)net) >> ilog2(sizeof(*net))); |
| -#else |
| - return 0; |
| -#endif |
| + return net->hash_mix; |
| } |
| #endif |
| diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c |
| index b02fb19df2cc..40c249c574c1 100644 |
| --- a/net/core/net_namespace.c |
| +++ b/net/core/net_namespace.c |
| @@ -304,6 +304,7 @@ static __net_init int setup_net(struct net *net, struct user_namespace *user_ns) |
| |
| refcount_set(&net->count, 1); |
| refcount_set(&net->passive, 1); |
| + get_random_bytes(&net->hash_mix, sizeof(u32)); |
| net->dev_base_seq = 1; |
| net->user_ns = user_ns; |
| idr_init(&net->netns_ids); |
| -- |
| 2.19.1 |
| |