diff options
author | Hannes Frederic Sowa <hannes@stressinduktion.org> | 2013-10-19 15:48:58 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-10-19 19:45:35 -0400 |
commit | 222e83d2e0aecb6a5e8d42b1a8d51332a1eba960 (patch) | |
tree | 395011fb151ed3ce911333e1ab70602b2cfbc3e0 | |
parent | 1bbdceef1e535add893bf71d7b7ab102e4eb69eb (diff) |
tcp: switch tcp_fastopen key generation to net_get_random_once
Changed key initialization of tcp_fastopen cookies to net_get_random_once.
If the user sets a custom key net_get_random_once must be called at
least once to ensure we don't overwrite the user provided key when the
first cookie is generated later on.
Cc: Yuchung Cheng <ycheng@google.com>
Cc: Eric Dumazet <edumazet@google.com>
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/tcp.h | 2 | ||||
-rw-r--r-- | net/ipv4/sysctl_net_ipv4.c | 5 | ||||
-rw-r--r-- | net/ipv4/tcp_fastopen.c | 27 |
3 files changed, 22 insertions, 12 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h index f30326f1c92b..b12e29a76590 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -1322,7 +1322,7 @@ extern struct tcp_fastopen_context __rcu *tcp_fastopen_ctx; | |||
1322 | int tcp_fastopen_reset_cipher(void *key, unsigned int len); | 1322 | int tcp_fastopen_reset_cipher(void *key, unsigned int len); |
1323 | void tcp_fastopen_cookie_gen(__be32 src, __be32 dst, | 1323 | void tcp_fastopen_cookie_gen(__be32 src, __be32 dst, |
1324 | struct tcp_fastopen_cookie *foc); | 1324 | struct tcp_fastopen_cookie *foc); |
1325 | 1325 | void tcp_fastopen_init_key_once(bool publish); | |
1326 | #define TCP_FASTOPEN_KEY_LENGTH 16 | 1326 | #define TCP_FASTOPEN_KEY_LENGTH 16 |
1327 | 1327 | ||
1328 | /* Fastopen key context */ | 1328 | /* Fastopen key context */ |
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); | ||