From patchwork Tue Jun 19 12:36:36 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 139109 Delivered-To: patch@linaro.org Received: by 2002:a2e:970d:0:0:0:0:0 with SMTP id r13-v6csp5156969lji; Tue, 19 Jun 2018 05:38:19 -0700 (PDT) X-Google-Smtp-Source: ADUXVKKqz8w1kFqkzVKLlKG5Bhlh8AyH4lwl3QFH6Gibls9qUaV6SjjRu6vz71xRl1ybvwS+RzqM X-Received: by 2002:a17:902:28a6:: with SMTP id f35-v6mr18738134plb.110.1529411899440; Tue, 19 Jun 2018 05:38:19 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529411899; cv=none; d=google.com; s=arc-20160816; b=vHV1MsAk03MTQscf0qpuj/idrl4shcsKbGdPuH3wvbRZvMKFbw3Qc5Z9XzyYzUJcqw wR2Hw5+LU075gGeHfQPw+ahqgmqZp/vLOtS+mSaLeOZXYKCAxsVQF4VuKlw7xyli4aHl fo0q31fRwPQ79m1/gn0eAphTNzAx7sB0EDwCkXGP3bepBkB1L9gK7WGkRsLyrAoKnTWX Carxz6ArDuBxLsdkY4bGhtJXnal0KyYUw70vT+Pwoapo664bH2tCgjPKk6s6IWvFGOcY rL2DPqRJFtgHyRueY+7eeo6f/hMik1GhZMUyyXupxSWrYRxd+T408U9Uw5Epo19V0Rfn eHIQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :arc-authentication-results; bh=hMYx8TRleXxmySctuwGwivi17rdjg7wP+hhN52Ig7l0=; b=jC0FqRRGnDhENChv5hiYTexZp3mY2caQnb5tSuEi0HMt4OLkhGyNZpRrk0tvN36bT6 UgZA2C370H6Ux4JrpvVAzqlKZD/2iwp0mMgAj8UjwNuSZdyK/MuMCZOlcXWam5CNDsEK kQu9nNGOl9K/c0iU9g4Bsp7FICxE2iArWdc8lSsWN4hv69sWhwzN/AkELHgZHCkmiMhy 3kaRonVkRGSU+ttSppQrtYLNeOnBfd77q4oCRfkdwgcX0O/Ol9lTVdPJjNQbfZx7YTQb v9Aodr0zoKfPQIKN3BMle0Xmi71e/+nG/lb5POc/I7TX7e0D/cba4kmlEB0aUokpNC4u xccQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-crypto-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-crypto-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id j10-v6si18013263plg.396.2018.06.19.05.38.19; Tue, 19 Jun 2018 05:38:19 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-crypto-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-crypto-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-crypto-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S937737AbeFSMiS (ORCPT + 1 other); Tue, 19 Jun 2018 08:38:18 -0400 Received: from mout.kundenserver.de ([212.227.17.13]:58459 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S937707AbeFSMiQ (ORCPT ); Tue, 19 Jun 2018 08:38:16 -0400 Received: from wuerfel.lan ([95.208.111.237]) by mrelayeu.kundenserver.de (mreue101 [212.227.15.145]) with ESMTPA (Nemesis) id 0MbhXp-1foADT129N-00J4X3; Tue, 19 Jun 2018 14:37:34 +0200 From: Arnd Bergmann To: Herbert Xu , "David S. Miller" , Eric Dumazet , Alexey Kuznetsov , Hideaki YOSHIFUJI Cc: y2038@lists.linaro.org, Arnd Bergmann , Harsh Jain , Atul Gupta , Michael Werner , "Gustavo A. R. Silva" , Yuchung Cheng , Neal Cardwell , Soheil Hassas Yeganeh , Florian Westphal , Christoph Paasch , Lawrence Brakmo , linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org Subject: [PATCH] [net-next, v2] tcp: use monotonic timestamps for PAWS Date: Tue, 19 Jun 2018 14:36:36 +0200 Message-Id: <20180619123724.2535981-1-arnd@arndb.de> X-Mailer: git-send-email 2.9.0 X-Provags-ID: V03:K1:nGNf3Br2BKk68areSnAhlepsYxrCf7ZDopLMMAOugbKPF086z7j 5m194V706AMPJGLIwcHM4kg8PjN2dGKjmVETOIyYa3VclFS3HGZ5uVeihfkEPyKvWKE8AtB xy1qXfIAThz0D69TduHwwhsLF7MiDPsdcR2EtIQ8XTgkpCpVyYFFl48gmzhXS9CJpZrYfs1 3FOBPwjKlv8rT+oci1jHw== X-UI-Out-Filterresults: notjunk:1; V01:K0:QRV2xxjVjD0=:Gwslp0WHSIbMLAFLGqhUIg zbznaE48q0rBe3liftW+9FBYgdq21neBF2ORKs+9TlDLYXalCW/2ZARH7xJWVN/iv5ac2UNff MQ0Zy6GspJ6rBijD/LJKNpG90h2v01TSbmr5N7M4tfhtzhsesO/g+SN2MV0Sw+DTyWyysR5yr OHud1pCe+vuSNVl/Sgit2TAW7uJxxRfMBispCDsekLwKAUV5fLCMMmu3Q2N8lf1IUPwiGOYK0 Exn923dWdXP0TV01e59FJlhnJ4ekMprmwtOy6gTQAao1WY9b9OV/X1oYkS990K/fPjkmPkh7J 5Sw5g+G+AUzFHElY/fQhT6DCHay8v5QQTt6oH+8Nm5KqRUN8+iAGeHV9dkKAQBbLwUWkCY3g5 VVGh/80QLWZBa5vmYR8TmuDD8tLpjQM0E+PIO5BVnSpJZGVvjX+qf9ECdWNYqKdoz9G8nmLLr Q6pzVOChLoWKc2i84NZ47UL4TcqmknZC9iweXV6BUMjsVicZlQhGHcMGPwWQRnnsh3UMXD6zg 1OXKWpWekFT3npHrUG8skC5zobn7ijhTJ1imLnjxKn212FVZsu58rLX6MFMWC/rkzjuzAVxQq fwL3jM/PuKNRQwMaYz27w1HFsjiH5oyS6WEGf0K6PLTSkUSU3LOdaucTSzgXxgJpFHD7TMUqR O9GnTLodjI9KJXi7/UW4zyI8YHMJT0e3vajP8iwa+JZkvGeGLbrEITJQmj7IC7PpAel4= Sender: linux-crypto-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-crypto@vger.kernel.org Using get_seconds() for timestamps is deprecated since it can lead to overflows on 32-bit systems. While the interface generally doesn't overflow until year 2106, the specific implementation of the TCP PAWS algorithm breaks in 2038 when the intermediate signed 32-bit timestamps overflow. A related problem is that the local timestamps in CLOCK_REALTIME form lead to unexpected behavior when settimeofday is called to set the system clock backwards or forwards by more than 24 days. While the first problem could be solved by using an overflow-safe method of comparing the timestamps, a nicer solution is to use a monotonic clocksource with ktime_get_seconds() that simply doesn't overflow (at least not until 136 years after boot) and that doesn't change during settimeofday(). To make 32-bit and 64-bit architectures behave the same way here, and also save a few bytes in the tcp_options_received structure, I'm changing the type to a 32-bit integer, which is now safe on all architectures. Finally, the ts_recent_stamp field also (confusingly) gets used to store a jiffies value in tcp_synq_overflow()/tcp_synq_no_recent_overflow(). This is currently safe, but changing the type to 32-bit requires some small changes there to keep it working. Signed-off-by: Arnd Bergmann --- v2: use time_before32()/time_after32() everywhere as suggested Eric Dumazet --- drivers/crypto/chelsio/chtls/chtls_cm.c | 2 +- include/linux/tcp.h | 4 ++-- include/net/tcp.h | 17 ++++++++++------- net/ipv4/tcp_input.c | 2 +- net/ipv4/tcp_ipv4.c | 3 ++- net/ipv4/tcp_minisocks.c | 8 ++++---- 6 files changed, 20 insertions(+), 16 deletions(-) -- 2.9.0 Signed-off-by: Eric Dumazet diff --git a/drivers/crypto/chelsio/chtls/chtls_cm.c b/drivers/crypto/chelsio/chtls/chtls_cm.c index 2bb6f0380758..0997e166ea57 100644 --- a/drivers/crypto/chelsio/chtls/chtls_cm.c +++ b/drivers/crypto/chelsio/chtls/chtls_cm.c @@ -1673,7 +1673,7 @@ static void chtls_timewait(struct sock *sk) struct tcp_sock *tp = tcp_sk(sk); tp->rcv_nxt++; - tp->rx_opt.ts_recent_stamp = get_seconds(); + tp->rx_opt.ts_recent_stamp = ktime_get_seconds(); tp->srtt_us = 0; tcp_time_wait(sk, TCP_TIME_WAIT, 0); } diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 72705eaf4b84..f911b9b09b16 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -89,7 +89,7 @@ struct tcp_sack_block { struct tcp_options_received { /* PAWS/RTTM data */ - long ts_recent_stamp;/* Time we stored ts_recent (for aging) */ + int ts_recent_stamp;/* Time we stored ts_recent (for aging) */ u32 ts_recent; /* Time stamp to echo next */ u32 rcv_tsval; /* Time stamp value */ u32 rcv_tsecr; /* Time stamp echo reply */ @@ -425,7 +425,7 @@ struct tcp_timewait_sock { /* The time we sent the last out-of-window ACK: */ u32 tw_last_oow_ack_time; - long tw_ts_recent_stamp; + int tw_ts_recent_stamp; #ifdef CONFIG_TCP_MD5SIG struct tcp_md5sig_key *tw_md5_key; #endif diff --git a/include/net/tcp.h b/include/net/tcp.h index 0448e7c5d2b4..535dfb7f2ab4 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -471,19 +471,20 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb); */ static inline void tcp_synq_overflow(const struct sock *sk) { - unsigned long last_overflow = tcp_sk(sk)->rx_opt.ts_recent_stamp; - unsigned long now = jiffies; + unsigned int last_overflow = tcp_sk(sk)->rx_opt.ts_recent_stamp; + unsigned int now = jiffies; - if (time_after(now, last_overflow + HZ)) + if (time_after32(now, last_overflow + HZ)) tcp_sk(sk)->rx_opt.ts_recent_stamp = now; } /* syncookies: no recent synqueue overflow on this listening socket? */ static inline bool tcp_synq_no_recent_overflow(const struct sock *sk) { - unsigned long last_overflow = tcp_sk(sk)->rx_opt.ts_recent_stamp; + unsigned int last_overflow = tcp_sk(sk)->rx_opt.ts_recent_stamp; + unsigned int now = jiffies; - return time_after(jiffies, last_overflow + TCP_SYNCOOKIE_VALID); + return time_after32(now, last_overflow + TCP_SYNCOOKIE_VALID); } static inline u32 tcp_cookie_time(void) @@ -1361,7 +1362,8 @@ static inline bool tcp_paws_check(const struct tcp_options_received *rx_opt, { if ((s32)(rx_opt->ts_recent - rx_opt->rcv_tsval) <= paws_win) return true; - if (unlikely(get_seconds() >= rx_opt->ts_recent_stamp + TCP_PAWS_24DAYS)) + if (unlikely(!time_before32(ktime_get_seconds(), + rx_opt->ts_recent_stamp + TCP_PAWS_24DAYS))) return true; /* * Some OSes send SYN and SYNACK messages with tsval=0 tsecr=0, @@ -1391,7 +1393,8 @@ static inline bool tcp_paws_reject(const struct tcp_options_received *rx_opt, However, we can relax time bounds for RST segments to MSL. */ - if (rst && get_seconds() >= rx_opt->ts_recent_stamp + TCP_PAWS_MSL) + if (rst && !time_before32(ktime_get_seconds(), + rx_opt->ts_recent_stamp + TCP_PAWS_MSL)) return false; return true; } diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 355d3dffd021..0eb314774aec 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3449,7 +3449,7 @@ static void tcp_send_challenge_ack(struct sock *sk, const struct sk_buff *skb) static void tcp_store_ts_recent(struct tcp_sock *tp) { tp->rx_opt.ts_recent = tp->rx_opt.rcv_tsval; - tp->rx_opt.ts_recent_stamp = get_seconds(); + tp->rx_opt.ts_recent_stamp = ktime_get_seconds(); } static void tcp_replace_ts_recent(struct tcp_sock *tp, u32 seq) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index bea17f1e8302..dc415c66a33a 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -155,7 +155,8 @@ int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp) and use initial timestamp retrieved from peer table. */ if (tcptw->tw_ts_recent_stamp && - (!twp || (reuse && get_seconds() - tcptw->tw_ts_recent_stamp > 1))) { + (!twp || (reuse && time_after32(ktime_get_seconds(), + tcptw->tw_ts_recent_stamp)))) { tp->write_seq = tcptw->tw_snd_nxt + 65535 + 2; if (tp->write_seq == 0) tp->write_seq = 1; diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 1dda1341a223..1f652beb79ca 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -144,7 +144,7 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb, tw->tw_substate = TCP_TIME_WAIT; tcptw->tw_rcv_nxt = TCP_SKB_CB(skb)->end_seq; if (tmp_opt.saw_tstamp) { - tcptw->tw_ts_recent_stamp = get_seconds(); + tcptw->tw_ts_recent_stamp = ktime_get_seconds(); tcptw->tw_ts_recent = tmp_opt.rcv_tsval; } @@ -189,7 +189,7 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb, if (tmp_opt.saw_tstamp) { tcptw->tw_ts_recent = tmp_opt.rcv_tsval; - tcptw->tw_ts_recent_stamp = get_seconds(); + tcptw->tw_ts_recent_stamp = ktime_get_seconds(); } inet_twsk_put(tw); @@ -534,7 +534,7 @@ struct sock *tcp_create_openreq_child(const struct sock *sk, if (newtp->rx_opt.tstamp_ok) { newtp->rx_opt.ts_recent = req->ts_recent; - newtp->rx_opt.ts_recent_stamp = get_seconds(); + newtp->rx_opt.ts_recent_stamp = ktime_get_seconds(); newtp->tcp_header_len = sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED; } else { newtp->rx_opt.ts_recent_stamp = 0; @@ -600,7 +600,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, * it can be estimated (approximately) * from another data. */ - tmp_opt.ts_recent_stamp = get_seconds() - ((TCP_TIMEOUT_INIT/HZ)<num_timeout); + tmp_opt.ts_recent_stamp = ktime_get_seconds() - ((TCP_TIMEOUT_INIT/HZ)<num_timeout); paws_reject = tcp_paws_reject(&tmp_opt, th->rst); } }