diff options
-rw-r--r-- | arch/x86/kernel/jump_label.c | 25 | ||||
-rw-r--r-- | include/linux/jump_label.h | 10 | ||||
-rw-r--r-- | include/linux/jump_label_ratelimit.h | 2 | ||||
-rw-r--r-- | include/linux/net.h | 25 | ||||
-rw-r--r-- | include/net/inet6_hashtables.h | 28 | ||||
-rw-r--r-- | include/net/inet_sock.h | 26 | ||||
-rw-r--r-- | include/net/ipv6.h | 4 | ||||
-rw-r--r-- | include/net/tcp.h | 3 | ||||
-rw-r--r-- | init/main.c | 7 | ||||
-rw-r--r-- | kernel/jump_label.c | 5 | ||||
-rw-r--r-- | net/core/secure_seq.c | 14 | ||||
-rw-r--r-- | net/core/utils.c | 48 | ||||
-rw-r--r-- | net/ipv4/af_inet.c | 27 | ||||
-rw-r--r-- | net/ipv4/inet_hashtables.c | 25 | ||||
-rw-r--r-- | net/ipv4/syncookies.c | 15 | ||||
-rw-r--r-- | net/ipv4/sysctl_net_ipv4.c | 5 | ||||
-rw-r--r-- | net/ipv4/tcp_fastopen.c | 27 | ||||
-rw-r--r-- | net/ipv4/udp.c | 20 | ||||
-rw-r--r-- | net/ipv6/af_inet6.c | 5 | ||||
-rw-r--r-- | net/ipv6/inet6_hashtables.c | 33 | ||||
-rw-r--r-- | net/ipv6/syncookies.c | 12 | ||||
-rw-r--r-- | net/ipv6/udp.c | 31 | ||||
-rw-r--r-- | net/rds/connection.c | 12 |
23 files changed, 278 insertions, 131 deletions
diff --git a/arch/x86/kernel/jump_label.c b/arch/x86/kernel/jump_label.c index ee11b7dfbfbb..26d5a55a2736 100644 --- a/arch/x86/kernel/jump_label.c +++ b/arch/x86/kernel/jump_label.c | |||
@@ -42,15 +42,27 @@ static void __jump_label_transform(struct jump_entry *entry, | |||
42 | int init) | 42 | int init) |
43 | { | 43 | { |
44 | union jump_code_union code; | 44 | union jump_code_union code; |
45 | const unsigned char default_nop[] = { STATIC_KEY_INIT_NOP }; | ||
45 | const unsigned char *ideal_nop = ideal_nops[NOP_ATOMIC5]; | 46 | const unsigned char *ideal_nop = ideal_nops[NOP_ATOMIC5]; |
46 | 47 | ||
47 | if (type == JUMP_LABEL_ENABLE) { | 48 | if (type == JUMP_LABEL_ENABLE) { |
48 | /* | 49 | if (init) { |
49 | * We are enabling this jump label. If it is not a nop | 50 | /* |
50 | * then something must have gone wrong. | 51 | * Jump label is enabled for the first time. |
51 | */ | 52 | * So we expect a default_nop... |
52 | if (unlikely(memcmp((void *)entry->code, ideal_nop, 5) != 0)) | 53 | */ |
53 | bug_at((void *)entry->code, __LINE__); | 54 | if (unlikely(memcmp((void *)entry->code, default_nop, 5) |
55 | != 0)) | ||
56 | bug_at((void *)entry->code, __LINE__); | ||
57 | } else { | ||
58 | /* | ||
59 | * ...otherwise expect an ideal_nop. Otherwise | ||
60 | * something went horribly wrong. | ||
61 | */ | ||
62 | if (unlikely(memcmp((void *)entry->code, ideal_nop, 5) | ||
63 | != 0)) | ||
64 | bug_at((void *)entry->code, __LINE__); | ||
65 | } | ||
54 | 66 | ||
55 | code.jump = 0xe9; | 67 | code.jump = 0xe9; |
56 | code.offset = entry->target - | 68 | code.offset = entry->target - |
@@ -63,7 +75,6 @@ static void __jump_label_transform(struct jump_entry *entry, | |||
63 | * are converting the default nop to the ideal nop. | 75 | * are converting the default nop to the ideal nop. |
64 | */ | 76 | */ |
65 | if (init) { | 77 | if (init) { |
66 | const unsigned char default_nop[] = { STATIC_KEY_INIT_NOP }; | ||
67 | if (unlikely(memcmp((void *)entry->code, default_nop, 5) != 0)) | 78 | if (unlikely(memcmp((void *)entry->code, default_nop, 5) != 0)) |
68 | bug_at((void *)entry->code, __LINE__); | 79 | bug_at((void *)entry->code, __LINE__); |
69 | } else { | 80 | } else { |
diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h index a5079072da66..e96be7245717 100644 --- a/include/linux/jump_label.h +++ b/include/linux/jump_label.h | |||
@@ -48,6 +48,13 @@ | |||
48 | 48 | ||
49 | #include <linux/types.h> | 49 | #include <linux/types.h> |
50 | #include <linux/compiler.h> | 50 | #include <linux/compiler.h> |
51 | #include <linux/bug.h> | ||
52 | |||
53 | extern bool static_key_initialized; | ||
54 | |||
55 | #define STATIC_KEY_CHECK_USE() WARN(!static_key_initialized, \ | ||
56 | "%s used before call to jump_label_init", \ | ||
57 | __func__) | ||
51 | 58 | ||
52 | #if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL) | 59 | #if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL) |
53 | 60 | ||
@@ -128,6 +135,7 @@ struct static_key { | |||
128 | 135 | ||
129 | static __always_inline void jump_label_init(void) | 136 | static __always_inline void jump_label_init(void) |
130 | { | 137 | { |
138 | static_key_initialized = true; | ||
131 | } | 139 | } |
132 | 140 | ||
133 | static __always_inline bool static_key_false(struct static_key *key) | 141 | static __always_inline bool static_key_false(struct static_key *key) |
@@ -146,11 +154,13 @@ static __always_inline bool static_key_true(struct static_key *key) | |||
146 | 154 | ||
147 | static inline void static_key_slow_inc(struct static_key *key) | 155 | static inline void static_key_slow_inc(struct static_key *key) |
148 | { | 156 | { |
157 | STATIC_KEY_CHECK_USE(); | ||
149 | atomic_inc(&key->enabled); | 158 | atomic_inc(&key->enabled); |
150 | } | 159 | } |
151 | 160 | ||
152 | static inline void static_key_slow_dec(struct static_key *key) | 161 | static inline void static_key_slow_dec(struct static_key *key) |
153 | { | 162 | { |
163 | STATIC_KEY_CHECK_USE(); | ||
154 | atomic_dec(&key->enabled); | 164 | atomic_dec(&key->enabled); |
155 | } | 165 | } |
156 | 166 | ||
diff --git a/include/linux/jump_label_ratelimit.h b/include/linux/jump_label_ratelimit.h index 113788389b3d..089f70f83e97 100644 --- a/include/linux/jump_label_ratelimit.h +++ b/include/linux/jump_label_ratelimit.h | |||
@@ -23,12 +23,14 @@ struct static_key_deferred { | |||
23 | }; | 23 | }; |
24 | static inline void static_key_slow_dec_deferred(struct static_key_deferred *key) | 24 | static inline void static_key_slow_dec_deferred(struct static_key_deferred *key) |
25 | { | 25 | { |
26 | STATIC_KEY_CHECK_USE(); | ||
26 | static_key_slow_dec(&key->key); | 27 | static_key_slow_dec(&key->key); |
27 | } | 28 | } |
28 | static inline void | 29 | static inline void |
29 | jump_label_rate_limit(struct static_key_deferred *key, | 30 | jump_label_rate_limit(struct static_key_deferred *key, |
30 | unsigned long rl) | 31 | unsigned long rl) |
31 | { | 32 | { |
33 | STATIC_KEY_CHECK_USE(); | ||
32 | } | 34 | } |
33 | #endif /* HAVE_JUMP_LABEL */ | 35 | #endif /* HAVE_JUMP_LABEL */ |
34 | #endif /* _LINUX_JUMP_LABEL_RATELIMIT_H */ | 36 | #endif /* _LINUX_JUMP_LABEL_RATELIMIT_H */ |
diff --git a/include/linux/net.h b/include/linux/net.h index ca9ec8540905..a489705f6fa3 100644 --- a/include/linux/net.h +++ b/include/linux/net.h | |||
@@ -239,6 +239,31 @@ do { \ | |||
239 | #define net_random() prandom_u32() | 239 | #define net_random() prandom_u32() |
240 | #define net_srandom(seed) prandom_seed((__force u32)(seed)) | 240 | #define net_srandom(seed) prandom_seed((__force u32)(seed)) |
241 | 241 | ||
242 | bool __net_get_random_once(void *buf, int nbytes, bool *done, | ||
243 | struct static_key *done_key); | ||
244 | |||
245 | #ifdef HAVE_JUMP_LABEL | ||
246 | #define ___NET_RANDOM_STATIC_KEY_INIT ((struct static_key) \ | ||
247 | { .enabled = ATOMIC_INIT(0), .entries = (void *)1 }) | ||
248 | #else /* !HAVE_JUMP_LABEL */ | ||
249 | #define ___NET_RANDOM_STATIC_KEY_INIT STATIC_KEY_INIT_FALSE | ||
250 | #endif /* HAVE_JUMP_LABEL */ | ||
251 | |||
252 | /* BE CAREFUL: this function is not interrupt safe */ | ||
253 | #define net_get_random_once(buf, nbytes) \ | ||
254 | ({ \ | ||
255 | bool ___ret = false; \ | ||
256 | static bool ___done = false; \ | ||
257 | static struct static_key ___done_key = \ | ||
258 | ___NET_RANDOM_STATIC_KEY_INIT; \ | ||
259 | if (!static_key_true(&___done_key)) \ | ||
260 | ___ret = __net_get_random_once(buf, \ | ||
261 | nbytes, \ | ||
262 | &___done, \ | ||
263 | &___done_key); \ | ||
264 | ___ret; \ | ||
265 | }) | ||
266 | |||
242 | int kernel_sendmsg(struct socket *sock, struct msghdr *msg, struct kvec *vec, | 267 | int kernel_sendmsg(struct socket *sock, struct msghdr *msg, struct kvec *vec, |
243 | size_t num, size_t len); | 268 | size_t num, size_t len); |
244 | int kernel_recvmsg(struct socket *sock, struct msghdr *msg, struct kvec *vec, | 269 | int kernel_recvmsg(struct socket *sock, struct msghdr *msg, struct kvec *vec, |
diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h index a105d1a2fc00..ae0613544308 100644 --- a/include/net/inet6_hashtables.h +++ b/include/net/inet6_hashtables.h | |||
@@ -28,28 +28,14 @@ | |||
28 | 28 | ||
29 | struct inet_hashinfo; | 29 | struct inet_hashinfo; |
30 | 30 | ||
31 | static inline unsigned int inet6_ehashfn(struct net *net, | 31 | static inline unsigned int __inet6_ehashfn(const u32 lhash, |
32 | const struct in6_addr *laddr, const u16 lport, | 32 | const u16 lport, |
33 | const struct in6_addr *faddr, const __be16 fport) | 33 | const u32 fhash, |
34 | const __be16 fport, | ||
35 | const u32 initval) | ||
34 | { | 36 | { |
35 | u32 ports = (((u32)lport) << 16) | (__force u32)fport; | 37 | const u32 ports = (((u32)lport) << 16) | (__force u32)fport; |
36 | 38 | return jhash_3words(lhash, fhash, ports, initval); | |
37 | return jhash_3words((__force u32)laddr->s6_addr32[3], | ||
38 | ipv6_addr_jhash(faddr), | ||
39 | ports, | ||
40 | inet_ehash_secret + net_hash_mix(net)); | ||
41 | } | ||
42 | |||
43 | static inline int inet6_sk_ehashfn(const struct sock *sk) | ||
44 | { | ||
45 | const struct inet_sock *inet = inet_sk(sk); | ||
46 | const struct in6_addr *laddr = &sk->sk_v6_rcv_saddr; | ||
47 | const struct in6_addr *faddr = &sk->sk_v6_daddr; | ||
48 | const __u16 lport = inet->inet_num; | ||
49 | const __be16 fport = inet->inet_dport; | ||
50 | struct net *net = sock_net(sk); | ||
51 | |||
52 | return inet6_ehashfn(net, laddr, lport, faddr, fport); | ||
53 | } | 39 | } |
54 | 40 | ||
55 | int __inet6_hash(struct sock *sk, struct inet_timewait_sock *twp); | 41 | int __inet6_hash(struct sock *sk, struct inet_timewait_sock *twp); |
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index 06da91efbc83..1833c3f389ee 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h | |||
@@ -204,30 +204,16 @@ static inline void inet_sk_copy_descendant(struct sock *sk_to, | |||
204 | 204 | ||
205 | int inet_sk_rebuild_header(struct sock *sk); | 205 | int inet_sk_rebuild_header(struct sock *sk); |
206 | 206 | ||
207 | extern u32 inet_ehash_secret; | 207 | static inline unsigned int __inet_ehashfn(const __be32 laddr, |
208 | extern u32 ipv6_hash_secret; | 208 | const __u16 lport, |
209 | void build_ehash_secret(void); | 209 | const __be32 faddr, |
210 | 210 | const __be16 fport, | |
211 | static inline unsigned int inet_ehashfn(struct net *net, | 211 | u32 initval) |
212 | const __be32 laddr, const __u16 lport, | ||
213 | const __be32 faddr, const __be16 fport) | ||
214 | { | 212 | { |
215 | return jhash_3words((__force __u32) laddr, | 213 | return jhash_3words((__force __u32) laddr, |
216 | (__force __u32) faddr, | 214 | (__force __u32) faddr, |
217 | ((__u32) lport) << 16 | (__force __u32)fport, | 215 | ((__u32) lport) << 16 | (__force __u32)fport, |
218 | inet_ehash_secret + net_hash_mix(net)); | 216 | initval); |
219 | } | ||
220 | |||
221 | static inline int inet_sk_ehashfn(const struct sock *sk) | ||
222 | { | ||
223 | const struct inet_sock *inet = inet_sk(sk); | ||
224 | const __be32 laddr = inet->inet_rcv_saddr; | ||
225 | const __u16 lport = inet->inet_num; | ||
226 | const __be32 faddr = inet->inet_daddr; | ||
227 | const __be16 fport = inet->inet_dport; | ||
228 | struct net *net = sock_net(sk); | ||
229 | |||
230 | return inet_ehashfn(net, laddr, lport, faddr, fport); | ||
231 | } | 217 | } |
232 | 218 | ||
233 | static inline struct request_sock *inet_reqsk_alloc(struct request_sock_ops *ops) | 219 | static inline struct request_sock *inet_reqsk_alloc(struct request_sock_ops *ops) |
diff --git a/include/net/ipv6.h b/include/net/ipv6.h index fe1c7f6c9217..a35055f4f8da 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h | |||
@@ -539,14 +539,14 @@ static inline u32 ipv6_addr_hash(const struct in6_addr *a) | |||
539 | } | 539 | } |
540 | 540 | ||
541 | /* more secured version of ipv6_addr_hash() */ | 541 | /* more secured version of ipv6_addr_hash() */ |
542 | static inline u32 ipv6_addr_jhash(const struct in6_addr *a) | 542 | static inline u32 __ipv6_addr_jhash(const struct in6_addr *a, const u32 initval) |
543 | { | 543 | { |
544 | u32 v = (__force u32)a->s6_addr32[0] ^ (__force u32)a->s6_addr32[1]; | 544 | u32 v = (__force u32)a->s6_addr32[0] ^ (__force u32)a->s6_addr32[1]; |
545 | 545 | ||
546 | return jhash_3words(v, | 546 | return jhash_3words(v, |
547 | (__force u32)a->s6_addr32[2], | 547 | (__force u32)a->s6_addr32[2], |
548 | (__force u32)a->s6_addr32[3], | 548 | (__force u32)a->s6_addr32[3], |
549 | ipv6_hash_secret); | 549 | initval); |
550 | } | 550 | } |
551 | 551 | ||
552 | static inline bool ipv6_addr_loopback(const struct in6_addr *a) | 552 | static inline bool ipv6_addr_loopback(const struct in6_addr *a) |
diff --git a/include/net/tcp.h b/include/net/tcp.h index 372dcccfeed0..b12e29a76590 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -475,7 +475,6 @@ int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size); | |||
475 | void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb); | 475 | void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb); |
476 | 476 | ||
477 | /* From syncookies.c */ | 477 | /* From syncookies.c */ |
478 | extern __u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS]; | ||
479 | int __cookie_v4_check(const struct iphdr *iph, const struct tcphdr *th, | 478 | int __cookie_v4_check(const struct iphdr *iph, const struct tcphdr *th, |
480 | u32 cookie); | 479 | u32 cookie); |
481 | struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, | 480 | struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, |
@@ -1323,7 +1322,7 @@ extern struct tcp_fastopen_context __rcu *tcp_fastopen_ctx; | |||
1323 | int tcp_fastopen_reset_cipher(void *key, unsigned int len); | 1322 | int tcp_fastopen_reset_cipher(void *key, unsigned int len); |
1324 | void tcp_fastopen_cookie_gen(__be32 src, __be32 dst, | 1323 | void tcp_fastopen_cookie_gen(__be32 src, __be32 dst, |
1325 | struct tcp_fastopen_cookie *foc); | 1324 | struct tcp_fastopen_cookie *foc); |
1326 | 1325 | void tcp_fastopen_init_key_once(bool publish); | |
1327 | #define TCP_FASTOPEN_KEY_LENGTH 16 | 1326 | #define TCP_FASTOPEN_KEY_LENGTH 16 |
1328 | 1327 | ||
1329 | /* Fastopen key context */ | 1328 | /* Fastopen key context */ |
diff --git a/init/main.c b/init/main.c index af310afbef28..27bbec1a5b35 100644 --- a/init/main.c +++ b/init/main.c | |||
@@ -136,6 +136,13 @@ static char *execute_command; | |||
136 | static char *ramdisk_execute_command; | 136 | static char *ramdisk_execute_command; |
137 | 137 | ||
138 | /* | 138 | /* |
139 | * Used to generate warnings if static_key manipulation functions are used | ||
140 | * before jump_label_init is called. | ||
141 | */ | ||
142 | bool static_key_initialized __read_mostly = false; | ||
143 | EXPORT_SYMBOL_GPL(static_key_initialized); | ||
144 | |||
145 | /* | ||
139 | * If set, this is an indication to the drivers that reset the underlying | 146 | * If set, this is an indication to the drivers that reset the underlying |
140 | * device before going ahead with the initialization otherwise driver might | 147 | * device before going ahead with the initialization otherwise driver might |
141 | * rely on the BIOS and skip the reset operation. | 148 | * rely on the BIOS and skip the reset operation. |
diff --git a/kernel/jump_label.c b/kernel/jump_label.c index 297a9247a3b3..9019f15deab2 100644 --- a/kernel/jump_label.c +++ b/kernel/jump_label.c | |||
@@ -58,6 +58,7 @@ static void jump_label_update(struct static_key *key, int enable); | |||
58 | 58 | ||
59 | void static_key_slow_inc(struct static_key *key) | 59 | void static_key_slow_inc(struct static_key *key) |
60 | { | 60 | { |
61 | STATIC_KEY_CHECK_USE(); | ||
61 | if (atomic_inc_not_zero(&key->enabled)) | 62 | if (atomic_inc_not_zero(&key->enabled)) |
62 | return; | 63 | return; |
63 | 64 | ||
@@ -103,12 +104,14 @@ static void jump_label_update_timeout(struct work_struct *work) | |||
103 | 104 | ||
104 | void static_key_slow_dec(struct static_key *key) | 105 | void static_key_slow_dec(struct static_key *key) |
105 | { | 106 | { |
107 | STATIC_KEY_CHECK_USE(); | ||
106 | __static_key_slow_dec(key, 0, NULL); | 108 | __static_key_slow_dec(key, 0, NULL); |
107 | } | 109 | } |
108 | EXPORT_SYMBOL_GPL(static_key_slow_dec); | 110 | EXPORT_SYMBOL_GPL(static_key_slow_dec); |
109 | 111 | ||
110 | void static_key_slow_dec_deferred(struct static_key_deferred *key) | 112 | void static_key_slow_dec_deferred(struct static_key_deferred *key) |
111 | { | 113 | { |
114 | STATIC_KEY_CHECK_USE(); | ||
112 | __static_key_slow_dec(&key->key, key->timeout, &key->work); | 115 | __static_key_slow_dec(&key->key, key->timeout, &key->work); |
113 | } | 116 | } |
114 | EXPORT_SYMBOL_GPL(static_key_slow_dec_deferred); | 117 | EXPORT_SYMBOL_GPL(static_key_slow_dec_deferred); |
@@ -116,6 +119,7 @@ EXPORT_SYMBOL_GPL(static_key_slow_dec_deferred); | |||
116 | void jump_label_rate_limit(struct static_key_deferred *key, | 119 | void jump_label_rate_limit(struct static_key_deferred *key, |
117 | unsigned long rl) | 120 | unsigned long rl) |
118 | { | 121 | { |
122 | STATIC_KEY_CHECK_USE(); | ||
119 | key->timeout = rl; | 123 | key->timeout = rl; |
120 | INIT_DELAYED_WORK(&key->work, jump_label_update_timeout); | 124 | INIT_DELAYED_WORK(&key->work, jump_label_update_timeout); |
121 | } | 125 | } |
@@ -212,6 +216,7 @@ void __init jump_label_init(void) | |||
212 | key->next = NULL; | 216 | key->next = NULL; |
213 | #endif | 217 | #endif |
214 | } | 218 | } |
219 | static_key_initialized = true; | ||
215 | jump_label_unlock(); | 220 | jump_label_unlock(); |
216 | } | 221 | } |
217 | 222 | ||
diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c index 3f1ec1586ae1..b02fd16b8942 100644 --- a/net/core/secure_seq.c +++ b/net/core/secure_seq.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <linux/hrtimer.h> | 7 | #include <linux/hrtimer.h> |
8 | #include <linux/ktime.h> | 8 | #include <linux/ktime.h> |
9 | #include <linux/string.h> | 9 | #include <linux/string.h> |
10 | #include <linux/net.h> | ||
10 | 11 | ||
11 | #include <net/secure_seq.h> | 12 | #include <net/secure_seq.h> |
12 | 13 | ||
@@ -16,18 +17,7 @@ static u32 net_secret[NET_SECRET_SIZE] ____cacheline_aligned; | |||
16 | 17 | ||
17 | static void net_secret_init(void) | 18 | static void net_secret_init(void) |
18 | { | 19 | { |
19 | u32 tmp; | 20 | net_get_random_once(net_secret, sizeof(net_secret)); |
20 | int i; | ||
21 | |||
22 | if (likely(net_secret[0])) | ||
23 | return; | ||
24 | |||
25 | for (i = NET_SECRET_SIZE; i > 0;) { | ||
26 | do { | ||
27 | get_random_bytes(&tmp, sizeof(tmp)); | ||
28 | } while (!tmp); | ||
29 | cmpxchg(&net_secret[--i], 0, tmp); | ||
30 | } | ||
31 | } | 21 | } |
32 | 22 | ||
33 | #ifdef CONFIG_INET | 23 | #ifdef CONFIG_INET |
diff --git a/net/core/utils.c b/net/core/utils.c index aa88e23fc87a..bf09371e19b1 100644 --- a/net/core/utils.c +++ b/net/core/utils.c | |||
@@ -338,3 +338,51 @@ void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb, | |||
338 | csum_unfold(*sum))); | 338 | csum_unfold(*sum))); |
339 | } | 339 | } |
340 | EXPORT_SYMBOL(inet_proto_csum_replace16); | 340 | EXPORT_SYMBOL(inet_proto_csum_replace16); |
341 | |||
342 | struct __net_random_once_work { | ||
343 | struct work_struct work; | ||
344 | struct static_key *key; | ||
345 | }; | ||
346 | |||
347 | static void __net_random_once_deferred(struct work_struct *w) | ||
348 | { | ||
349 | struct __net_random_once_work *work = | ||
350 | container_of(w, struct __net_random_once_work, work); | ||
351 | if (!static_key_enabled(work->key)) | ||
352 | static_key_slow_inc(work->key); | ||
353 | kfree(work); | ||
354 | } | ||
355 | |||
356 | static void __net_random_once_disable_jump(struct static_key *key) | ||
357 | { | ||
358 | struct __net_random_once_work *w; | ||
359 | |||
360 | w = kmalloc(sizeof(*w), GFP_ATOMIC); | ||
361 | if (!w) | ||
362 | return; | ||
363 | |||
364 | INIT_WORK(&w->work, __net_random_once_deferred); | ||
365 | w->key = key; | ||
366 | schedule_work(&w->work); | ||
367 | } | ||
368 | |||
369 | bool __net_get_random_once(void *buf, int nbytes, bool *done, | ||
370 | struct static_key *done_key) | ||
371 | { | ||
372 | static DEFINE_SPINLOCK(lock); | ||
373 | |||
374 | spin_lock_bh(&lock); | ||
375 | if (*done) { | ||
376 | spin_unlock_bh(&lock); | ||
377 | return false; | ||
378 | } | ||
379 | |||
380 | get_random_bytes(buf, nbytes); | ||
381 | *done = true; | ||
382 | spin_unlock_bh(&lock); | ||
383 | |||
384 | __net_random_once_disable_jump(done_key); | ||
385 | |||
386 | return true; | ||
387 | } | ||
388 | EXPORT_SYMBOL(__net_get_random_once); | ||
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 | } |
246 | EXPORT_SYMBOL(inet_listen); | 246 | EXPORT_SYMBOL(inet_listen); |
247 | 247 | ||
248 | u32 inet_ehash_secret __read_mostly; | ||
249 | EXPORT_SYMBOL(inet_ehash_secret); | ||
250 | |||
251 | u32 ipv6_hash_secret __read_mostly; | ||
252 | EXPORT_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 | */ | ||
258 | void 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 | } | ||
269 | EXPORT_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 a4b66bbe4f21..8b9cf279450d 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c | |||
@@ -24,6 +24,31 @@ | |||
24 | #include <net/secure_seq.h> | 24 | #include <net/secure_seq.h> |
25 | #include <net/ip.h> | 25 | #include <net/ip.h> |
26 | 26 | ||
27 | static unsigned int inet_ehashfn(struct net *net, const __be32 laddr, | ||
28 | const __u16 lport, const __be32 faddr, | ||
29 | const __be16 fport) | ||
30 | { | ||
31 | static u32 inet_ehash_secret __read_mostly; | ||
32 | |||
33 | net_get_random_once(&inet_ehash_secret, sizeof(inet_ehash_secret)); | ||
34 | |||
35 | return __inet_ehashfn(laddr, lport, faddr, fport, | ||
36 | inet_ehash_secret + net_hash_mix(net)); | ||
37 | } | ||
38 | |||
39 | |||
40 | static unsigned int inet_sk_ehashfn(const struct sock *sk) | ||
41 | { | ||
42 | const struct inet_sock *inet = inet_sk(sk); | ||
43 | const __be32 laddr = inet->inet_rcv_saddr; | ||
44 | const __u16 lport = inet->inet_num; | ||
45 | const __be32 faddr = inet->inet_daddr; | ||
46 | const __be16 fport = inet->inet_dport; | ||
47 | struct net *net = sock_net(sk); | ||
48 | |||
49 | return inet_ehashfn(net, laddr, lport, faddr, fport); | ||
50 | } | ||
51 | |||
27 | /* | 52 | /* |
28 | * Allocate and initialize a new local port bind bucket. | 53 | * Allocate and initialize a new local port bind bucket. |
29 | * The bindhash mutex for snum's hash chain must be held here. | 54 | * The bindhash mutex for snum's hash chain must be held here. |
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index 3b64c59b4109..b95331e6c077 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c | |||
@@ -25,15 +25,7 @@ | |||
25 | 25 | ||
26 | extern int sysctl_tcp_syncookies; | 26 | extern int sysctl_tcp_syncookies; |
27 | 27 | ||
28 | __u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS]; | 28 | static u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS]; |
29 | EXPORT_SYMBOL(syncookie_secret); | ||
30 | |||
31 | static __init int init_syncookies(void) | ||
32 | { | ||
33 | get_random_bytes(syncookie_secret, sizeof(syncookie_secret)); | ||
34 | return 0; | ||
35 | } | ||
36 | __initcall(init_syncookies); | ||
37 | 29 | ||
38 | #define COOKIEBITS 24 /* Upper bits store count */ | 30 | #define COOKIEBITS 24 /* Upper bits store count */ |
39 | #define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1) | 31 | #define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1) |
@@ -44,8 +36,11 @@ static DEFINE_PER_CPU(__u32 [16 + 5 + SHA_WORKSPACE_WORDS], | |||
44 | static u32 cookie_hash(__be32 saddr, __be32 daddr, __be16 sport, __be16 dport, | 36 | static u32 cookie_hash(__be32 saddr, __be32 daddr, __be16 sport, __be16 dport, |
45 | u32 count, int c) | 37 | u32 count, int c) |
46 | { | 38 | { |
47 | __u32 *tmp = __get_cpu_var(ipv4_cookie_scratch); | 39 | __u32 *tmp; |
40 | |||
41 | net_get_random_once(syncookie_secret, sizeof(syncookie_secret)); | ||
48 | 42 | ||
43 | tmp = __get_cpu_var(ipv4_cookie_scratch); | ||
49 | memcpy(tmp + 4, syncookie_secret[c], sizeof(syncookie_secret[c])); | 44 | memcpy(tmp + 4, syncookie_secret[c], sizeof(syncookie_secret[c])); |
50 | tmp[0] = (__force u32)saddr; | 45 | tmp[0] = (__force u32)saddr; |
51 | tmp[1] = (__force u32)daddr; | 46 | tmp[1] = (__force u32)daddr; |
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index c08f096d46b5..4b161d5aba0b 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c | |||
@@ -274,6 +274,11 @@ static int proc_tcp_fastopen_key(struct ctl_table *ctl, int write, | |||
274 | ret = -EINVAL; | 274 | ret = -EINVAL; |
275 | goto bad_key; | 275 | goto bad_key; |
276 | } | 276 | } |
277 | /* Generate a dummy secret but don't publish it. This | ||
278 | * is needed so we don't regenerate a new key on the | ||
279 | * first invocation of tcp_fastopen_cookie_gen | ||
280 | */ | ||
281 | tcp_fastopen_init_key_once(false); | ||
277 | tcp_fastopen_reset_cipher(user_key, TCP_FASTOPEN_KEY_LENGTH); | 282 | tcp_fastopen_reset_cipher(user_key, TCP_FASTOPEN_KEY_LENGTH); |
278 | } | 283 | } |
279 | 284 | ||
diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c index ab7bd35bb312..766032b4a6c3 100644 --- a/net/ipv4/tcp_fastopen.c +++ b/net/ipv4/tcp_fastopen.c | |||
@@ -14,6 +14,20 @@ struct tcp_fastopen_context __rcu *tcp_fastopen_ctx; | |||
14 | 14 | ||
15 | static DEFINE_SPINLOCK(tcp_fastopen_ctx_lock); | 15 | static DEFINE_SPINLOCK(tcp_fastopen_ctx_lock); |
16 | 16 | ||
17 | void tcp_fastopen_init_key_once(bool publish) | ||
18 | { | ||
19 | static u8 key[TCP_FASTOPEN_KEY_LENGTH]; | ||
20 | |||
21 | /* tcp_fastopen_reset_cipher publishes the new context | ||
22 | * atomically, so we allow this race happening here. | ||
23 | * | ||
24 | * All call sites of tcp_fastopen_cookie_gen also check | ||
25 | * for a valid cookie, so this is an acceptable risk. | ||
26 | */ | ||
27 | if (net_get_random_once(key, sizeof(key)) && publish) | ||
28 | tcp_fastopen_reset_cipher(key, sizeof(key)); | ||
29 | } | ||
30 | |||
17 | static void tcp_fastopen_ctx_free(struct rcu_head *head) | 31 | static void tcp_fastopen_ctx_free(struct rcu_head *head) |
18 | { | 32 | { |
19 | struct tcp_fastopen_context *ctx = | 33 | struct tcp_fastopen_context *ctx = |
@@ -70,6 +84,8 @@ void tcp_fastopen_cookie_gen(__be32 src, __be32 dst, | |||
70 | __be32 path[4] = { src, dst, 0, 0 }; | 84 | __be32 path[4] = { src, dst, 0, 0 }; |
71 | struct tcp_fastopen_context *ctx; | 85 | struct tcp_fastopen_context *ctx; |
72 | 86 | ||
87 | tcp_fastopen_init_key_once(true); | ||
88 | |||
73 | rcu_read_lock(); | 89 | rcu_read_lock(); |
74 | ctx = rcu_dereference(tcp_fastopen_ctx); | 90 | ctx = rcu_dereference(tcp_fastopen_ctx); |
75 | if (ctx) { | 91 | if (ctx) { |
@@ -78,14 +94,3 @@ void tcp_fastopen_cookie_gen(__be32 src, __be32 dst, | |||
78 | } | 94 | } |
79 | rcu_read_unlock(); | 95 | rcu_read_unlock(); |
80 | } | 96 | } |
81 | |||
82 | static int __init tcp_fastopen_init(void) | ||
83 | { | ||
84 | __u8 key[TCP_FASTOPEN_KEY_LENGTH]; | ||
85 | |||
86 | get_random_bytes(key, sizeof(key)); | ||
87 | tcp_fastopen_reset_cipher(key, sizeof(key)); | ||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | late_initcall(tcp_fastopen_init); | ||
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 9f27bb800607..89909dd730dd 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -407,6 +407,18 @@ static inline int compute_score2(struct sock *sk, struct net *net, | |||
407 | return score; | 407 | return score; |
408 | } | 408 | } |
409 | 409 | ||
410 | static unsigned int udp_ehashfn(struct net *net, const __be32 laddr, | ||
411 | const __u16 lport, const __be32 faddr, | ||
412 | const __be16 fport) | ||
413 | { | ||
414 | static u32 udp_ehash_secret __read_mostly; | ||
415 | |||
416 | net_get_random_once(&udp_ehash_secret, sizeof(udp_ehash_secret)); | ||
417 | |||
418 | return __inet_ehashfn(laddr, lport, faddr, fport, | ||
419 | udp_ehash_secret + net_hash_mix(net)); | ||
420 | } | ||
421 | |||
410 | 422 | ||
411 | /* called with read_rcu_lock() */ | 423 | /* called with read_rcu_lock() */ |
412 | static struct sock *udp4_lib_lookup2(struct net *net, | 424 | static struct sock *udp4_lib_lookup2(struct net *net, |
@@ -430,8 +442,8 @@ begin: | |||
430 | badness = score; | 442 | badness = score; |
431 | reuseport = sk->sk_reuseport; | 443 | reuseport = sk->sk_reuseport; |
432 | if (reuseport) { | 444 | if (reuseport) { |
433 | hash = inet_ehashfn(net, daddr, hnum, | 445 | hash = udp_ehashfn(net, daddr, hnum, |
434 | saddr, sport); | 446 | saddr, sport); |
435 | matches = 1; | 447 | matches = 1; |
436 | } | 448 | } |
437 | } else if (score == badness && reuseport) { | 449 | } else if (score == badness && reuseport) { |
@@ -511,8 +523,8 @@ begin: | |||
511 | badness = score; | 523 | badness = score; |
512 | reuseport = sk->sk_reuseport; | 524 | reuseport = sk->sk_reuseport; |
513 | if (reuseport) { | 525 | if (reuseport) { |
514 | hash = inet_ehashfn(net, daddr, hnum, | 526 | hash = udp_ehashfn(net, daddr, hnum, |
515 | saddr, sport); | 527 | saddr, sport); |
516 | matches = 1; | 528 | matches = 1; |
517 | } | 529 | } |
518 | } else if (score == badness && reuseport) { | 530 | } else if (score == badness && reuseport) { |
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. */ |
119 | lookup_protocol: | 114 | lookup_protocol: |
120 | err = -ESOCKTNOSUPPORT; | 115 | err = -ESOCKTNOSUPPORT; |
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index 842d833dfc18..262e13c02ec2 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c | |||
@@ -23,6 +23,39 @@ | |||
23 | #include <net/secure_seq.h> | 23 | #include <net/secure_seq.h> |
24 | #include <net/ip.h> | 24 | #include <net/ip.h> |
25 | 25 | ||
26 | static unsigned int inet6_ehashfn(struct net *net, | ||
27 | const struct in6_addr *laddr, | ||
28 | const u16 lport, | ||
29 | const struct in6_addr *faddr, | ||
30 | const __be16 fport) | ||
31 | { | ||
32 | static u32 inet6_ehash_secret __read_mostly; | ||
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 | |||
43 | return __inet6_ehashfn(lhash, lport, fhash, fport, | ||
44 | inet6_ehash_secret + net_hash_mix(net)); | ||
45 | } | ||
46 | |||
47 | static int inet6_sk_ehashfn(const struct sock *sk) | ||
48 | { | ||
49 | const struct inet_sock *inet = inet_sk(sk); | ||
50 | const struct in6_addr *laddr = &sk->sk_v6_rcv_saddr; | ||
51 | const struct in6_addr *faddr = &sk->sk_v6_daddr; | ||
52 | const __u16 lport = inet->inet_num; | ||
53 | const __be16 fport = inet->inet_dport; | ||
54 | struct net *net = sock_net(sk); | ||
55 | |||
56 | return inet6_ehashfn(net, laddr, lport, faddr, fport); | ||
57 | } | ||
58 | |||
26 | int __inet6_hash(struct sock *sk, struct inet_timewait_sock *tw) | 59 | int __inet6_hash(struct sock *sk, struct inet_timewait_sock *tw) |
27 | { | 60 | { |
28 | struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo; | 61 | struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo; |
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index d04d3f1dd9b7..535a3ad262f1 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c | |||
@@ -24,6 +24,8 @@ | |||
24 | #define COOKIEBITS 24 /* Upper bits store count */ | 24 | #define COOKIEBITS 24 /* Upper bits store count */ |
25 | #define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1) | 25 | #define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1) |
26 | 26 | ||
27 | static u32 syncookie6_secret[2][16-4+SHA_DIGEST_WORDS]; | ||
28 | |||
27 | /* RFC 2460, Section 8.3: | 29 | /* RFC 2460, Section 8.3: |
28 | * [ipv6 tcp] MSS must be computed as the maximum packet size minus 60 [..] | 30 | * [ipv6 tcp] MSS must be computed as the maximum packet size minus 60 [..] |
29 | * | 31 | * |
@@ -61,14 +63,18 @@ static DEFINE_PER_CPU(__u32 [16 + 5 + SHA_WORKSPACE_WORDS], | |||
61 | static u32 cookie_hash(const struct in6_addr *saddr, const struct in6_addr *daddr, | 63 | static u32 cookie_hash(const struct in6_addr *saddr, const struct in6_addr *daddr, |
62 | __be16 sport, __be16 dport, u32 count, int c) | 64 | __be16 sport, __be16 dport, u32 count, int c) |
63 | { | 65 | { |
64 | __u32 *tmp = __get_cpu_var(ipv6_cookie_scratch); | 66 | __u32 *tmp; |
67 | |||
68 | net_get_random_once(syncookie6_secret, sizeof(syncookie6_secret)); | ||
69 | |||
70 | tmp = __get_cpu_var(ipv6_cookie_scratch); | ||
65 | 71 | ||
66 | /* | 72 | /* |
67 | * we have 320 bits of information to hash, copy in the remaining | 73 | * we have 320 bits of information to hash, copy in the remaining |
68 | * 192 bits required for sha_transform, from the syncookie_secret | 74 | * 192 bits required for sha_transform, from the syncookie6_secret |
69 | * and overwrite the digest with the secret | 75 | * and overwrite the digest with the secret |
70 | */ | 76 | */ |
71 | memcpy(tmp + 10, syncookie_secret[c], 44); | 77 | memcpy(tmp + 10, syncookie6_secret[c], 44); |
72 | memcpy(tmp, saddr, 16); | 78 | memcpy(tmp, saddr, 16); |
73 | memcpy(tmp + 4, daddr, 16); | 79 | memcpy(tmp + 4, daddr, 16); |
74 | tmp[8] = ((__force u32)sport << 16) + (__force u32)dport; | 80 | tmp[8] = ((__force u32)sport << 16) + (__force u32)dport; |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index b496de19a341..44fc4e3d661f 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -53,6 +53,29 @@ | |||
53 | #include <trace/events/skb.h> | 53 | #include <trace/events/skb.h> |
54 | #include "udp_impl.h" | 54 | #include "udp_impl.h" |
55 | 55 | ||
56 | static unsigned int udp6_ehashfn(struct net *net, | ||
57 | const struct in6_addr *laddr, | ||
58 | const u16 lport, | ||
59 | const struct in6_addr *faddr, | ||
60 | const __be16 fport) | ||
61 | { | ||
62 | static u32 udp6_ehash_secret __read_mostly; | ||
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 | |||
75 | return __inet6_ehashfn(lhash, lport, fhash, fport, | ||
76 | udp_ipv6_hash_secret + net_hash_mix(net)); | ||
77 | } | ||
78 | |||
56 | int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) | 79 | int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) |
57 | { | 80 | { |
58 | const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2); | 81 | const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2); |
@@ -214,8 +237,8 @@ begin: | |||
214 | badness = score; | 237 | badness = score; |
215 | reuseport = sk->sk_reuseport; | 238 | reuseport = sk->sk_reuseport; |
216 | if (reuseport) { | 239 | if (reuseport) { |
217 | hash = inet6_ehashfn(net, daddr, hnum, | 240 | hash = udp6_ehashfn(net, daddr, hnum, |
218 | saddr, sport); | 241 | saddr, sport); |
219 | matches = 1; | 242 | matches = 1; |
220 | } else if (score == SCORE2_MAX) | 243 | } else if (score == SCORE2_MAX) |
221 | goto exact_match; | 244 | goto exact_match; |
@@ -295,8 +318,8 @@ begin: | |||
295 | badness = score; | 318 | badness = score; |
296 | reuseport = sk->sk_reuseport; | 319 | reuseport = sk->sk_reuseport; |
297 | if (reuseport) { | 320 | if (reuseport) { |
298 | hash = inet6_ehashfn(net, daddr, hnum, | 321 | hash = udp6_ehashfn(net, daddr, hnum, |
299 | saddr, sport); | 322 | saddr, sport); |
300 | matches = 1; | 323 | matches = 1; |
301 | } | 324 | } |
302 | } else if (score == badness && reuseport) { | 325 | } else if (score == badness && reuseport) { |
diff --git a/net/rds/connection.c b/net/rds/connection.c index 642ad42c416b..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 | ||
52 | static struct hlist_head *rds_conn_bucket(__be32 laddr, __be32 faddr) | 52 | static 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(NULL, | 61 | hash = __inet_ehashfn(be32_to_cpu(laddr), 0, |
56 | be32_to_cpu(laddr), 0, | 62 | be32_to_cpu(faddr), 0, |
57 | be32_to_cpu(faddr), 0); | 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 | ||