aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2016-12-01 05:32:06 -0500
committerDavid S. Miller <davem@davemloft.net>2016-12-02 12:49:59 -0500
commit95a22caee396cef0bb2ca8fafdd82966a49367bb (patch)
treeba58ca9c85a73dc887096d8123d199b3d28a705c /net
parent7df5358d4707c6f0a26266d3a4dd97fd353947e2 (diff)
tcp: randomize tcp timestamp offsets for each connection
jiffies based timestamps allow for easy inference of number of devices behind NAT translators and also makes tracking of hosts simpler. commit ceaa1fef65a7c2e ("tcp: adding a per-socket timestamp offset") added the main infrastructure that is needed for per-connection ts randomization, in particular writing/reading the on-wire tcp header format takes the offset into account so rest of stack can use normal tcp_time_stamp (jiffies). So only two items are left: - add a tsoffset for request sockets - extend the tcp isn generator to also return another 32bit number in addition to the ISN. Re-use of ISN generator also means timestamps are still monotonically increasing for same connection quadruple, i.e. PAWS will still work. Includes fixes from Eric Dumazet. Signed-off-by: Florian Westphal <fw@strlen.de> Acked-by: Eric Dumazet <edumazet@google.com> Acked-by: Yuchung Cheng <ycheng@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/secure_seq.c10
-rw-r--r--net/ipv4/syncookies.c1
-rw-r--r--net/ipv4/tcp_input.c7
-rw-r--r--net/ipv4/tcp_ipv4.c9
-rw-r--r--net/ipv4/tcp_minisocks.c4
-rw-r--r--net/ipv4/tcp_output.c2
-rw-r--r--net/ipv6/syncookies.c1
-rw-r--r--net/ipv6/tcp_ipv6.c10
8 files changed, 29 insertions, 15 deletions
diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c
index fd3ce461fbe6..a8d6062cbb4a 100644
--- a/net/core/secure_seq.c
+++ b/net/core/secure_seq.c
@@ -40,8 +40,8 @@ static u32 seq_scale(u32 seq)
40#endif 40#endif
41 41
42#if IS_ENABLED(CONFIG_IPV6) 42#if IS_ENABLED(CONFIG_IPV6)
43__u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr, 43u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr,
44 __be16 sport, __be16 dport) 44 __be16 sport, __be16 dport, u32 *tsoff)
45{ 45{
46 u32 secret[MD5_MESSAGE_BYTES / 4]; 46 u32 secret[MD5_MESSAGE_BYTES / 4];
47 u32 hash[MD5_DIGEST_WORDS]; 47 u32 hash[MD5_DIGEST_WORDS];
@@ -58,6 +58,7 @@ __u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr,
58 58
59 md5_transform(hash, secret); 59 md5_transform(hash, secret);
60 60
61 *tsoff = hash[1];
61 return seq_scale(hash[0]); 62 return seq_scale(hash[0]);
62} 63}
63EXPORT_SYMBOL(secure_tcpv6_sequence_number); 64EXPORT_SYMBOL(secure_tcpv6_sequence_number);
@@ -86,8 +87,8 @@ EXPORT_SYMBOL(secure_ipv6_port_ephemeral);
86 87
87#ifdef CONFIG_INET 88#ifdef CONFIG_INET
88 89
89__u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr, 90u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
90 __be16 sport, __be16 dport) 91 __be16 sport, __be16 dport, u32 *tsoff)
91{ 92{
92 u32 hash[MD5_DIGEST_WORDS]; 93 u32 hash[MD5_DIGEST_WORDS];
93 94
@@ -99,6 +100,7 @@ __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
99 100
100 md5_transform(hash, net_secret); 101 md5_transform(hash, net_secret);
101 102
103 *tsoff = hash[1];
102 return seq_scale(hash[0]); 104 return seq_scale(hash[0]);
103} 105}
104 106
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index 0dc6286272aa..3e88467d70ee 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -334,6 +334,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
334 treq = tcp_rsk(req); 334 treq = tcp_rsk(req);
335 treq->rcv_isn = ntohl(th->seq) - 1; 335 treq->rcv_isn = ntohl(th->seq) - 1;
336 treq->snt_isn = cookie; 336 treq->snt_isn = cookie;
337 treq->ts_off = 0;
337 req->mss = mss; 338 req->mss = mss;
338 ireq->ir_num = ntohs(th->dest); 339 ireq->ir_num = ntohs(th->dest);
339 ireq->ir_rmt_port = th->source; 340 ireq->ir_rmt_port = th->source;
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 56fe736fd64d..2257de244622 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -6307,6 +6307,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
6307 goto drop; 6307 goto drop;
6308 6308
6309 tcp_rsk(req)->af_specific = af_ops; 6309 tcp_rsk(req)->af_specific = af_ops;
6310 tcp_rsk(req)->ts_off = 0;
6310 6311
6311 tcp_clear_options(&tmp_opt); 6312 tcp_clear_options(&tmp_opt);
6312 tmp_opt.mss_clamp = af_ops->mss_clamp; 6313 tmp_opt.mss_clamp = af_ops->mss_clamp;
@@ -6328,6 +6329,9 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
6328 if (security_inet_conn_request(sk, skb, req)) 6329 if (security_inet_conn_request(sk, skb, req))
6329 goto drop_and_free; 6330 goto drop_and_free;
6330 6331
6332 if (isn && tmp_opt.tstamp_ok)
6333 af_ops->init_seq(skb, &tcp_rsk(req)->ts_off);
6334
6331 if (!want_cookie && !isn) { 6335 if (!want_cookie && !isn) {
6332 /* VJ's idea. We save last timestamp seen 6336 /* VJ's idea. We save last timestamp seen
6333 * from the destination in peer table, when entering 6337 * from the destination in peer table, when entering
@@ -6368,7 +6372,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
6368 goto drop_and_release; 6372 goto drop_and_release;
6369 } 6373 }
6370 6374
6371 isn = af_ops->init_seq(skb); 6375 isn = af_ops->init_seq(skb, &tcp_rsk(req)->ts_off);
6372 } 6376 }
6373 if (!dst) { 6377 if (!dst) {
6374 dst = af_ops->route_req(sk, &fl, req, NULL); 6378 dst = af_ops->route_req(sk, &fl, req, NULL);
@@ -6380,6 +6384,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
6380 6384
6381 if (want_cookie) { 6385 if (want_cookie) {
6382 isn = cookie_init_sequence(af_ops, sk, skb, &req->mss); 6386 isn = cookie_init_sequence(af_ops, sk, skb, &req->mss);
6387 tcp_rsk(req)->ts_off = 0;
6383 req->cookie_ts = tmp_opt.tstamp_ok; 6388 req->cookie_ts = tmp_opt.tstamp_ok;
6384 if (!tmp_opt.tstamp_ok) 6389 if (!tmp_opt.tstamp_ok)
6385 inet_rsk(req)->ecn_ok = 0; 6390 inet_rsk(req)->ecn_ok = 0;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 5555eb86e549..b50f05905ced 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -95,12 +95,12 @@ static int tcp_v4_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key,
95struct inet_hashinfo tcp_hashinfo; 95struct inet_hashinfo tcp_hashinfo;
96EXPORT_SYMBOL(tcp_hashinfo); 96EXPORT_SYMBOL(tcp_hashinfo);
97 97
98static __u32 tcp_v4_init_sequence(const struct sk_buff *skb) 98static u32 tcp_v4_init_sequence(const struct sk_buff *skb, u32 *tsoff)
99{ 99{
100 return secure_tcp_sequence_number(ip_hdr(skb)->daddr, 100 return secure_tcp_sequence_number(ip_hdr(skb)->daddr,
101 ip_hdr(skb)->saddr, 101 ip_hdr(skb)->saddr,
102 tcp_hdr(skb)->dest, 102 tcp_hdr(skb)->dest,
103 tcp_hdr(skb)->source); 103 tcp_hdr(skb)->source, tsoff);
104} 104}
105 105
106int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp) 106int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
@@ -237,7 +237,8 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
237 tp->write_seq = secure_tcp_sequence_number(inet->inet_saddr, 237 tp->write_seq = secure_tcp_sequence_number(inet->inet_saddr,
238 inet->inet_daddr, 238 inet->inet_daddr,
239 inet->inet_sport, 239 inet->inet_sport,
240 usin->sin_port); 240 usin->sin_port,
241 &tp->tsoffset);
241 242
242 inet->inet_id = tp->write_seq ^ jiffies; 243 inet->inet_id = tp->write_seq ^ jiffies;
243 244
@@ -824,7 +825,7 @@ static void tcp_v4_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,
824 tcp_v4_send_ack(sk, skb, seq, 825 tcp_v4_send_ack(sk, skb, seq,
825 tcp_rsk(req)->rcv_nxt, 826 tcp_rsk(req)->rcv_nxt,
826 req->rsk_rcv_wnd >> inet_rsk(req)->rcv_wscale, 827 req->rsk_rcv_wnd >> inet_rsk(req)->rcv_wscale,
827 tcp_time_stamp, 828 tcp_time_stamp + tcp_rsk(req)->ts_off,
828 req->ts_recent, 829 req->ts_recent,
829 0, 830 0,
830 tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&ip_hdr(skb)->daddr, 831 tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&ip_hdr(skb)->daddr,
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 6234ebaa7db1..28ce5ee831f5 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -532,7 +532,7 @@ struct sock *tcp_create_openreq_child(const struct sock *sk,
532 newtp->rx_opt.ts_recent_stamp = 0; 532 newtp->rx_opt.ts_recent_stamp = 0;
533 newtp->tcp_header_len = sizeof(struct tcphdr); 533 newtp->tcp_header_len = sizeof(struct tcphdr);
534 } 534 }
535 newtp->tsoffset = 0; 535 newtp->tsoffset = treq->ts_off;
536#ifdef CONFIG_TCP_MD5SIG 536#ifdef CONFIG_TCP_MD5SIG
537 newtp->md5sig_info = NULL; /*XXX*/ 537 newtp->md5sig_info = NULL; /*XXX*/
538 if (newtp->af_specific->md5_lookup(sk, newsk)) 538 if (newtp->af_specific->md5_lookup(sk, newsk))
@@ -581,6 +581,8 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
581 581
582 if (tmp_opt.saw_tstamp) { 582 if (tmp_opt.saw_tstamp) {
583 tmp_opt.ts_recent = req->ts_recent; 583 tmp_opt.ts_recent = req->ts_recent;
584 if (tmp_opt.rcv_tsecr)
585 tmp_opt.rcv_tsecr -= tcp_rsk(req)->ts_off;
584 /* We do not store true stamp, but it is not required, 586 /* We do not store true stamp, but it is not required,
585 * it can be estimated (approximately) 587 * it can be estimated (approximately)
586 * from another data. 588 * from another data.
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index d3545d0cff75..c7adcb57654e 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -640,7 +640,7 @@ static unsigned int tcp_synack_options(struct request_sock *req,
640 } 640 }
641 if (likely(ireq->tstamp_ok)) { 641 if (likely(ireq->tstamp_ok)) {
642 opts->options |= OPTION_TS; 642 opts->options |= OPTION_TS;
643 opts->tsval = tcp_skb_timestamp(skb); 643 opts->tsval = tcp_skb_timestamp(skb) + tcp_rsk(req)->ts_off;
644 opts->tsecr = req->ts_recent; 644 opts->tsecr = req->ts_recent;
645 remaining -= TCPOLEN_TSTAMP_ALIGNED; 645 remaining -= TCPOLEN_TSTAMP_ALIGNED;
646 } 646 }
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
index 97830a6a9cbb..a4d49760bf43 100644
--- a/net/ipv6/syncookies.c
+++ b/net/ipv6/syncookies.c
@@ -209,6 +209,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
209 treq->snt_synack.v64 = 0; 209 treq->snt_synack.v64 = 0;
210 treq->rcv_isn = ntohl(th->seq) - 1; 210 treq->rcv_isn = ntohl(th->seq) - 1;
211 treq->snt_isn = cookie; 211 treq->snt_isn = cookie;
212 treq->ts_off = 0;
212 213
213 /* 214 /*
214 * We need to lookup the dst_entry to get the correct window size. 215 * We need to lookup the dst_entry to get the correct window size.
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 28ec0a2e7b72..a2185a214abc 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -101,12 +101,12 @@ 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_sequence(const struct sk_buff *skb) 104static u32 tcp_v6_init_sequence(const struct sk_buff *skb, u32 *tsoff)
105{ 105{
106 return secure_tcpv6_sequence_number(ipv6_hdr(skb)->daddr.s6_addr32, 106 return secure_tcpv6_sequence_number(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); 109 tcp_hdr(skb)->source, tsoff);
110} 110}
111 111
112static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, 112static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
@@ -283,7 +283,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
283 tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32, 283 tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32,
284 sk->sk_v6_daddr.s6_addr32, 284 sk->sk_v6_daddr.s6_addr32,
285 inet->inet_sport, 285 inet->inet_sport,
286 inet->inet_dport); 286 inet->inet_dport,
287 &tp->tsoffset);
287 288
288 err = tcp_connect(sk); 289 err = tcp_connect(sk);
289 if (err) 290 if (err)
@@ -956,7 +957,8 @@ static void tcp_v6_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,
956 tcp_rsk(req)->snt_isn + 1 : tcp_sk(sk)->snd_nxt, 957 tcp_rsk(req)->snt_isn + 1 : tcp_sk(sk)->snd_nxt,
957 tcp_rsk(req)->rcv_nxt, 958 tcp_rsk(req)->rcv_nxt,
958 req->rsk_rcv_wnd >> inet_rsk(req)->rcv_wscale, 959 req->rsk_rcv_wnd >> inet_rsk(req)->rcv_wscale,
959 tcp_time_stamp, req->ts_recent, sk->sk_bound_dev_if, 960 tcp_time_stamp + tcp_rsk(req)->ts_off,
961 req->ts_recent, sk->sk_bound_dev_if,
960 tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr), 962 tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr),
961 0, 0); 963 0, 0);
962} 964}