aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2017-05-05 09:56:54 -0400
committerDavid S. Miller <davem@davemloft.net>2017-05-05 12:00:11 -0400
commit84b114b98452c431299d99c135f751659e517acb (patch)
tree53778bfd4964bed65ac40a9c1c57a73f21cb9664
parent9051247dcf9ecee156d2ddac39a4f1ca591f8428 (diff)
tcp: randomize timestamps on syncookies
Whole point of randomization was to hide server uptime, but an attacker can simply start a syn flood and TCP generates 'old style' timestamps, directly revealing server jiffies value. Also, TSval sent by the server to a particular remote address vary depending on syncookies being sent or not, potentially triggering PAWS drops for innocent clients. Lets implement proper randomization, including for SYNcookies. Also we do not need to export sysctl_tcp_timestamps, since it is not used from a module. In v2, I added Florian feedback and contribution, adding tsoff to tcp_get_cookie_sock(). v3 removed one unused variable in tcp_v4_connect() as Florian spotted. Fixes: 95a22caee396c ("tcp: randomize tcp timestamp offsets for each connection") Signed-off-by: Eric Dumazet <edumazet@google.com> Reviewed-by: Florian Westphal <fw@strlen.de> Tested-by: Florian Westphal <fw@strlen.de> Cc: Yuchung Cheng <ycheng@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/secure_seq.h10
-rw-r--r--include/net/tcp.h5
-rw-r--r--net/core/secure_seq.c31
-rw-r--r--net/ipv4/syncookies.c12
-rw-r--r--net/ipv4/tcp_input.c8
-rw-r--r--net/ipv4/tcp_ipv4.c32
-rw-r--r--net/ipv6/syncookies.c10
-rw-r--r--net/ipv6/tcp_ipv6.c32
8 files changed, 88 insertions, 52 deletions
diff --git a/include/net/secure_seq.h b/include/net/secure_seq.h
index fe236b3429f0..b94006f6fbdd 100644
--- a/include/net/secure_seq.h
+++ b/include/net/secure_seq.h
@@ -6,10 +6,12 @@
6u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport); 6u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport);
7u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, 7u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
8 __be16 dport); 8 __be16 dport);
9u32 secure_tcp_seq_and_tsoff(__be32 saddr, __be32 daddr, 9u32 secure_tcp_seq(__be32 saddr, __be32 daddr,
10 __be16 sport, __be16 dport, u32 *tsoff); 10 __be16 sport, __be16 dport);
11u32 secure_tcpv6_seq_and_tsoff(const __be32 *saddr, const __be32 *daddr, 11u32 secure_tcp_ts_off(__be32 saddr, __be32 daddr);
12 __be16 sport, __be16 dport, u32 *tsoff); 12u32 secure_tcpv6_seq(const __be32 *saddr, const __be32 *daddr,
13 __be16 sport, __be16 dport);
14u32 secure_tcpv6_ts_off(const __be32 *saddr, const __be32 *daddr);
13u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr, 15u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
14 __be16 sport, __be16 dport); 16 __be16 sport, __be16 dport);
15u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr, 17u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 270e5cc43c99..8c0e5a901d64 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -470,7 +470,7 @@ void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb);
470/* From syncookies.c */ 470/* From syncookies.c */
471struct sock *tcp_get_cookie_sock(struct sock *sk, struct sk_buff *skb, 471struct sock *tcp_get_cookie_sock(struct sock *sk, struct sk_buff *skb,
472 struct request_sock *req, 472 struct request_sock *req,
473 struct dst_entry *dst); 473 struct dst_entry *dst, u32 tsoff);
474int __cookie_v4_check(const struct iphdr *iph, const struct tcphdr *th, 474int __cookie_v4_check(const struct iphdr *iph, const struct tcphdr *th,
475 u32 cookie); 475 u32 cookie);
476struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb); 476struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb);
@@ -1822,7 +1822,8 @@ struct tcp_request_sock_ops {
1822#endif 1822#endif
1823 struct dst_entry *(*route_req)(const struct sock *sk, struct flowi *fl, 1823 struct dst_entry *(*route_req)(const struct sock *sk, struct flowi *fl,
1824 const struct request_sock *req); 1824 const struct request_sock *req);
1825 __u32 (*init_seq_tsoff)(const struct sk_buff *skb, u32 *tsoff); 1825 u32 (*init_seq)(const struct sk_buff *skb);
1826 u32 (*init_ts_off)(const struct sk_buff *skb);
1826 int (*send_synack)(const struct sock *sk, struct dst_entry *dst, 1827 int (*send_synack)(const struct sock *sk, struct dst_entry *dst,
1827 struct flowi *fl, struct request_sock *req, 1828 struct flowi *fl, struct request_sock *req,
1828 struct tcp_fastopen_cookie *foc, 1829 struct tcp_fastopen_cookie *foc,
diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c
index 6bd2f8fb0476..ae35cce3a40d 100644
--- a/net/core/secure_seq.c
+++ b/net/core/secure_seq.c
@@ -24,9 +24,13 @@ static siphash_key_t ts_secret __read_mostly;
24 24
25static __always_inline void net_secret_init(void) 25static __always_inline void net_secret_init(void)
26{ 26{
27 net_get_random_once(&ts_secret, sizeof(ts_secret));
28 net_get_random_once(&net_secret, sizeof(net_secret)); 27 net_get_random_once(&net_secret, sizeof(net_secret));
29} 28}
29
30static __always_inline void ts_secret_init(void)
31{
32 net_get_random_once(&ts_secret, sizeof(ts_secret));
33}
30#endif 34#endif
31 35
32#ifdef CONFIG_INET 36#ifdef CONFIG_INET
@@ -47,7 +51,7 @@ static u32 seq_scale(u32 seq)
47#endif 51#endif
48 52
49#if IS_ENABLED(CONFIG_IPV6) 53#if IS_ENABLED(CONFIG_IPV6)
50static u32 secure_tcpv6_ts_off(const __be32 *saddr, const __be32 *daddr) 54u32 secure_tcpv6_ts_off(const __be32 *saddr, const __be32 *daddr)
51{ 55{
52 const struct { 56 const struct {
53 struct in6_addr saddr; 57 struct in6_addr saddr;
@@ -60,12 +64,14 @@ static u32 secure_tcpv6_ts_off(const __be32 *saddr, const __be32 *daddr)
60 if (sysctl_tcp_timestamps != 1) 64 if (sysctl_tcp_timestamps != 1)
61 return 0; 65 return 0;
62 66
67 ts_secret_init();
63 return siphash(&combined, offsetofend(typeof(combined), daddr), 68 return siphash(&combined, offsetofend(typeof(combined), daddr),
64 &ts_secret); 69 &ts_secret);
65} 70}
71EXPORT_SYMBOL(secure_tcpv6_ts_off);
66 72
67u32 secure_tcpv6_seq_and_tsoff(const __be32 *saddr, const __be32 *daddr, 73u32 secure_tcpv6_seq(const __be32 *saddr, const __be32 *daddr,
68 __be16 sport, __be16 dport, u32 *tsoff) 74 __be16 sport, __be16 dport)
69{ 75{
70 const struct { 76 const struct {
71 struct in6_addr saddr; 77 struct in6_addr saddr;
@@ -78,14 +84,14 @@ u32 secure_tcpv6_seq_and_tsoff(const __be32 *saddr, const __be32 *daddr,
78 .sport = sport, 84 .sport = sport,
79 .dport = dport 85 .dport = dport
80 }; 86 };
81 u64 hash; 87 u32 hash;
88
82 net_secret_init(); 89 net_secret_init();
83 hash = siphash(&combined, offsetofend(typeof(combined), dport), 90 hash = siphash(&combined, offsetofend(typeof(combined), dport),
84 &net_secret); 91 &net_secret);
85 *tsoff = secure_tcpv6_ts_off(saddr, daddr);
86 return seq_scale(hash); 92 return seq_scale(hash);
87} 93}
88EXPORT_SYMBOL(secure_tcpv6_seq_and_tsoff); 94EXPORT_SYMBOL(secure_tcpv6_seq);
89 95
90u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, 96u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
91 __be16 dport) 97 __be16 dport)
@@ -107,11 +113,12 @@ EXPORT_SYMBOL(secure_ipv6_port_ephemeral);
107#endif 113#endif
108 114
109#ifdef CONFIG_INET 115#ifdef CONFIG_INET
110static u32 secure_tcp_ts_off(__be32 saddr, __be32 daddr) 116u32 secure_tcp_ts_off(__be32 saddr, __be32 daddr)
111{ 117{
112 if (sysctl_tcp_timestamps != 1) 118 if (sysctl_tcp_timestamps != 1)
113 return 0; 119 return 0;
114 120
121 ts_secret_init();
115 return siphash_2u32((__force u32)saddr, (__force u32)daddr, 122 return siphash_2u32((__force u32)saddr, (__force u32)daddr,
116 &ts_secret); 123 &ts_secret);
117} 124}
@@ -121,15 +128,15 @@ static u32 secure_tcp_ts_off(__be32 saddr, __be32 daddr)
121 * it would be easy enough to have the former function use siphash_4u32, passing 128 * it would be easy enough to have the former function use siphash_4u32, passing
122 * the arguments as separate u32. 129 * the arguments as separate u32.
123 */ 130 */
124u32 secure_tcp_seq_and_tsoff(__be32 saddr, __be32 daddr, 131u32 secure_tcp_seq(__be32 saddr, __be32 daddr,
125 __be16 sport, __be16 dport, u32 *tsoff) 132 __be16 sport, __be16 dport)
126{ 133{
127 u64 hash; 134 u32 hash;
135
128 net_secret_init(); 136 net_secret_init();
129 hash = siphash_3u32((__force u32)saddr, (__force u32)daddr, 137 hash = siphash_3u32((__force u32)saddr, (__force u32)daddr,
130 (__force u32)sport << 16 | (__force u32)dport, 138 (__force u32)sport << 16 | (__force u32)dport,
131 &net_secret); 139 &net_secret);
132 *tsoff = secure_tcp_ts_off(saddr, daddr);
133 return seq_scale(hash); 140 return seq_scale(hash);
134} 141}
135 142
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index 496b97e17aaf..0257d965f111 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -16,6 +16,7 @@
16#include <linux/siphash.h> 16#include <linux/siphash.h>
17#include <linux/kernel.h> 17#include <linux/kernel.h>
18#include <linux/export.h> 18#include <linux/export.h>
19#include <net/secure_seq.h>
19#include <net/tcp.h> 20#include <net/tcp.h>
20#include <net/route.h> 21#include <net/route.h>
21 22
@@ -203,7 +204,7 @@ EXPORT_SYMBOL_GPL(__cookie_v4_check);
203 204
204struct sock *tcp_get_cookie_sock(struct sock *sk, struct sk_buff *skb, 205struct sock *tcp_get_cookie_sock(struct sock *sk, struct sk_buff *skb,
205 struct request_sock *req, 206 struct request_sock *req,
206 struct dst_entry *dst) 207 struct dst_entry *dst, u32 tsoff)
207{ 208{
208 struct inet_connection_sock *icsk = inet_csk(sk); 209 struct inet_connection_sock *icsk = inet_csk(sk);
209 struct sock *child; 210 struct sock *child;
@@ -213,6 +214,7 @@ struct sock *tcp_get_cookie_sock(struct sock *sk, struct sk_buff *skb,
213 NULL, &own_req); 214 NULL, &own_req);
214 if (child) { 215 if (child) {
215 atomic_set(&req->rsk_refcnt, 1); 216 atomic_set(&req->rsk_refcnt, 1);
217 tcp_sk(child)->tsoffset = tsoff;
216 sock_rps_save_rxhash(child, skb); 218 sock_rps_save_rxhash(child, skb);
217 inet_csk_reqsk_queue_add(sk, req, child); 219 inet_csk_reqsk_queue_add(sk, req, child);
218 } else { 220 } else {
@@ -292,6 +294,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
292 struct rtable *rt; 294 struct rtable *rt;
293 __u8 rcv_wscale; 295 __u8 rcv_wscale;
294 struct flowi4 fl4; 296 struct flowi4 fl4;
297 u32 tsoff = 0;
295 298
296 if (!sock_net(sk)->ipv4.sysctl_tcp_syncookies || !th->ack || th->rst) 299 if (!sock_net(sk)->ipv4.sysctl_tcp_syncookies || !th->ack || th->rst)
297 goto out; 300 goto out;
@@ -311,6 +314,11 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
311 memset(&tcp_opt, 0, sizeof(tcp_opt)); 314 memset(&tcp_opt, 0, sizeof(tcp_opt));
312 tcp_parse_options(skb, &tcp_opt, 0, NULL); 315 tcp_parse_options(skb, &tcp_opt, 0, NULL);
313 316
317 if (tcp_opt.saw_tstamp && tcp_opt.rcv_tsecr) {
318 tsoff = secure_tcp_ts_off(ip_hdr(skb)->daddr, ip_hdr(skb)->saddr);
319 tcp_opt.rcv_tsecr -= tsoff;
320 }
321
314 if (!cookie_timestamp_decode(&tcp_opt)) 322 if (!cookie_timestamp_decode(&tcp_opt))
315 goto out; 323 goto out;
316 324
@@ -381,7 +389,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
381 ireq->rcv_wscale = rcv_wscale; 389 ireq->rcv_wscale = rcv_wscale;
382 ireq->ecn_ok = cookie_ecn_ok(&tcp_opt, sock_net(sk), &rt->dst); 390 ireq->ecn_ok = cookie_ecn_ok(&tcp_opt, sock_net(sk), &rt->dst);
383 391
384 ret = tcp_get_cookie_sock(sk, skb, req, &rt->dst); 392 ret = tcp_get_cookie_sock(sk, skb, req, &rt->dst, tsoff);
385 /* ip_queue_xmit() depends on our flow being setup 393 /* ip_queue_xmit() depends on our flow being setup
386 * Normal sockets get it right from inet_csk_route_child_sock() 394 * Normal sockets get it right from inet_csk_route_child_sock()
387 */ 395 */
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 9739962bfb3f..5a3ad09e2786 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -85,7 +85,6 @@ int sysctl_tcp_dsack __read_mostly = 1;
85int sysctl_tcp_app_win __read_mostly = 31; 85int sysctl_tcp_app_win __read_mostly = 31;
86int sysctl_tcp_adv_win_scale __read_mostly = 1; 86int sysctl_tcp_adv_win_scale __read_mostly = 1;
87EXPORT_SYMBOL(sysctl_tcp_adv_win_scale); 87EXPORT_SYMBOL(sysctl_tcp_adv_win_scale);
88EXPORT_SYMBOL(sysctl_tcp_timestamps);
89 88
90/* rfc5961 challenge ack rate limiting */ 89/* rfc5961 challenge ack rate limiting */
91int sysctl_tcp_challenge_ack_limit = 1000; 90int sysctl_tcp_challenge_ack_limit = 1000;
@@ -6347,8 +6346,8 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
6347 if (security_inet_conn_request(sk, skb, req)) 6346 if (security_inet_conn_request(sk, skb, req))
6348 goto drop_and_free; 6347 goto drop_and_free;
6349 6348
6350 if (isn && tmp_opt.tstamp_ok) 6349 if (tmp_opt.tstamp_ok)
6351 af_ops->init_seq_tsoff(skb, &tcp_rsk(req)->ts_off); 6350 tcp_rsk(req)->ts_off = af_ops->init_ts_off(skb);
6352 6351
6353 if (!want_cookie && !isn) { 6352 if (!want_cookie && !isn) {
6354 /* Kill the following clause, if you dislike this way. */ 6353 /* Kill the following clause, if you dislike this way. */
@@ -6368,7 +6367,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
6368 goto drop_and_release; 6367 goto drop_and_release;
6369 } 6368 }
6370 6369
6371 isn = af_ops->init_seq_tsoff(skb, &tcp_rsk(req)->ts_off); 6370 isn = af_ops->init_seq(skb);
6372 } 6371 }
6373 if (!dst) { 6372 if (!dst) {
6374 dst = af_ops->route_req(sk, &fl, req); 6373 dst = af_ops->route_req(sk, &fl, req);
@@ -6380,7 +6379,6 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
6380 6379
6381 if (want_cookie) { 6380 if (want_cookie) {
6382 isn = cookie_init_sequence(af_ops, sk, skb, &req->mss); 6381 isn = cookie_init_sequence(af_ops, sk, skb, &req->mss);
6383 tcp_rsk(req)->ts_off = 0;
6384 req->cookie_ts = tmp_opt.tstamp_ok; 6382 req->cookie_ts = tmp_opt.tstamp_ok;
6385 if (!tmp_opt.tstamp_ok) 6383 if (!tmp_opt.tstamp_ok)
6386 inet_rsk(req)->ecn_ok = 0; 6384 inet_rsk(req)->ecn_ok = 0;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index cbbafe546c0f..3a51582bef55 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -94,12 +94,18 @@ static int tcp_v4_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key,
94struct inet_hashinfo tcp_hashinfo; 94struct inet_hashinfo tcp_hashinfo;
95EXPORT_SYMBOL(tcp_hashinfo); 95EXPORT_SYMBOL(tcp_hashinfo);
96 96
97static u32 tcp_v4_init_seq_and_tsoff(const struct sk_buff *skb, u32 *tsoff) 97static u32 tcp_v4_init_seq(const struct sk_buff *skb)
98{ 98{
99 return secure_tcp_seq_and_tsoff(ip_hdr(skb)->daddr, 99 return secure_tcp_seq(ip_hdr(skb)->daddr,
100 ip_hdr(skb)->saddr, 100 ip_hdr(skb)->saddr,
101 tcp_hdr(skb)->dest, 101 tcp_hdr(skb)->dest,
102 tcp_hdr(skb)->source, tsoff); 102 tcp_hdr(skb)->source);
103}
104
105static u32 tcp_v4_init_ts_off(const struct sk_buff *skb)
106{
107 return secure_tcp_ts_off(ip_hdr(skb)->daddr,
108 ip_hdr(skb)->saddr);
103} 109}
104 110
105int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp) 111int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
@@ -145,7 +151,6 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
145 struct flowi4 *fl4; 151 struct flowi4 *fl4;
146 struct rtable *rt; 152 struct rtable *rt;
147 int err; 153 int err;
148 u32 seq;
149 struct ip_options_rcu *inet_opt; 154 struct ip_options_rcu *inet_opt;
150 struct inet_timewait_death_row *tcp_death_row = &sock_net(sk)->ipv4.tcp_death_row; 155 struct inet_timewait_death_row *tcp_death_row = &sock_net(sk)->ipv4.tcp_death_row;
151 156
@@ -232,13 +237,13 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
232 rt = NULL; 237 rt = NULL;
233 238
234 if (likely(!tp->repair)) { 239 if (likely(!tp->repair)) {
235 seq = secure_tcp_seq_and_tsoff(inet->inet_saddr,
236 inet->inet_daddr,
237 inet->inet_sport,
238 usin->sin_port,
239 &tp->tsoffset);
240 if (!tp->write_seq) 240 if (!tp->write_seq)
241 tp->write_seq = seq; 241 tp->write_seq = secure_tcp_seq(inet->inet_saddr,
242 inet->inet_daddr,
243 inet->inet_sport,
244 usin->sin_port);
245 tp->tsoffset = secure_tcp_ts_off(inet->inet_saddr,
246 inet->inet_daddr);
242 } 247 }
243 248
244 inet->inet_id = tp->write_seq ^ jiffies; 249 inet->inet_id = tp->write_seq ^ jiffies;
@@ -1239,7 +1244,8 @@ static const struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = {
1239 .cookie_init_seq = cookie_v4_init_sequence, 1244 .cookie_init_seq = cookie_v4_init_sequence,
1240#endif 1245#endif
1241 .route_req = tcp_v4_route_req, 1246 .route_req = tcp_v4_route_req,
1242 .init_seq_tsoff = tcp_v4_init_seq_and_tsoff, 1247 .init_seq = tcp_v4_init_seq,
1248 .init_ts_off = tcp_v4_init_ts_off,
1243 .send_synack = tcp_v4_send_synack, 1249 .send_synack = tcp_v4_send_synack,
1244}; 1250};
1245 1251
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
index 895ff650db43..5abc3692b901 100644
--- a/net/ipv6/syncookies.c
+++ b/net/ipv6/syncookies.c
@@ -18,6 +18,7 @@
18#include <linux/random.h> 18#include <linux/random.h>
19#include <linux/siphash.h> 19#include <linux/siphash.h>
20#include <linux/kernel.h> 20#include <linux/kernel.h>
21#include <net/secure_seq.h>
21#include <net/ipv6.h> 22#include <net/ipv6.h>
22#include <net/tcp.h> 23#include <net/tcp.h>
23 24
@@ -143,6 +144,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
143 int mss; 144 int mss;
144 struct dst_entry *dst; 145 struct dst_entry *dst;
145 __u8 rcv_wscale; 146 __u8 rcv_wscale;
147 u32 tsoff = 0;
146 148
147 if (!sock_net(sk)->ipv4.sysctl_tcp_syncookies || !th->ack || th->rst) 149 if (!sock_net(sk)->ipv4.sysctl_tcp_syncookies || !th->ack || th->rst)
148 goto out; 150 goto out;
@@ -162,6 +164,12 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
162 memset(&tcp_opt, 0, sizeof(tcp_opt)); 164 memset(&tcp_opt, 0, sizeof(tcp_opt));
163 tcp_parse_options(skb, &tcp_opt, 0, NULL); 165 tcp_parse_options(skb, &tcp_opt, 0, NULL);
164 166
167 if (tcp_opt.saw_tstamp && tcp_opt.rcv_tsecr) {
168 tsoff = secure_tcpv6_ts_off(ipv6_hdr(skb)->daddr.s6_addr32,
169 ipv6_hdr(skb)->saddr.s6_addr32);
170 tcp_opt.rcv_tsecr -= tsoff;
171 }
172
165 if (!cookie_timestamp_decode(&tcp_opt)) 173 if (!cookie_timestamp_decode(&tcp_opt))
166 goto out; 174 goto out;
167 175
@@ -242,7 +250,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
242 ireq->rcv_wscale = rcv_wscale; 250 ireq->rcv_wscale = rcv_wscale;
243 ireq->ecn_ok = cookie_ecn_ok(&tcp_opt, sock_net(sk), dst); 251 ireq->ecn_ok = cookie_ecn_ok(&tcp_opt, sock_net(sk), dst);
244 252
245 ret = tcp_get_cookie_sock(sk, skb, req, dst); 253 ret = tcp_get_cookie_sock(sk, skb, req, dst, tsoff);
246out: 254out:
247 return ret; 255 return ret;
248out_free: 256out_free:
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 8e42e8f54b70..aeb9497b5bb7 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -101,12 +101,18 @@ static void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb)
101 } 101 }
102} 102}
103 103
104static u32 tcp_v6_init_seq_and_tsoff(const struct sk_buff *skb, u32 *tsoff) 104static u32 tcp_v6_init_seq(const struct sk_buff *skb)
105{ 105{
106 return secure_tcpv6_seq_and_tsoff(ipv6_hdr(skb)->daddr.s6_addr32, 106 return secure_tcpv6_seq(ipv6_hdr(skb)->daddr.s6_addr32,
107 ipv6_hdr(skb)->saddr.s6_addr32, 107 ipv6_hdr(skb)->saddr.s6_addr32,
108 tcp_hdr(skb)->dest, 108 tcp_hdr(skb)->dest,
109 tcp_hdr(skb)->source, tsoff); 109 tcp_hdr(skb)->source);
110}
111
112static u32 tcp_v6_init_ts_off(const struct sk_buff *skb)
113{
114 return secure_tcpv6_ts_off(ipv6_hdr(skb)->daddr.s6_addr32,
115 ipv6_hdr(skb)->saddr.s6_addr32);
110} 116}
111 117
112static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, 118static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
@@ -122,7 +128,6 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
122 struct flowi6 fl6; 128 struct flowi6 fl6;
123 struct dst_entry *dst; 129 struct dst_entry *dst;
124 int addr_type; 130 int addr_type;
125 u32 seq;
126 int err; 131 int err;
127 struct inet_timewait_death_row *tcp_death_row = &sock_net(sk)->ipv4.tcp_death_row; 132 struct inet_timewait_death_row *tcp_death_row = &sock_net(sk)->ipv4.tcp_death_row;
128 133
@@ -282,13 +287,13 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
282 sk_set_txhash(sk); 287 sk_set_txhash(sk);
283 288
284 if (likely(!tp->repair)) { 289 if (likely(!tp->repair)) {
285 seq = secure_tcpv6_seq_and_tsoff(np->saddr.s6_addr32,
286 sk->sk_v6_daddr.s6_addr32,
287 inet->inet_sport,
288 inet->inet_dport,
289 &tp->tsoffset);
290 if (!tp->write_seq) 290 if (!tp->write_seq)
291 tp->write_seq = seq; 291 tp->write_seq = secure_tcpv6_seq(np->saddr.s6_addr32,
292 sk->sk_v6_daddr.s6_addr32,
293 inet->inet_sport,
294 inet->inet_dport);
295 tp->tsoffset = secure_tcpv6_ts_off(np->saddr.s6_addr32,
296 sk->sk_v6_daddr.s6_addr32);
292 } 297 }
293 298
294 if (tcp_fastopen_defer_connect(sk, &err)) 299 if (tcp_fastopen_defer_connect(sk, &err))
@@ -749,7 +754,8 @@ static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = {
749 .cookie_init_seq = cookie_v6_init_sequence, 754 .cookie_init_seq = cookie_v6_init_sequence,
750#endif 755#endif
751 .route_req = tcp_v6_route_req, 756 .route_req = tcp_v6_route_req,
752 .init_seq_tsoff = tcp_v6_init_seq_and_tsoff, 757 .init_seq = tcp_v6_init_seq,
758 .init_ts_off = tcp_v6_init_ts_off,
753 .send_synack = tcp_v6_send_synack, 759 .send_synack = tcp_v6_send_synack,
754}; 760};
755 761