aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/inet_sock.h4
-rw-r--r--net/ipv4/af_inet.c27
-rw-r--r--net/ipv4/inet_hashtables.c4
-rw-r--r--net/ipv4/udp.c6
-rw-r--r--net/ipv6/af_inet6.c5
-rw-r--r--net/ipv6/inet6_hashtables.c15
-rw-r--r--net/ipv6/udp.c17
-rw-r--r--net/rds/connection.c12
8 files changed, 44 insertions, 46 deletions
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index 7a6c7f80a8fd..1833c3f389ee 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -204,10 +204,6 @@ static inline void inet_sk_copy_descendant(struct sock *sk_to,
204 204
205int inet_sk_rebuild_header(struct sock *sk); 205int inet_sk_rebuild_header(struct sock *sk);
206 206
207extern u32 inet_ehash_secret;
208extern u32 ipv6_hash_secret;
209void build_ehash_secret(void);
210
211static inline unsigned int __inet_ehashfn(const __be32 laddr, 207static inline unsigned int __inet_ehashfn(const __be32 laddr,
212 const __u16 lport, 208 const __u16 lport,
213 const __be32 faddr, 209 const __be32 faddr,
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 4049906010f7..9433a6186f54 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -245,29 +245,6 @@ out:
245} 245}
246EXPORT_SYMBOL(inet_listen); 246EXPORT_SYMBOL(inet_listen);
247 247
248u32 inet_ehash_secret __read_mostly;
249EXPORT_SYMBOL(inet_ehash_secret);
250
251u32 ipv6_hash_secret __read_mostly;
252EXPORT_SYMBOL(ipv6_hash_secret);
253
254/*
255 * inet_ehash_secret must be set exactly once, and to a non nul value
256 * ipv6_hash_secret must be set exactly once.
257 */
258void build_ehash_secret(void)
259{
260 u32 rnd;
261
262 do {
263 get_random_bytes(&rnd, sizeof(rnd));
264 } while (rnd == 0);
265
266 if (cmpxchg(&inet_ehash_secret, 0, rnd) == 0)
267 get_random_bytes(&ipv6_hash_secret, sizeof(ipv6_hash_secret));
268}
269EXPORT_SYMBOL(build_ehash_secret);
270
271/* 248/*
272 * Create an inet socket. 249 * Create an inet socket.
273 */ 250 */
@@ -284,10 +261,6 @@ static int inet_create(struct net *net, struct socket *sock, int protocol,
284 int try_loading_module = 0; 261 int try_loading_module = 0;
285 int err; 262 int err;
286 263
287 if (unlikely(!inet_ehash_secret))
288 if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM)
289 build_ehash_secret();
290
291 sock->state = SS_UNCONNECTED; 264 sock->state = SS_UNCONNECTED;
292 265
293 /* Look for the requested type/protocol pair. */ 266 /* Look for the requested type/protocol pair. */
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 18aa668d0cc9..8b9cf279450d 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -28,6 +28,10 @@ static unsigned int inet_ehashfn(struct net *net, const __be32 laddr,
28 const __u16 lport, const __be32 faddr, 28 const __u16 lport, const __be32 faddr,
29 const __be16 fport) 29 const __be16 fport)
30{ 30{
31 static u32 inet_ehash_secret __read_mostly;
32
33 net_get_random_once(&inet_ehash_secret, sizeof(inet_ehash_secret));
34
31 return __inet_ehashfn(laddr, lport, faddr, fport, 35 return __inet_ehashfn(laddr, lport, faddr, fport,
32 inet_ehash_secret + net_hash_mix(net)); 36 inet_ehash_secret + net_hash_mix(net));
33} 37}
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index b4437c7db6ce..89909dd730dd 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -411,8 +411,12 @@ static unsigned int udp_ehashfn(struct net *net, const __be32 laddr,
411 const __u16 lport, const __be32 faddr, 411 const __u16 lport, const __be32 faddr,
412 const __be16 fport) 412 const __be16 fport)
413{ 413{
414 static u32 udp_ehash_secret __read_mostly;
415
416 net_get_random_once(&udp_ehash_secret, sizeof(udp_ehash_secret));
417
414 return __inet_ehashfn(laddr, lport, faddr, fport, 418 return __inet_ehashfn(laddr, lport, faddr, fport,
415 inet_ehash_secret + net_hash_mix(net)); 419 udp_ehash_secret + net_hash_mix(net));
416} 420}
417 421
418 422
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index a2cb07cd3850..20af1fb81c83 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -110,11 +110,6 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol,
110 int try_loading_module = 0; 110 int try_loading_module = 0;
111 int err; 111 int err;
112 112
113 if (sock->type != SOCK_RAW &&
114 sock->type != SOCK_DGRAM &&
115 !inet_ehash_secret)
116 build_ehash_secret();
117
118 /* Look for the requested type/protocol pair. */ 113 /* Look for the requested type/protocol pair. */
119lookup_protocol: 114lookup_protocol:
120 err = -ESOCKTNOSUPPORT; 115 err = -ESOCKTNOSUPPORT;
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index fa7dd3856c55..262e13c02ec2 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -29,10 +29,19 @@ static unsigned int inet6_ehashfn(struct net *net,
29 const struct in6_addr *faddr, 29 const struct in6_addr *faddr,
30 const __be16 fport) 30 const __be16 fport)
31{ 31{
32 const u32 lhash = (__force u32)laddr->s6_addr32[3]; 32 static u32 inet6_ehash_secret __read_mostly;
33 const u32 fhash = __ipv6_addr_jhash(faddr, ipv6_hash_secret); 33 static u32 ipv6_hash_secret __read_mostly;
34
35 u32 lhash, fhash;
36
37 net_get_random_once(&inet6_ehash_secret, sizeof(inet6_ehash_secret));
38 net_get_random_once(&ipv6_hash_secret, sizeof(ipv6_hash_secret));
39
40 lhash = (__force u32)laddr->s6_addr32[3];
41 fhash = __ipv6_addr_jhash(faddr, ipv6_hash_secret);
42
34 return __inet6_ehashfn(lhash, lport, fhash, fport, 43 return __inet6_ehashfn(lhash, lport, fhash, fport,
35 inet_ehash_secret + net_hash_mix(net)); 44 inet6_ehash_secret + net_hash_mix(net));
36} 45}
37 46
38static int inet6_sk_ehashfn(const struct sock *sk) 47static int inet6_sk_ehashfn(const struct sock *sk)
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 324bd36c23bc..44fc4e3d661f 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -59,10 +59,21 @@ static unsigned int udp6_ehashfn(struct net *net,
59 const struct in6_addr *faddr, 59 const struct in6_addr *faddr,
60 const __be16 fport) 60 const __be16 fport)
61{ 61{
62 const u32 lhash = (__force u32)laddr->s6_addr32[3]; 62 static u32 udp6_ehash_secret __read_mostly;
63 const u32 fhash = __ipv6_addr_jhash(faddr, ipv6_hash_secret); 63 static u32 udp_ipv6_hash_secret __read_mostly;
64
65 u32 lhash, fhash;
66
67 net_get_random_once(&udp6_ehash_secret,
68 sizeof(udp6_ehash_secret));
69 net_get_random_once(&udp_ipv6_hash_secret,
70 sizeof(udp_ipv6_hash_secret));
71
72 lhash = (__force u32)laddr->s6_addr32[3];
73 fhash = __ipv6_addr_jhash(faddr, udp_ipv6_hash_secret);
74
64 return __inet6_ehashfn(lhash, lport, fhash, fport, 75 return __inet6_ehashfn(lhash, lport, fhash, fport,
65 inet_ehash_secret + net_hash_mix(net)); 76 udp_ipv6_hash_secret + net_hash_mix(net));
66} 77}
67 78
68int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) 79int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2)
diff --git a/net/rds/connection.c b/net/rds/connection.c
index 45e23660437a..378c3a6acf84 100644
--- a/net/rds/connection.c
+++ b/net/rds/connection.c
@@ -51,10 +51,16 @@ static struct kmem_cache *rds_conn_slab;
51 51
52static struct hlist_head *rds_conn_bucket(__be32 laddr, __be32 faddr) 52static struct hlist_head *rds_conn_bucket(__be32 laddr, __be32 faddr)
53{ 53{
54 static u32 rds_hash_secret __read_mostly;
55
56 unsigned long hash;
57
58 net_get_random_once(&rds_hash_secret, sizeof(rds_hash_secret));
59
54 /* Pass NULL, don't need struct net for hash */ 60 /* Pass NULL, don't need struct net for hash */
55 unsigned long hash = __inet_ehashfn(be32_to_cpu(laddr), 0, 61 hash = __inet_ehashfn(be32_to_cpu(laddr), 0,
56 be32_to_cpu(faddr), 0, 62 be32_to_cpu(faddr), 0,
57 inet_ehash_secret); 63 rds_hash_secret);
58 return &rds_conn_hash[hash & RDS_CONNECTION_HASH_MASK]; 64 return &rds_conn_hash[hash & RDS_CONNECTION_HASH_MASK];
59} 65}
60 66