From patchwork Fri Dec 13 20:52:13 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 1209455 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=arndb.de Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 47ZNF10YP4z9sR0 for ; Sat, 14 Dec 2019 07:53:57 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726826AbfLMUxu (ORCPT ); Fri, 13 Dec 2019 15:53:50 -0500 Received: from mout.kundenserver.de ([212.227.126.187]:43261 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725937AbfLMUxt (ORCPT ); Fri, 13 Dec 2019 15:53:49 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue012 [212.227.15.129]) with ESMTPA (Nemesis) id 1Mf3yk-1i3ky22RkQ-00gY1h; Fri, 13 Dec 2019 21:53:36 +0100 From: Arnd Bergmann To: y2038@lists.linaro.org, linux-kernel@vger.kernel.org, "David S. Miller" Cc: Arnd Bergmann , Willem de Bruijn , Eric Dumazet , Maxim Mikityanskiy , Paolo Abeni , netdev@vger.kernel.org Subject: [PATCH v2 08/24] packet: clarify timestamp overflow Date: Fri, 13 Dec 2019 21:52:13 +0100 Message-Id: <20191213205221.3787308-5-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191213204936.3643476-1-arnd@arndb.de> References: <20191213204936.3643476-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:kKBta+G+as32YcXvSh8tqOxFF8jEv1GeP9pum+Ut03Clje4yb0Y szlos7jj5U38a9OyuzukApS8mGz2pEGMpu1kdmhnUtVYGq1KoMKrBMvwG2Ju1qHHmp6TxBX Ckl2dSzUfranvLS9EdhP4rZF83JADlDdY8rQeETo2twFKq2U+Hc5gvv4bWLL/UDNPmm4X9p JVMHJaWzJlbVlDbLw7GIQ== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1; V03:K0:IRdm5OTc3rE=:EZmf5cbRyzKAHD8CnHoxmH gRxlyJt2cIfonuW1EgiTb6S6CC3kH7g5rzAgTaMgZ0k1RpIInOJ2F8y2+gd9A6VUVkKi5JCGb kd3iCHr+Obp8BOvM4r1mNwxlrC+n9BXx0w+2KXY6qh2qXG4lNnP1LNV+ftLNGZtPFNdGOrKcr wsh4atIZsxCGAek99Bp7zpXILcoh8saZ3vcIf+IuU9ytJDcsTP02o2wd4tQPS8FuXsZG/EYpG gP6AS9n28Y9Q5BEtZXdAAM6SeL4CGa+8eL10mRk9ruYXac+Uyk50eNmdioIsalwVYhAQPqN8g sD5ZAbLLfyKD01KehEeUvUEtOJMNUdtUaaDUGmvQx6LkICIZjvEKGY7tfG3W4jxBJ5+fRR3It 8D81cJPCLAx8nBmUVJXvnDtvRYZSI2xaDDdi+v4p7ge5IviGf4LvGxsUqG22NAIuIsEGPwswR MRpgwWx95S8xjpP+eM8f35d4yEg8Zwl8cf0QSE2vRpxNTSN6BAC23Ugpc0MgkaZvTN6PlgHy3 3Yh1MDgPA8QogrIr5jLZby5BU44A12q/x8ulD0APdnweT0jCXUQqUm2wLBb3dbSpdtinVL147 5kntc3jlnYo6w1mCqN9CRLprjxVgRpKRgCR3UEcqVEYjOLu2pY7wTgGZOOfyYAuJotpjSCjr/ XlSIPO8GPwp3rLOl6z/JJoPmio90dX0nZi0jpOFeN9uHM9zbTXcnSGed0EnppfrcBJMoVR+YR 3ZyCOZjrtvRn5uKUkBZwnN1TgWzSHQpGViJqM8zRLcUpooFBFjgaWbyMEEB0HDT06PmgwsZKV ybKqE9JyyG90ElcZMYr1x0qseCj9ADA+RrT2+g9cu3G0ogv7a92+boY1NSUaS8oRVuYX9JbMU 1ytJBPm9j09YOD61HG6Q== Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The memory mapped packet socket data structure in version 1 through 3 all contain 32-bit second values for the packet time stamps, which makes them suffer from the overflow of time_t in y2038 or y2106 (depending on whether user space interprets the value as signed or unsigned). The implementation uses the deprecated getnstimeofday() function. In order to get rid of that, this changes the code to use ktime_get_real_ts64() as a replacement, documenting the nature of the overflow. As long as the user applications treat the timestamps as unsigned, or only use the difference between timestamps, they are fine, and changing the timestamps to 64-bit wouldn't require a more invasive user space API change. Note: a lot of other APIs suffer from incompatible structures when time_t gets redefined to 64-bit in 32-bit user space, but this one does not. Acked-by: Willem de Bruijn Link: https://lore.kernel.org/lkml/CAF=yD-Jomr-gWSR-EBNKnSpFL46UeG564FLfqTCMNEm-prEaXA@mail.gmail.com/T/#u Signed-off-by: Arnd Bergmann --- net/packet/af_packet.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 53c1d41fb1c9..60300f3fcddc 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -408,17 +408,17 @@ static int __packet_get_status(const struct packet_sock *po, void *frame) } } -static __u32 tpacket_get_timestamp(struct sk_buff *skb, struct timespec *ts, +static __u32 tpacket_get_timestamp(struct sk_buff *skb, struct timespec64 *ts, unsigned int flags) { struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb); if (shhwtstamps && (flags & SOF_TIMESTAMPING_RAW_HARDWARE) && - ktime_to_timespec_cond(shhwtstamps->hwtstamp, ts)) + ktime_to_timespec64_cond(shhwtstamps->hwtstamp, ts)) return TP_STATUS_TS_RAW_HARDWARE; - if (ktime_to_timespec_cond(skb->tstamp, ts)) + if (ktime_to_timespec64_cond(skb->tstamp, ts)) return TP_STATUS_TS_SOFTWARE; return 0; @@ -428,13 +428,20 @@ static __u32 __packet_set_timestamp(struct packet_sock *po, void *frame, struct sk_buff *skb) { union tpacket_uhdr h; - struct timespec ts; + struct timespec64 ts; __u32 ts_status; if (!(ts_status = tpacket_get_timestamp(skb, &ts, po->tp_tstamp))) return 0; h.raw = frame; + /* + * versions 1 through 3 overflow the timestamps in y2106, since they + * all store the seconds in a 32-bit unsigned integer. + * If we create a version 4, that should have a 64-bit timestamp, + * either 64-bit seconds + 32-bit nanoseconds, or just 64-bit + * nanoseconds. + */ switch (po->tp_version) { case TPACKET_V1: h.h1->tp_sec = ts.tv_sec; @@ -774,8 +781,8 @@ static void prb_close_block(struct tpacket_kbdq_core *pkc1, * It shouldn't really happen as we don't close empty * blocks. See prb_retire_rx_blk_timer_expired(). */ - struct timespec ts; - getnstimeofday(&ts); + struct timespec64 ts; + ktime_get_real_ts64(&ts); h1->ts_last_pkt.ts_sec = ts.tv_sec; h1->ts_last_pkt.ts_nsec = ts.tv_nsec; } @@ -805,7 +812,7 @@ static void prb_thaw_queue(struct tpacket_kbdq_core *pkc) static void prb_open_block(struct tpacket_kbdq_core *pkc1, struct tpacket_block_desc *pbd1) { - struct timespec ts; + struct timespec64 ts; struct tpacket_hdr_v1 *h1 = &pbd1->hdr.bh1; smp_rmb(); @@ -818,7 +825,7 @@ static void prb_open_block(struct tpacket_kbdq_core *pkc1, BLOCK_NUM_PKTS(pbd1) = 0; BLOCK_LEN(pbd1) = BLK_PLUS_PRIV(pkc1->blk_sizeof_priv); - getnstimeofday(&ts); + ktime_get_real_ts64(&ts); h1->ts_first_pkt.ts_sec = ts.tv_sec; h1->ts_first_pkt.ts_nsec = ts.tv_nsec; @@ -2168,7 +2175,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, unsigned long status = TP_STATUS_USER; unsigned short macoff, netoff, hdrlen; struct sk_buff *copy_skb = NULL; - struct timespec ts; + struct timespec64 ts; __u32 ts_status; bool is_drop_n_account = false; bool do_vnet = false; @@ -2300,7 +2307,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, skb_copy_bits(skb, 0, h.raw + macoff, snaplen); if (!(ts_status = tpacket_get_timestamp(skb, &ts, po->tp_tstamp))) - getnstimeofday(&ts); + ktime_get_real_ts64(&ts); status |= ts_status; From patchwork Fri Dec 13 20:53:43 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 1209457 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=arndb.de Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 47ZNJX0MTdz9sPh for ; Sat, 14 Dec 2019 07:57:00 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726713AbfLMU44 (ORCPT ); Fri, 13 Dec 2019 15:56:56 -0500 Received: from mout.kundenserver.de ([212.227.126.135]:48953 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725747AbfLMU4z (ORCPT ); Fri, 13 Dec 2019 15:56:55 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue010 [212.227.15.129]) with ESMTPA (Nemesis) id 1M7sUE-1iatty0MiI-004zAm; Fri, 13 Dec 2019 21:56:24 +0100 From: Arnd Bergmann To: y2038@lists.linaro.org, linux-kernel@vger.kernel.org, "J. Bruce Fields" , Chuck Lever , Trond Myklebust , Anna Schumaker , "David S. Miller" Cc: Arnd Bergmann , Simo Sorce , Eric Biggers , Herbert Xu , Bruce Fields , linux-nfs@vger.kernel.org, netdev@vger.kernel.org Subject: [PATCH v2 15/24] sunrpc: convert to time64_t for expiry Date: Fri, 13 Dec 2019 21:53:43 +0100 Message-Id: <20191213205417.3871055-6-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191213204936.3643476-1-arnd@arndb.de> References: <20191213204936.3643476-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:RkDeIaFu6tTIaveO+DHQKcjxBAB7BEHoQZvY2uFHzWjSYL9X+Lx mzQe0jVYOkFmWsPcEWpDftiypK700MdwLlAC5qHAnYw/dM8edUwm+Nvgn59UcxvmMnrXtFC BPjnhGYXWorgsajgWORN1DsJp0bCmKmgUk+4B9lqB2Oa400G0AdEjnGetqrNtA3X2c/Cz7w 3gqATfZJ2wxJUqTZA0O+w== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1; V03:K0:4xIoJv151vc=:EjO59GyBCVMiLbjrWvBAmc P1ThtoYjwjePIQ0tzE2plQ54sqhA06sclv6rfW73/e9ZxajyIfvD/CHxMkAk18L5s/8S73GWJ HcUYGis6cW7xAPt4vqT0YQNqiJtTBelhYL+NTpNEWuHoRStoRYLypFpJPNXAgXavnYJs0IdPy gkgBNDpKsgmL+yBUayrRWobfKhdHffP0LNysiTtzOzx5JmrX57hIdqH2nlHtWOLC/gc+gWNeX RU8BWuFrqw+6hELw1Y0jBvNohB6zZTXX+1/twtli6t/poGfEtrI8mhA4YWlvlmya1kjgW3Qo/ QUGuxQhEEAXcy/D0YmAFM/PxMcM8BAVrvo0MpW8Jo6cB7uSK6GvFZH2hUygcSyjyza09meChQ soXDRXWvgjif8CbzDUbZQs9axsgAWoYJy3Q7rLpg7h3qO0nXv3G4LOCrxoxQNS8Z8XXScjb1r WUdsIvx7vxmSVyNHQxmHduqCUQ5HTVeUvcegoH1RzkKUlVf4pCEMXxuvsWAcvtnYXmfGgZXoH mSVCWIL7x/jAcuDb3fvxpFZZCJh6nWN+2gsN8s0U1l/8vGWF4f3TiAaMVWIPUjFdUSRPtNtsu SNhhqwYQwrDxhpOlX5IFrw9IzhZUwS9j3JTVBTHavWtOhjtkTO/7J1v75RP7RlAKE9AOpMANX e56lfM1GrecgvziKOwlVbqwNaoCWfd5JAvrl36ceFDGXH1AKLvU/ipR1Kob+jY6hdufwmpC2y 985ESbrWyeFUJjkGeEKqiPvobI9ubS6kiA1MUpbHU/dLa0VjQ9euq0eC8WB4qIJVCRVLq7tA1 EN23CSxDp4saTvTzf363IrwVNRFY77HnmVA8qE5f8aUk5H3dq8rPF25okrsT/vdZ/wuyQwDsz NPGrVjQVZ3VWo6XU9RHg== Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Using signed 32-bit types for UTC time leads to the y2038 overflow, which is what happens in the sunrpc code at the moment. This changes the sunrpc code over to use time64_t where possible. The one exception is the gss_import_v{1,2}_context() function for kerberos5, which uses 32-bit timestamps in the protocol. Here, we can at least treat the numbers as 'unsigned', which extends the range from 2038 to 2106. Signed-off-by: Arnd Bergmann --- include/linux/sunrpc/gss_api.h | 4 ++-- include/linux/sunrpc/gss_krb5.h | 2 +- net/sunrpc/auth_gss/gss_krb5_mech.c | 12 +++++++++--- net/sunrpc/auth_gss/gss_krb5_seal.c | 8 ++++---- net/sunrpc/auth_gss/gss_krb5_unseal.c | 6 +++--- net/sunrpc/auth_gss/gss_krb5_wrap.c | 16 ++++++++-------- net/sunrpc/auth_gss/gss_mech_switch.c | 2 +- net/sunrpc/auth_gss/svcauth_gss.c | 4 ++-- 8 files changed, 30 insertions(+), 24 deletions(-) diff --git a/include/linux/sunrpc/gss_api.h b/include/linux/sunrpc/gss_api.h index bd691e08be3b..1cc6cefb1220 100644 --- a/include/linux/sunrpc/gss_api.h +++ b/include/linux/sunrpc/gss_api.h @@ -48,7 +48,7 @@ int gss_import_sec_context( size_t bufsize, struct gss_api_mech *mech, struct gss_ctx **ctx_id, - time_t *endtime, + time64_t *endtime, gfp_t gfp_mask); u32 gss_get_mic( struct gss_ctx *ctx_id, @@ -108,7 +108,7 @@ struct gss_api_ops { const void *input_token, size_t bufsize, struct gss_ctx *ctx_id, - time_t *endtime, + time64_t *endtime, gfp_t gfp_mask); u32 (*gss_get_mic)( struct gss_ctx *ctx_id, diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index 02c0412e368c..c1d77dd8ed41 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h @@ -106,9 +106,9 @@ struct krb5_ctx { struct crypto_sync_skcipher *initiator_enc_aux; u8 Ksess[GSS_KRB5_MAX_KEYLEN]; /* session key */ u8 cksum[GSS_KRB5_MAX_KEYLEN]; - s32 endtime; atomic_t seq_send; atomic64_t seq_send64; + time64_t endtime; struct xdr_netobj mech_used; u8 initiator_sign[GSS_KRB5_MAX_KEYLEN]; u8 acceptor_sign[GSS_KRB5_MAX_KEYLEN]; diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 6e5d6d240215..75b3c2e9e8f8 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -253,6 +253,7 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx) { u32 seq_send; int tmp; + u32 time32; p = simple_get_bytes(p, end, &ctx->initiate, sizeof(ctx->initiate)); if (IS_ERR(p)) @@ -290,9 +291,11 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx) p = ERR_PTR(-ENOSYS); goto out_err; } - p = simple_get_bytes(p, end, &ctx->endtime, sizeof(ctx->endtime)); + p = simple_get_bytes(p, end, &time32, sizeof(time32)); if (IS_ERR(p)) goto out_err; + /* unsigned 32-bit time overflows in year 2106 */ + ctx->endtime = (time64_t)time32; p = simple_get_bytes(p, end, &seq_send, sizeof(seq_send)); if (IS_ERR(p)) goto out_err; @@ -587,15 +590,18 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx, { u64 seq_send64; int keylen; + u32 time32; p = simple_get_bytes(p, end, &ctx->flags, sizeof(ctx->flags)); if (IS_ERR(p)) goto out_err; ctx->initiate = ctx->flags & KRB5_CTX_FLAG_INITIATOR; - p = simple_get_bytes(p, end, &ctx->endtime, sizeof(ctx->endtime)); + p = simple_get_bytes(p, end, &time32, sizeof(time32)); if (IS_ERR(p)) goto out_err; + /* unsigned 32-bit time overflows in year 2106 */ + ctx->endtime = (time64_t)time32; p = simple_get_bytes(p, end, &seq_send64, sizeof(seq_send64)); if (IS_ERR(p)) goto out_err; @@ -659,7 +665,7 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx, static int gss_import_sec_context_kerberos(const void *p, size_t len, struct gss_ctx *ctx_id, - time_t *endtime, + time64_t *endtime, gfp_t gfp_mask) { const void *end = (const void *)((const char *)p + len); diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c index 48fe4a591b54..f1d280accf43 100644 --- a/net/sunrpc/auth_gss/gss_krb5_seal.c +++ b/net/sunrpc/auth_gss/gss_krb5_seal.c @@ -131,14 +131,14 @@ gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text, struct xdr_netobj md5cksum = {.len = sizeof(cksumdata), .data = cksumdata}; void *ptr; - s32 now; + time64_t now; u32 seq_send; u8 *cksumkey; dprintk("RPC: %s\n", __func__); BUG_ON(ctx == NULL); - now = get_seconds(); + now = ktime_get_real_seconds(); ptr = setup_token(ctx, token); @@ -170,7 +170,7 @@ gss_get_mic_v2(struct krb5_ctx *ctx, struct xdr_buf *text, struct xdr_netobj cksumobj = { .len = sizeof(cksumdata), .data = cksumdata}; void *krb5_hdr; - s32 now; + time64_t now; u8 *cksumkey; unsigned int cksum_usage; __be64 seq_send_be64; @@ -198,7 +198,7 @@ gss_get_mic_v2(struct krb5_ctx *ctx, struct xdr_buf *text, memcpy(krb5_hdr + GSS_KRB5_TOK_HDR_LEN, cksumobj.data, cksumobj.len); - now = get_seconds(); + now = ktime_get_real_seconds(); return (ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE; } diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c index ef2b25b86d2f..aaab91cf24c8 100644 --- a/net/sunrpc/auth_gss/gss_krb5_unseal.c +++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c @@ -124,7 +124,7 @@ gss_verify_mic_v1(struct krb5_ctx *ctx, /* it got through unscathed. Make sure the context is unexpired */ - now = get_seconds(); + now = ktime_get_real_seconds(); if (now > ctx->endtime) return GSS_S_CONTEXT_EXPIRED; @@ -149,7 +149,7 @@ gss_verify_mic_v2(struct krb5_ctx *ctx, char cksumdata[GSS_KRB5_MAX_CKSUM_LEN]; struct xdr_netobj cksumobj = {.len = sizeof(cksumdata), .data = cksumdata}; - s32 now; + time64_t now; u8 *ptr = read_token->data; u8 *cksumkey; u8 flags; @@ -194,7 +194,7 @@ gss_verify_mic_v2(struct krb5_ctx *ctx, return GSS_S_BAD_SIG; /* it got through unscathed. Make sure the context is unexpired */ - now = get_seconds(); + now = ktime_get_real_seconds(); if (now > ctx->endtime) return GSS_S_CONTEXT_EXPIRED; diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c index 14a0aff0cd84..6c1920eed771 100644 --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c @@ -163,7 +163,7 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset, .data = cksumdata}; int blocksize = 0, plainlen; unsigned char *ptr, *msg_start; - s32 now; + time64_t now; int headlen; struct page **tmp_pages; u32 seq_send; @@ -172,7 +172,7 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset, dprintk("RPC: %s\n", __func__); - now = get_seconds(); + now = ktime_get_real_seconds(); blocksize = crypto_sync_skcipher_blocksize(kctx->enc); gss_krb5_add_padding(buf, offset, blocksize); @@ -268,7 +268,7 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) char cksumdata[GSS_KRB5_MAX_CKSUM_LEN]; struct xdr_netobj md5cksum = {.len = sizeof(cksumdata), .data = cksumdata}; - s32 now; + time64_t now; int direction; s32 seqnum; unsigned char *ptr; @@ -359,7 +359,7 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) /* it got through unscathed. Make sure the context is unexpired */ - now = get_seconds(); + now = ktime_get_real_seconds(); if (now > kctx->endtime) return GSS_S_CONTEXT_EXPIRED; @@ -439,7 +439,7 @@ gss_wrap_kerberos_v2(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf, struct page **pages) { u8 *ptr, *plainhdr; - s32 now; + time64_t now; u8 flags = 0x00; __be16 *be16ptr; __be64 *be64ptr; @@ -481,14 +481,14 @@ gss_wrap_kerberos_v2(struct krb5_ctx *kctx, u32 offset, if (err) return err; - now = get_seconds(); + now = ktime_get_real_seconds(); return (kctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE; } static u32 gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) { - s32 now; + time64_t now; u8 *ptr; u8 flags = 0x00; u16 ec, rrc; @@ -557,7 +557,7 @@ gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) /* do sequencing checks */ /* it got through unscathed. Make sure the context is unexpired */ - now = get_seconds(); + now = ktime_get_real_seconds(); if (now > kctx->endtime) return GSS_S_CONTEXT_EXPIRED; diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c index 30b7de6f3d76..d3685d4ed9e0 100644 --- a/net/sunrpc/auth_gss/gss_mech_switch.c +++ b/net/sunrpc/auth_gss/gss_mech_switch.c @@ -376,7 +376,7 @@ int gss_import_sec_context(const void *input_token, size_t bufsize, struct gss_api_mech *mech, struct gss_ctx **ctx_id, - time_t *endtime, + time64_t *endtime, gfp_t gfp_mask) { if (!(*ctx_id = kzalloc(sizeof(**ctx_id), gfp_mask))) diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index c62d1f10978b..0c3e22838ddf 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -436,7 +436,7 @@ static int rsc_parse(struct cache_detail *cd, int id; int len, rv; struct rsc rsci, *rscp = NULL; - time_t expiry; + time64_t expiry; int status = -EINVAL; struct gss_api_mech *gm = NULL; @@ -1221,7 +1221,7 @@ static int gss_proxy_save_rsc(struct cache_detail *cd, static atomic64_t ctxhctr; long long ctxh; struct gss_api_mech *gm = NULL; - time_t expiry; + time64_t expiry; int status = -EINVAL; memset(&rsci, 0, sizeof(rsci)); From patchwork Fri Dec 13 20:53:44 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 1209458 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=arndb.de Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 47ZNJt3DVpz9sPh for ; Sat, 14 Dec 2019 07:57:18 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726743AbfLMU5P (ORCPT ); Fri, 13 Dec 2019 15:57:15 -0500 Received: from mout.kundenserver.de ([212.227.126.134]:47911 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725747AbfLMU5O (ORCPT ); Fri, 13 Dec 2019 15:57:14 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue010 [212.227.15.129]) with ESMTPA (Nemesis) id 1Macf4-1i8Ard27AI-00c9CC; Fri, 13 Dec 2019 21:56:47 +0100 From: Arnd Bergmann To: y2038@lists.linaro.org, linux-kernel@vger.kernel.org, "J. Bruce Fields" , Chuck Lever , Trond Myklebust , Anna Schumaker , "David S. Miller" Cc: Arnd Bergmann , Thomas Gleixner , Jeff Layton , linux-nfs@vger.kernel.org, netdev@vger.kernel.org Subject: [PATCH v2 16/24] nfs: use time64_t internally Date: Fri, 13 Dec 2019 21:53:44 +0100 Message-Id: <20191213205417.3871055-7-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191213204936.3643476-1-arnd@arndb.de> References: <20191213204936.3643476-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:zU579cGLtM2BwOX2L6/aBNJm2mG2LNJX5rJZryF/qIu0irH6BiF ZY/JjteGsij9vQsWk3Dj+aew3UprVZlgGfztwzz6xul+TAEV6K79wojrGUoIE8ZCzm5WE6j 8KBq0afuO2eCyU1AwnwovRQvXboZv/LEA8qVC0DirLx+zt/KcYbbbSL8JVLt6310oGaM2Kk wTDJ99kbGOJq5qwuAogxQ== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1; V03:K0:EWtUItQVyk0=:EOA+z3Iv+IOZwyevr7KVIP jXwQMOg+cf5aR7Jh0dtXDGqvIqvAiYH42nbT4N3oC7mHEoSEXLoQFNTdMufsa4OIewrZoMCh2 z14/rjfPVlV7A76zSvP2NU+ifgLGFT4RtGHITc9KGom0dLiYiFVhj1LXcTNUbZGo3jnbDQfyF lhmR1Pd5Yarq/LR56qFXgJ+TtWEiiCK1ZO9FT9gQaAGzJ6erSY2mgrgIiPQ2cbUAS0gXAofRu tlHCJXgIviZNGo2EqYzHEEIfpDAwf4BFarVXnPd1Z56HzTMbnREo3yws4u5+3hXPntj7EVOKp /PGwgcytxz55P/iDOI7hPx8PB6F/GMe1gcFESzrTAu+ExTDcGCRiIyMP6ziYU/IfmZ4YsHAeE Fx9Z2P10MxSAZ/gqLW+zoKnMG/9t5Jwz7y1tVCUtRM4eHE0tT1bk45QT5+0EgLuCWAZrIxeBX Ohe3yU0QyP7OVGZ0PnSbd8jUENV5oImZlviqvOFv4oFtGA3O7DqSprNeWiogEpn2KMkyL+nB+ cyPWeOYbj6ZzvtMEPiQTL3/+OtPBXQQxAZEoUIKe2FJgrdCJYT7db9MwpT6KJ9JU2RHxpfvBk D/M18UAr3iZKTtWBuXwO75l46mCt8+lOFuu+9Yzh7L8pKgWEt5gLasRYxuHCfa5axA4Z8fR9W 9h/ibWkPpGhTROhXarsgmgq5Su2Jz10DR01iRLwEIlKT9pCr/qLoHDLc6Y7XZwtaLTFB3Pfpz 6ZXkXkvXy8c4da0vU093frsZO8cbMF/DZwjvYozTkWnRr5fF9JTK2gOmONFEMf8ifaSrgiecN fapJ4Wkjez2Pjkn25MwYRSnoKzJCaA2lUEOwHtMsf9ks8XSU4VhqPVDcR82w3vEhdBGlHp3Mq /Ap8N6uIIZ8R3+xZbJ9g== Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The timestamps for the cache are all in boottime seconds, so they don't overflow 32-bit values, but the use of time_t is deprecated because it generally does overflow when used with wall-clock time. There are multiple possible ways of avoiding it: - leave time_t, which is safe here, but forces others to look into this code to determine that it is over and over. - use a more generic type, like 'int' or 'long', which is known to be sufficient here but loses the documentation of referring to timestamps - use ktime_t everywhere, and convert into seconds in the few places where we want realtime-seconds. The conversion is sometimes expensive, but not more so than the conversion we do today. - use time64_t to clarify that this code is safe. Nothing would change for 64-bit architectures, but it is slightly less efficient on 32-bit architectures. Without a clear winner of the three approaches above, this picks the last one, favouring readability over a small performance loss on 32-bit architectures. Signed-off-by: Arnd Bergmann --- include/linux/sunrpc/cache.h | 42 +++++++++++++++++-------------- net/sunrpc/auth_gss/svcauth_gss.c | 2 +- net/sunrpc/cache.c | 16 ++++++------ net/sunrpc/svcauth_unix.c | 10 ++++---- 4 files changed, 37 insertions(+), 33 deletions(-) diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h index f8603724fbee..0f64de7caa39 100644 --- a/include/linux/sunrpc/cache.h +++ b/include/linux/sunrpc/cache.h @@ -45,8 +45,8 @@ */ struct cache_head { struct hlist_node cache_list; - time_t expiry_time; /* After time time, don't use the data */ - time_t last_refresh; /* If CACHE_PENDING, this is when upcall was + time64_t expiry_time; /* After time time, don't use the data */ + time64_t last_refresh; /* If CACHE_PENDING, this is when upcall was * sent, else this is when update was * received, though it is alway set to * be *after* ->flush_time. @@ -95,22 +95,22 @@ struct cache_detail { /* fields below this comment are for internal use * and should not be touched by cache owners */ - time_t flush_time; /* flush all cache items with + time64_t flush_time; /* flush all cache items with * last_refresh at or earlier * than this. last_refresh * is never set at or earlier * than this. */ struct list_head others; - time_t nextcheck; + time64_t nextcheck; int entries; /* fields for communication over channel */ struct list_head queue; atomic_t writers; /* how many time is /channel open */ - time_t last_close; /* if no writers, when did last close */ - time_t last_warn; /* when we last warned about no writers */ + time64_t last_close; /* if no writers, when did last close */ + time64_t last_warn; /* when we last warned about no writers */ union { struct proc_dir_entry *procfs; @@ -147,18 +147,22 @@ struct cache_deferred_req { * timestamps kept in the cache are expressed in seconds * since boot. This is the best for measuring differences in * real time. + * This reimplemnts ktime_get_boottime_seconds() in a slightly + * faster but less accurate way. When we end up converting + * back to wallclock (CLOCK_REALTIME), that error often + * cancels out during the reverse operation. */ -static inline time_t seconds_since_boot(void) +static inline time64_t seconds_since_boot(void) { - struct timespec boot; - getboottime(&boot); - return get_seconds() - boot.tv_sec; + struct timespec64 boot; + getboottime64(&boot); + return ktime_get_real_seconds() - boot.tv_sec; } -static inline time_t convert_to_wallclock(time_t sinceboot) +static inline time64_t convert_to_wallclock(time64_t sinceboot) { - struct timespec boot; - getboottime(&boot); + struct timespec64 boot; + getboottime64(&boot); return boot.tv_sec + sinceboot; } @@ -273,7 +277,7 @@ static inline int get_uint(char **bpp, unsigned int *anint) return 0; } -static inline int get_time(char **bpp, time_t *time) +static inline int get_time(char **bpp, time64_t *time) { char buf[50]; long long ll; @@ -287,20 +291,20 @@ static inline int get_time(char **bpp, time_t *time) if (kstrtoll(buf, 0, &ll)) return -EINVAL; - *time = (time_t)ll; + *time = ll; return 0; } -static inline time_t get_expiry(char **bpp) +static inline time64_t get_expiry(char **bpp) { - time_t rv; - struct timespec boot; + time64_t rv; + struct timespec64 boot; if (get_time(bpp, &rv)) return 0; if (rv < 0) return 0; - getboottime(&boot); + getboottime64(&boot); return rv - boot.tv_sec; } diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 0c3e22838ddf..311181720d79 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -203,7 +203,7 @@ static int rsi_parse(struct cache_detail *cd, char *ep; int len; struct rsi rsii, *rsip = NULL; - time_t expiry; + time64_t expiry; int status = -EINVAL; memset(&rsii, 0, sizeof(rsii)); diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index f740cb51802a..d996bf872a7c 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -42,7 +42,7 @@ static bool cache_listeners_exist(struct cache_detail *detail); static void cache_init(struct cache_head *h, struct cache_detail *detail) { - time_t now = seconds_since_boot(); + time64_t now = seconds_since_boot(); INIT_HLIST_NODE(&h->cache_list); h->flags = 0; kref_init(&h->ref); @@ -139,10 +139,10 @@ EXPORT_SYMBOL_GPL(sunrpc_cache_lookup_rcu); static void cache_dequeue(struct cache_detail *detail, struct cache_head *ch); -static void cache_fresh_locked(struct cache_head *head, time_t expiry, +static void cache_fresh_locked(struct cache_head *head, time64_t expiry, struct cache_detail *detail) { - time_t now = seconds_since_boot(); + time64_t now = seconds_since_boot(); if (now <= detail->flush_time) /* ensure it isn't immediately treated as expired */ now = detail->flush_time + 1; @@ -274,7 +274,7 @@ int cache_check(struct cache_detail *detail, struct cache_head *h, struct cache_req *rqstp) { int rv; - long refresh_age, age; + time64_t refresh_age, age; /* First decide return status as best we can */ rv = cache_is_valid(h); @@ -288,7 +288,7 @@ int cache_check(struct cache_detail *detail, rv = -ENOENT; } else if (rv == -EAGAIN || (h->expiry_time != 0 && age > refresh_age/2)) { - dprintk("RPC: Want update, refage=%ld, age=%ld\n", + dprintk("RPC: Want update, refage=%lld, age=%lld\n", refresh_age, age); if (!test_and_set_bit(CACHE_PENDING, &h->flags)) { switch (cache_make_upcall(detail, h)) { @@ -1404,7 +1404,7 @@ static int c_show(struct seq_file *m, void *p) return cd->cache_show(m, cd, NULL); ifdebug(CACHE) - seq_printf(m, "# expiry=%ld refcnt=%d flags=%lx\n", + seq_printf(m, "# expiry=%lld refcnt=%d flags=%lx\n", convert_to_wallclock(cp->expiry_time), kref_read(&cp->ref), cp->flags); cache_get(cp); @@ -1477,7 +1477,7 @@ static ssize_t read_flush(struct file *file, char __user *buf, char tbuf[22]; size_t len; - len = snprintf(tbuf, sizeof(tbuf), "%lu\n", + len = snprintf(tbuf, sizeof(tbuf), "%llu\n", convert_to_wallclock(cd->flush_time)); return simple_read_from_buffer(buf, count, ppos, tbuf, len); } @@ -1488,7 +1488,7 @@ static ssize_t write_flush(struct file *file, const char __user *buf, { char tbuf[20]; char *ep; - time_t now; + time64_t now; if (*ppos || count > sizeof(tbuf)-1) return -EINVAL; diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 5c04ba7d456b..04aa80a2d752 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -166,7 +166,7 @@ static void ip_map_request(struct cache_detail *cd, } static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class, struct in6_addr *addr); -static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm, struct unix_domain *udom, time_t expiry); +static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm, struct unix_domain *udom, time64_t expiry); static int ip_map_parse(struct cache_detail *cd, char *mesg, int mlen) @@ -187,7 +187,7 @@ static int ip_map_parse(struct cache_detail *cd, struct ip_map *ipmp; struct auth_domain *dom; - time_t expiry; + time64_t expiry; if (mesg[mlen-1] != '\n') return -EINVAL; @@ -308,7 +308,7 @@ static inline struct ip_map *ip_map_lookup(struct net *net, char *class, } static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm, - struct unix_domain *udom, time_t expiry) + struct unix_domain *udom, time64_t expiry) { struct ip_map ip; struct cache_head *ch; @@ -328,7 +328,7 @@ static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm, } static inline int ip_map_update(struct net *net, struct ip_map *ipm, - struct unix_domain *udom, time_t expiry) + struct unix_domain *udom, time64_t expiry) { struct sunrpc_net *sn; @@ -491,7 +491,7 @@ static int unix_gid_parse(struct cache_detail *cd, int rv; int i; int err; - time_t expiry; + time64_t expiry; struct unix_gid ug, *ugp; if (mesg[mlen - 1] != '\n')