LKML Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH 0/8] y2038: bug fixes from y2038 work
@ 2019-11-08 20:34 Arnd Bergmann
  2019-11-08 20:34 ` [PATCH 1/8] y2038: timex: remove incorrect time_t truncation Arnd Bergmann
                   ` (7 more replies)
  0 siblings, 8 replies; 18+ messages in thread
From: Arnd Bergmann @ 2019-11-08 20:34 UTC (permalink / raw)
  To: y2038
  Cc: linux-kernel, Arnd Bergmann, Benjamin Herrenschmidt,
	Paul Mackerras, Michael Ellerman, Corey Minyard,
	Greg Kroah-Hartman, Sudip Mukherjee, Dmitry Torokhov,
	John Stultz, Thomas Gleixner, Stephen Boyd, Pablo Neira Ayuso,
	Jozsef Kadlecsik, Florian Westphal, David S. Miller,
	linuxppc-dev, openipmi-developer, linux-input, netfilter-devel,
	coreteam, netdev, sparclinux

I've gone through the remaining uses of time_t etc and come up with a
set of 90 patches of varying complexity and importance, to the point
of being able to remove the old time_t/timeval/timespec from the kernel
headers completely.

This set includes the eight patches that I think should be merged
right away and backported into stable kernels if possible.

Please apply individual patches to the respective maintainer trees
for either v5.4 or v5.5 as appropriate.

For reference, the full series of 90 patches can be found at
https://git.kernel.org/pub/scm/linux/kernel/git/arnd/playground.git/log/?h=y2038-endgame

      Arnd

Arnd Bergmann (8):
  y2038: timex: remove incorrect time_t truncation
  timekeeping: optimize ns_to_timespec64
  powerpc: fix vdso32 for ppc64le
  ipmi: kill off 'timespec' usage again
  netfilter: xt_time: use time64_t
  lp: fix sparc64 LPSETTIMEOUT ioctl
  ppdev: fix PPGETTIME/PPSETTIME ioctls
  Input: input_event: fix struct padding on sparc64

 arch/powerpc/kernel/vdso32/gettimeofday.S |  2 +-
 drivers/char/ipmi/ipmi_si_intf.c          | 40 ++++++++---------------
 drivers/char/lp.c                         |  4 +++
 drivers/char/ppdev.c                      | 16 ++++++---
 drivers/input/evdev.c                     |  3 ++
 drivers/input/misc/uinput.c               |  3 ++
 include/uapi/linux/input.h                |  1 +
 kernel/time/ntp.c                         |  2 +-
 kernel/time/time.c                        | 21 +++++++-----
 net/netfilter/xt_time.c                   | 19 ++++++-----
 10 files changed, 61 insertions(+), 50 deletions(-)

Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Corey Minyard <minyard@acm.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Pablo Neira Ayuso <pablo@netfilter.org>
Cc: Jozsef Kadlecsik <kadlec@netfilter.org>
Cc: Florian Westphal <fw@strlen.de>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: linux-kernel@vger.kernel.org
Cc: openipmi-developer@lists.sourceforge.net
Cc: linux-input@vger.kernel.org
Cc: netfilter-devel@vger.kernel.org
Cc: coreteam@netfilter.org
Cc: netdev@vger.kernel.org
Cc: sparclinux@vger.kernel.org

-- 
2.20.0


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 1/8] y2038: timex: remove incorrect time_t truncation
  2019-11-08 20:34 [PATCH 0/8] y2038: bug fixes from y2038 work Arnd Bergmann
@ 2019-11-08 20:34 ` Arnd Bergmann
  2019-11-10 20:44   ` Deepa Dinamani
  2019-11-12  7:16   ` [tip: timers/urgent] ntp/y2038: Remove " tip-bot2 for Arnd Bergmann
  2019-11-08 20:34 ` [PATCH 2/8] timekeeping: optimize ns_to_timespec64 Arnd Bergmann
                   ` (6 subsequent siblings)
  7 siblings, 2 replies; 18+ messages in thread
From: Arnd Bergmann @ 2019-11-08 20:34 UTC (permalink / raw)
  To: y2038, John Stultz, Thomas Gleixner
  Cc: linux-kernel, Arnd Bergmann, stable, Deepa Dinamani, linux-alpha,
	netdev, Stephen Boyd

A cast to 'time_t' was accidentally left in place during the
conversion of __do_adjtimex() to 64-bit timestamps, so the
resulting value is incorrectly truncated.

Remove the cast so the 64-bit time gets propagated correctly.

Cc: stable@vger.kernel.org
Fixes: ead25417f82e ("timex: use __kernel_timex internally")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 kernel/time/ntp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index 65eb796610dc..069ca78fb0bf 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -771,7 +771,7 @@ int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts,
 	/* fill PPS status fields */
 	pps_fill_timex(txc);
 
-	txc->time.tv_sec = (time_t)ts->tv_sec;
+	txc->time.tv_sec = ts->tv_sec;
 	txc->time.tv_usec = ts->tv_nsec;
 	if (!(time_status & STA_NANO))
 		txc->time.tv_usec = ts->tv_nsec / NSEC_PER_USEC;
-- 
2.20.0


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 2/8] timekeeping: optimize ns_to_timespec64
  2019-11-08 20:34 [PATCH 0/8] y2038: bug fixes from y2038 work Arnd Bergmann
  2019-11-08 20:34 ` [PATCH 1/8] y2038: timex: remove incorrect time_t truncation Arnd Bergmann
@ 2019-11-08 20:34 ` Arnd Bergmann
  2019-11-10 20:46   ` Deepa Dinamani
  2019-11-12  7:22   ` [tip: timers/core] time: Optimize ns_to_timespec64() tip-bot2 for Arnd Bergmann
  2019-11-08 20:34 ` [PATCH 3/8] powerpc: fix vdso32 for ppc64le Arnd Bergmann
                   ` (5 subsequent siblings)
  7 siblings, 2 replies; 18+ messages in thread
From: Arnd Bergmann @ 2019-11-08 20:34 UTC (permalink / raw)
  To: y2038, John Stultz, Thomas Gleixner
  Cc: linux-kernel, Arnd Bergmann, Stephen Boyd, Deepa Dinamani

I noticed that ns_to_timespec64() calls div_s64_rem(), which is
a rather slow function on 32-bit architectures, as it cannot take
advantage of the do_div() optimizations for constant arguments.

This open-codes the div_s64_rem() function here, so we can pass
a constant divider into the optimized div_u64_rem() function.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 kernel/time/time.c | 21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/kernel/time/time.c b/kernel/time/time.c
index 5c54ca632d08..45a358953f09 100644
--- a/kernel/time/time.c
+++ b/kernel/time/time.c
@@ -550,18 +550,21 @@ EXPORT_SYMBOL(set_normalized_timespec64);
  */
 struct timespec64 ns_to_timespec64(const s64 nsec)
 {
-	struct timespec64 ts;
+	struct timespec64 ts = { 0, 0 };
 	s32 rem;
 
-	if (!nsec)
-		return (struct timespec64) {0, 0};
-
-	ts.tv_sec = div_s64_rem(nsec, NSEC_PER_SEC, &rem);
-	if (unlikely(rem < 0)) {
-		ts.tv_sec--;
-		rem += NSEC_PER_SEC;
+	if (likely(nsec > 0)) {
+		ts.tv_sec = div_u64_rem(nsec, NSEC_PER_SEC, &rem);
+		ts.tv_nsec = rem;
+	} else if (nsec < 0) {
+		/*
+		 * With negative times, tv_sec points to the earlier
+		 * second, and tv_nsec counts the nanoseconds since
+		 * then, so tv_nsec is always a positive number.
+		 */
+		ts.tv_sec = -div_u64_rem(-nsec - 1, NSEC_PER_SEC, &rem) - 1;
+		ts.tv_nsec = NSEC_PER_SEC - rem - 1;
 	}
-	ts.tv_nsec = rem;
 
 	return ts;
 }
-- 
2.20.0


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 3/8] powerpc: fix vdso32 for ppc64le
  2019-11-08 20:34 [PATCH 0/8] y2038: bug fixes from y2038 work Arnd Bergmann
  2019-11-08 20:34 ` [PATCH 1/8] y2038: timex: remove incorrect time_t truncation Arnd Bergmann
  2019-11-08 20:34 ` [PATCH 2/8] timekeeping: optimize ns_to_timespec64 Arnd Bergmann
@ 2019-11-08 20:34 ` Arnd Bergmann
  2019-11-08 20:34 ` [PATCH 4/8] ipmi: kill off 'timespec' usage again Arnd Bergmann
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 18+ messages in thread
From: Arnd Bergmann @ 2019-11-08 20:34 UTC (permalink / raw)
  To: y2038, Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
  Cc: linux-kernel, Arnd Bergmann, linuxppc-dev

On little-endian 32-bit application running on 64-bit kernels,
the current vdso would read the wrong half of the xtime seconds
field. Change it to return the lower half like it does on
big-endian.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 arch/powerpc/kernel/vdso32/gettimeofday.S | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/powerpc/kernel/vdso32/gettimeofday.S b/arch/powerpc/kernel/vdso32/gettimeofday.S
index becd9f8767ed..4327665ad86f 100644
--- a/arch/powerpc/kernel/vdso32/gettimeofday.S
+++ b/arch/powerpc/kernel/vdso32/gettimeofday.S
@@ -13,7 +13,7 @@
 #include <asm/unistd.h>
 
 /* Offset for the low 32-bit part of a field of long type */
-#ifdef CONFIG_PPC64
+#if defined(CONFIG_PPC64) && defined(CONFIG_CPU_BIG_ENDIAN)
 #define LOPART	4
 #define TSPEC_TV_SEC	TSPC64_TV_SEC+LOPART
 #else
-- 
2.20.0


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 4/8] ipmi: kill off 'timespec' usage again
  2019-11-08 20:34 [PATCH 0/8] y2038: bug fixes from y2038 work Arnd Bergmann
                   ` (2 preceding siblings ...)
  2019-11-08 20:34 ` [PATCH 3/8] powerpc: fix vdso32 for ppc64le Arnd Bergmann
@ 2019-11-08 20:34 ` Arnd Bergmann
  2019-11-08 22:11   ` Corey Minyard
  2019-11-08 20:34 ` [PATCH 5/8] netfilter: xt_time: use time64_t Arnd Bergmann
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 18+ messages in thread
From: Arnd Bergmann @ 2019-11-08 20:34 UTC (permalink / raw)
  To: y2038, Corey Minyard, Arnd Bergmann, Greg Kroah-Hartman
  Cc: linux-kernel, Corey Minyard, openipmi-developer

'struct timespec' is getting removed from the kernel. The usage in ipmi
was fixed before in commit 48862ea2ce86 ("ipmi: Update timespec usage
to timespec64"), but unfortunately it crept back in.

The busy looping code can better use ktime_t anyway, so use that
there to simplify the implementation.

Fixes: cbb19cb1eef0 ("ipmi_si: Convert timespec64 to timespec")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 drivers/char/ipmi/ipmi_si_intf.c | 40 +++++++++++---------------------
 1 file changed, 13 insertions(+), 27 deletions(-)

diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 6b9a0593d2eb..c7cc8538b84a 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -265,10 +265,10 @@ static void cleanup_ipmi_si(void);
 #ifdef DEBUG_TIMING
 void debug_timestamp(char *msg)
 {
-	struct timespec t;
+	struct timespec64 t;
 
-	ktime_get_ts(&t);
-	pr_debug("**%s: %ld.%9.9ld\n", msg, (long) t.tv_sec, t.tv_nsec);
+	ktime_get_ts64(&t);
+	pr_debug("**%s: %lld.%9.9ld\n", msg, t.tv_sec, t.tv_nsec);
 }
 #else
 #define debug_timestamp(x)
@@ -935,38 +935,25 @@ static void set_run_to_completion(void *send_info, bool i_run_to_completion)
 }
 
 /*
- * Use -1 in the nsec value of the busy waiting timespec to tell that
- * we are spinning in kipmid looking for something and not delaying
- * between checks
+ * Use -1 as a special constant to tell that we are spinning in kipmid
+ * looking for something and not delaying between checks
  */
-static inline void ipmi_si_set_not_busy(struct timespec *ts)
-{
-	ts->tv_nsec = -1;
-}
-static inline int ipmi_si_is_busy(struct timespec *ts)
-{
-	return ts->tv_nsec != -1;
-}
-
+#define IPMI_TIME_NOT_BUSY ns_to_ktime(-1ull)
 static inline bool ipmi_thread_busy_wait(enum si_sm_result smi_result,
 					 const struct smi_info *smi_info,
-					 struct timespec *busy_until)
+					 ktime_t *busy_until)
 {
 	unsigned int max_busy_us = 0;
 
 	if (smi_info->si_num < num_max_busy_us)
 		max_busy_us = kipmid_max_busy_us[smi_info->si_num];
 	if (max_busy_us == 0 || smi_result != SI_SM_CALL_WITH_DELAY)
-		ipmi_si_set_not_busy(busy_until);
-	else if (!ipmi_si_is_busy(busy_until)) {
-		ktime_get_ts(busy_until);
-		timespec_add_ns(busy_until, max_busy_us * NSEC_PER_USEC);
+		*busy_until = IPMI_TIME_NOT_BUSY;
+	else if (*busy_until == IPMI_TIME_NOT_BUSY) {
+		*busy_until = ktime_get() + max_busy_us * NSEC_PER_USEC;
 	} else {
-		struct timespec now;
-
-		ktime_get_ts(&now);
-		if (unlikely(timespec_compare(&now, busy_until) > 0)) {
-			ipmi_si_set_not_busy(busy_until);
+		if (unlikely(ktime_get() > *busy_until)) {
+			*busy_until = IPMI_TIME_NOT_BUSY;
 			return false;
 		}
 	}
@@ -988,9 +975,8 @@ static int ipmi_thread(void *data)
 	struct smi_info *smi_info = data;
 	unsigned long flags;
 	enum si_sm_result smi_result;
-	struct timespec busy_until = { 0, 0 };
+	ktime_t busy_until = IPMI_TIME_NOT_BUSY;
 
-	ipmi_si_set_not_busy(&busy_until);
 	set_user_nice(current, MAX_NICE);
 	while (!kthread_should_stop()) {
 		int busy_wait;
-- 
2.20.0


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 5/8] netfilter: xt_time: use time64_t
  2019-11-08 20:34 [PATCH 0/8] y2038: bug fixes from y2038 work Arnd Bergmann
                   ` (3 preceding siblings ...)
  2019-11-08 20:34 ` [PATCH 4/8] ipmi: kill off 'timespec' usage again Arnd Bergmann
@ 2019-11-08 20:34 ` Arnd Bergmann
  2019-11-15 22:43   ` Pablo Neira Ayuso
  2019-11-08 20:34 ` [PATCH 6/8] lp: fix sparc64 LPSETTIMEOUT ioctl Arnd Bergmann
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 18+ messages in thread
From: Arnd Bergmann @ 2019-11-08 20:34 UTC (permalink / raw)
  To: y2038, Pablo Neira Ayuso, Jozsef Kadlecsik, Florian Westphal,
	David S. Miller
  Cc: linux-kernel, Arnd Bergmann, Eric Dumazet, netfilter-devel,
	coreteam, netdev

The current xt_time driver suffers from the y2038 overflow on 32-bit
architectures, when the time of day calculations break.

Also, on both 32-bit and 64-bit architectures, there is a problem with
info->date_start/stop, which is part of the user ABI and overflows in
in 2106.

Fix the first issue by using time64_t and explicit calls to div_u64()
and div_u64_rem(), and document the seconds issue.

The explicit 64-bit division is unfortunately slower on 32-bit
architectures, but doing it as unsigned lets us use the optimized
division-through-multiplication path in most configurations.  This should
be fine, as the code already does not allow any negative time of day
values.

Using u32 seconds values consistently would probably also work and
be a little more efficient, but that doesn't feel right as it would
propagate the y2106 overflow to more place rather than fewer.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 net/netfilter/xt_time.c | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/net/netfilter/xt_time.c b/net/netfilter/xt_time.c
index 8dbb4d48f2ed..67cb98489415 100644
--- a/net/netfilter/xt_time.c
+++ b/net/netfilter/xt_time.c
@@ -77,12 +77,12 @@ static inline bool is_leap(unsigned int y)
  * This is done in three separate functions so that the most expensive
  * calculations are done last, in case a "simple match" can be found earlier.
  */
-static inline unsigned int localtime_1(struct xtm *r, time_t time)
+static inline unsigned int localtime_1(struct xtm *r, time64_t time)
 {
 	unsigned int v, w;
 
 	/* Each day has 86400s, so finding the hour/minute is actually easy. */
-	v         = time % SECONDS_PER_DAY;
+	div_u64_rem(time, SECONDS_PER_DAY, &v);
 	r->second = v % 60;
 	w         = v / 60;
 	r->minute = w % 60;
@@ -90,13 +90,13 @@ static inline unsigned int localtime_1(struct xtm *r, time_t time)
 	return v;
 }
 
-static inline void localtime_2(struct xtm *r, time_t time)
+static inline void localtime_2(struct xtm *r, time64_t time)
 {
 	/*
 	 * Here comes the rest (weekday, monthday). First, divide the SSTE
 	 * by seconds-per-day to get the number of _days_ since the epoch.
 	 */
-	r->dse = time / 86400;
+	r->dse = div_u64(time, SECONDS_PER_DAY);
 
 	/*
 	 * 1970-01-01 (w=0) was a Thursday (4).
@@ -105,7 +105,7 @@ static inline void localtime_2(struct xtm *r, time_t time)
 	r->weekday = (4 + r->dse - 1) % 7 + 1;
 }
 
-static void localtime_3(struct xtm *r, time_t time)
+static void localtime_3(struct xtm *r, time64_t time)
 {
 	unsigned int year, i, w = r->dse;
 
@@ -160,7 +160,7 @@ time_mt(const struct sk_buff *skb, struct xt_action_param *par)
 	const struct xt_time_info *info = par->matchinfo;
 	unsigned int packet_time;
 	struct xtm current_time;
-	s64 stamp;
+	time64_t stamp;
 
 	/*
 	 * We need real time here, but we can neither use skb->tstamp
@@ -173,14 +173,14 @@ time_mt(const struct sk_buff *skb, struct xt_action_param *par)
 	 *	1. match before 13:00
 	 *	2. match after 13:00
 	 *
-	 * If you match against processing time (get_seconds) it
+	 * If you match against processing time (ktime_get_real_seconds) it
 	 * may happen that the same packet matches both rules if
 	 * it arrived at the right moment before 13:00, so it would be
 	 * better to check skb->tstamp and set it via __net_timestamp()
 	 * if needed.  This however breaks outgoing packets tx timestamp,
 	 * and causes them to get delayed forever by fq packet scheduler.
 	 */
-	stamp = get_seconds();
+	stamp = ktime_get_real_seconds();
 
 	if (info->flags & XT_TIME_LOCAL_TZ)
 		/* Adjust for local timezone */
@@ -193,6 +193,9 @@ time_mt(const struct sk_buff *skb, struct xt_action_param *par)
 	 *   - 'now' is in the weekday mask
 	 *   - 'now' is in the daytime range time_start..time_end
 	 * (and by default, libxt_time will set these so as to match)
+	 *
+	 * note: info->date_start/stop are unsigned 32-bit values that
+	 *	 can hold values beyond y2038, but not after y2106.
 	 */
 
 	if (stamp < info->date_start || stamp > info->date_stop)
-- 
2.20.0


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 6/8] lp: fix sparc64 LPSETTIMEOUT ioctl
  2019-11-08 20:34 [PATCH 0/8] y2038: bug fixes from y2038 work Arnd Bergmann
                   ` (4 preceding siblings ...)
  2019-11-08 20:34 ` [PATCH 5/8] netfilter: xt_time: use time64_t Arnd Bergmann
@ 2019-11-08 20:34 ` Arnd Bergmann
  2019-11-08 20:34 ` [PATCH 7/8] ppdev: fix PPGETTIME/PPSETTIME ioctls Arnd Bergmann
  2019-11-08 20:34 ` [PATCH 8/8] Input: input_event: fix struct padding on sparc64 Arnd Bergmann
  7 siblings, 0 replies; 18+ messages in thread
From: Arnd Bergmann @ 2019-11-08 20:34 UTC (permalink / raw)
  To: y2038, Greg Kroah-Hartman
  Cc: linux-kernel, Arnd Bergmann, stable, Bamvor Jian Zhang,
	Sudip Mukherjee, Gustavo A. R. Silva, Thomas Gleixner

The layout of struct timeval is different on sparc64 from
anything else, and the patch I did long ago failed to take
this into account.

Change it now to handle sparc64 user space correctly again.

Quite likely nobody cares about parallel ports on sparc64,
but there is no reason not to fix it.

Cc: stable@vger.kernel.org
Fixes: 9a450484089d ("lp: support 64-bit time_t user space")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 drivers/char/lp.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 7c9269e3477a..bd95aba1f9fe 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -713,6 +713,10 @@ static int lp_set_timeout64(unsigned int minor, void __user *arg)
 	if (copy_from_user(karg, arg, sizeof(karg)))
 		return -EFAULT;
 
+	/* sparc64 suseconds_t is 32-bit only */
+	if (IS_ENABLED(CONFIG_SPARC64) && !in_compat_syscall())
+		karg[1] >>= 32;
+
 	return lp_set_timeout(minor, karg[0], karg[1]);
 }
 
-- 
2.20.0


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 7/8] ppdev: fix PPGETTIME/PPSETTIME ioctls
  2019-11-08 20:34 [PATCH 0/8] y2038: bug fixes from y2038 work Arnd Bergmann
                   ` (5 preceding siblings ...)
  2019-11-08 20:34 ` [PATCH 6/8] lp: fix sparc64 LPSETTIMEOUT ioctl Arnd Bergmann
@ 2019-11-08 20:34 ` Arnd Bergmann
  2019-11-08 20:34 ` [PATCH 8/8] Input: input_event: fix struct padding on sparc64 Arnd Bergmann
  7 siblings, 0 replies; 18+ messages in thread
From: Arnd Bergmann @ 2019-11-08 20:34 UTC (permalink / raw)
  To: y2038, Sudip Mukherjee, Greg Kroah-Hartman
  Cc: linux-kernel, Arnd Bergmann, stable, Bamvor Jian Zhang,
	Michael S. Tsirkin, Thomas Gleixner

Going through the uses of timeval in the user space API,
I noticed two bugs in ppdev that were introduced in the y2038
conversion:

* The range check was accidentally moved from ppsettime to
  ppgettime

* On sparc64, the microseconds are in the other half of the
  64-bit word.

Fix both, and mark the fix for stable backports.

Cc: stable@vger.kernel.org
Fixes: 3b9ab374a1e6 ("ppdev: convert to y2038 safe")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 drivers/char/ppdev.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index c86f18aa8985..34bb88fe0b0a 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -619,20 +619,27 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		if (copy_from_user(time32, argp, sizeof(time32)))
 			return -EFAULT;
 
+		if ((time32[0] < 0) || (time32[1] < 0))
+			return -EINVAL;
+
 		return pp_set_timeout(pp->pdev, time32[0], time32[1]);
 
 	case PPSETTIME64:
 		if (copy_from_user(time64, argp, sizeof(time64)))
 			return -EFAULT;
 
+		if ((time64[0] < 0) || (time64[1] < 0))
+			return -EINVAL;
+
+		if (IS_ENABLED(CONFIG_SPARC64) && !in_compat_syscall())
+			time64[1] >>= 32;
+
 		return pp_set_timeout(pp->pdev, time64[0], time64[1]);
 
 	case PPGETTIME32:
 		jiffies_to_timespec64(pp->pdev->timeout, &ts);
 		time32[0] = ts.tv_sec;
 		time32[1] = ts.tv_nsec / NSEC_PER_USEC;
-		if ((time32[0] < 0) || (time32[1] < 0))
-			return -EINVAL;
 
 		if (copy_to_user(argp, time32, sizeof(time32)))
 			return -EFAULT;
@@ -643,8 +650,9 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		jiffies_to_timespec64(pp->pdev->timeout, &ts);
 		time64[0] = ts.tv_sec;
 		time64[1] = ts.tv_nsec / NSEC_PER_USEC;
-		if ((time64[0] < 0) || (time64[1] < 0))
-			return -EINVAL;
+
+		if (IS_ENABLED(CONFIG_SPARC64) && !in_compat_syscall())
+			time64[1] <<= 32;
 
 		if (copy_to_user(argp, time64, sizeof(time64)))
 			return -EFAULT;
-- 
2.20.0


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 8/8] Input: input_event: fix struct padding on sparc64
  2019-11-08 20:34 [PATCH 0/8] y2038: bug fixes from y2038 work Arnd Bergmann
                   ` (6 preceding siblings ...)
  2019-11-08 20:34 ` [PATCH 7/8] ppdev: fix PPGETTIME/PPSETTIME ioctls Arnd Bergmann
@ 2019-11-08 20:34 ` Arnd Bergmann
  2019-11-11 18:28   ` Dmitry Torokhov
  7 siblings, 1 reply; 18+ messages in thread
From: Arnd Bergmann @ 2019-11-08 20:34 UTC (permalink / raw)
  To: y2038, Dmitry Torokhov
  Cc: linux-kernel, Arnd Bergmann, sparclinux, David S. Miller, stable,
	Deepa Dinamani, Thomas Gleixner, linux-input

Going through all uses of timeval, I noticed that we screwed up
input_event in the previous attempts to fix it:

The time fields now match between kernel and user space, but
all following fields are in the wrong place.

Add the required padding that is implied by the glibc timeval
definition to fix the layout, and add explicit initialization
to avoid leaking kernel stack data.

Cc: sparclinux@vger.kernel.org
Cc: "David S. Miller" <davem@davemloft.net>
Cc: stable@vger.kernel.org
Fixes: 141e5dcaa735 ("Input: input_event - fix the CONFIG_SPARC64 mixup")
Fixes: 2e746942ebac ("Input: input_event - provide override for sparc64")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 drivers/input/evdev.c       | 3 +++
 drivers/input/misc/uinput.c | 3 +++
 include/uapi/linux/input.h  | 1 +
 3 files changed, 7 insertions(+)

diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index d7dd6fcf2db0..24a90793caf0 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -228,6 +228,9 @@ static void __pass_event(struct evdev_client *client,
 						event->input_event_sec;
 		client->buffer[client->tail].input_event_usec =
 						event->input_event_usec;
+#ifdef CONFIG_SPARC64
+		client->buffer[client->tail].__pad = 0;
+#endif
 		client->buffer[client->tail].type = EV_SYN;
 		client->buffer[client->tail].code = SYN_DROPPED;
 		client->buffer[client->tail].value = 0;
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 84051f20b18a..1d8c09e9fd47 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -80,6 +80,9 @@ static int uinput_dev_event(struct input_dev *dev,
 	ktime_get_ts64(&ts);
 	udev->buff[udev->head].input_event_sec = ts.tv_sec;
 	udev->buff[udev->head].input_event_usec = ts.tv_nsec / NSEC_PER_USEC;
+#ifdef CONFIG_SPARC64
+	udev->buff[udev->head].__pad = 0;
+#endif
 	udev->head = (udev->head + 1) % UINPUT_BUFFER_SIZE;
 
 	wake_up_interruptible(&udev->waitq);
diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
index f056b2a00d5c..9a61c28ed3ae 100644
--- a/include/uapi/linux/input.h
+++ b/include/uapi/linux/input.h
@@ -34,6 +34,7 @@ struct input_event {
 	__kernel_ulong_t __sec;
 #if defined(__sparc__) && defined(__arch64__)
 	unsigned int __usec;
+	unsigned int __pad;
 #else
 	__kernel_ulong_t __usec;
 #endif
-- 
2.20.0


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 4/8] ipmi: kill off 'timespec' usage again
  2019-11-08 20:34 ` [PATCH 4/8] ipmi: kill off 'timespec' usage again Arnd Bergmann
@ 2019-11-08 22:11   ` Corey Minyard
  2019-11-09 11:23     ` Arnd Bergmann
  0 siblings, 1 reply; 18+ messages in thread
From: Corey Minyard @ 2019-11-08 22:11 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: y2038, Corey Minyard, Greg Kroah-Hartman, linux-kernel,
	openipmi-developer

On Fri, Nov 08, 2019 at 09:34:27PM +0100, Arnd Bergmann wrote:
> 'struct timespec' is getting removed from the kernel. The usage in ipmi
> was fixed before in commit 48862ea2ce86 ("ipmi: Update timespec usage
> to timespec64"), but unfortunately it crept back in.
> 
> The busy looping code can better use ktime_t anyway, so use that
> there to simplify the implementation.

Thanks, this is a big improvement.  I have this queued, but if you
are going to submit this, I can remove it, and:

Reviewed-by: Corey Minyard <cminyard@mvista.com>

Do you think this should go in to 5.4?

-corey

> 
> Fixes: cbb19cb1eef0 ("ipmi_si: Convert timespec64 to timespec")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
>  drivers/char/ipmi/ipmi_si_intf.c | 40 +++++++++++---------------------
>  1 file changed, 13 insertions(+), 27 deletions(-)
> 
> diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
> index 6b9a0593d2eb..c7cc8538b84a 100644
> --- a/drivers/char/ipmi/ipmi_si_intf.c
> +++ b/drivers/char/ipmi/ipmi_si_intf.c
> @@ -265,10 +265,10 @@ static void cleanup_ipmi_si(void);
>  #ifdef DEBUG_TIMING
>  void debug_timestamp(char *msg)
>  {
> -	struct timespec t;
> +	struct timespec64 t;
>  
> -	ktime_get_ts(&t);
> -	pr_debug("**%s: %ld.%9.9ld\n", msg, (long) t.tv_sec, t.tv_nsec);
> +	ktime_get_ts64(&t);
> +	pr_debug("**%s: %lld.%9.9ld\n", msg, t.tv_sec, t.tv_nsec);
>  }
>  #else
>  #define debug_timestamp(x)
> @@ -935,38 +935,25 @@ static void set_run_to_completion(void *send_info, bool i_run_to_completion)
>  }
>  
>  /*
> - * Use -1 in the nsec value of the busy waiting timespec to tell that
> - * we are spinning in kipmid looking for something and not delaying
> - * between checks
> + * Use -1 as a special constant to tell that we are spinning in kipmid
> + * looking for something and not delaying between checks
>   */
> -static inline void ipmi_si_set_not_busy(struct timespec *ts)
> -{
> -	ts->tv_nsec = -1;
> -}
> -static inline int ipmi_si_is_busy(struct timespec *ts)
> -{
> -	return ts->tv_nsec != -1;
> -}
> -
> +#define IPMI_TIME_NOT_BUSY ns_to_ktime(-1ull)
>  static inline bool ipmi_thread_busy_wait(enum si_sm_result smi_result,
>  					 const struct smi_info *smi_info,
> -					 struct timespec *busy_until)
> +					 ktime_t *busy_until)
>  {
>  	unsigned int max_busy_us = 0;
>  
>  	if (smi_info->si_num < num_max_busy_us)
>  		max_busy_us = kipmid_max_busy_us[smi_info->si_num];
>  	if (max_busy_us == 0 || smi_result != SI_SM_CALL_WITH_DELAY)
> -		ipmi_si_set_not_busy(busy_until);
> -	else if (!ipmi_si_is_busy(busy_until)) {
> -		ktime_get_ts(busy_until);
> -		timespec_add_ns(busy_until, max_busy_us * NSEC_PER_USEC);
> +		*busy_until = IPMI_TIME_NOT_BUSY;
> +	else if (*busy_until == IPMI_TIME_NOT_BUSY) {
> +		*busy_until = ktime_get() + max_busy_us * NSEC_PER_USEC;
>  	} else {
> -		struct timespec now;
> -
> -		ktime_get_ts(&now);
> -		if (unlikely(timespec_compare(&now, busy_until) > 0)) {
> -			ipmi_si_set_not_busy(busy_until);
> +		if (unlikely(ktime_get() > *busy_until)) {
> +			*busy_until = IPMI_TIME_NOT_BUSY;
>  			return false;
>  		}
>  	}
> @@ -988,9 +975,8 @@ static int ipmi_thread(void *data)
>  	struct smi_info *smi_info = data;
>  	unsigned long flags;
>  	enum si_sm_result smi_result;
> -	struct timespec busy_until = { 0, 0 };
> +	ktime_t busy_until = IPMI_TIME_NOT_BUSY;
>  
> -	ipmi_si_set_not_busy(&busy_until);
>  	set_user_nice(current, MAX_NICE);
>  	while (!kthread_should_stop()) {
>  		int busy_wait;
> -- 
> 2.20.0
> 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 4/8] ipmi: kill off 'timespec' usage again
  2019-11-08 22:11   ` Corey Minyard
@ 2019-11-09 11:23     ` Arnd Bergmann
  0 siblings, 0 replies; 18+ messages in thread
From: Arnd Bergmann @ 2019-11-09 11:23 UTC (permalink / raw)
  To: cminyard
  Cc: y2038 Mailman List, Corey Minyard, Greg Kroah-Hartman,
	linux-kernel, openipmi-developer

On Fri, Nov 8, 2019 at 11:11 PM Corey Minyard <cminyard@mvista.com> wrote:
>
> On Fri, Nov 08, 2019 at 09:34:27PM +0100, Arnd Bergmann wrote:
> > 'struct timespec' is getting removed from the kernel. The usage in ipmi
> > was fixed before in commit 48862ea2ce86 ("ipmi: Update timespec usage
> > to timespec64"), but unfortunately it crept back in.
> >
> > The busy looping code can better use ktime_t anyway, so use that
> > there to simplify the implementation.
>
> Thanks, this is a big improvement.  I have this queued, but if you
> are going to submit this, I can remove it, and:
>
> Reviewed-by: Corey Minyard <cminyard@mvista.com>

I'd prefer to have this go through your tree, one less thing for me
to worry about (out of the 90 patches).

> Do you think this should go in to 5.4?

Up to you, it probably depends on how well you can test that the change
is correct beyond the review.

       Arnd

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 1/8] y2038: timex: remove incorrect time_t truncation
  2019-11-08 20:34 ` [PATCH 1/8] y2038: timex: remove incorrect time_t truncation Arnd Bergmann
@ 2019-11-10 20:44   ` Deepa Dinamani
  2019-11-12  7:16   ` [tip: timers/urgent] ntp/y2038: Remove " tip-bot2 for Arnd Bergmann
  1 sibling, 0 replies; 18+ messages in thread
From: Deepa Dinamani @ 2019-11-10 20:44 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: y2038 Mailman List, John Stultz, Thomas Gleixner,
	Linux Kernel Mailing List, # 3.4.x, alpha,
	Linux Network Devel Mailing List, Stephen Boyd

Thanks for fixing the bug.

Acked-by: Deepa Dinamani <deepa.kernel@gmail.com>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 2/8] timekeeping: optimize ns_to_timespec64
  2019-11-08 20:34 ` [PATCH 2/8] timekeeping: optimize ns_to_timespec64 Arnd Bergmann
@ 2019-11-10 20:46   ` Deepa Dinamani
  2019-11-12  7:22   ` [tip: timers/core] time: Optimize ns_to_timespec64() tip-bot2 for Arnd Bergmann
  1 sibling, 0 replies; 18+ messages in thread
From: Deepa Dinamani @ 2019-11-10 20:46 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: y2038 Mailman List, John Stultz, Thomas Gleixner,
	Linux Kernel Mailing List, Stephen Boyd

The arithmetic looks right to me.

Acked-by: Deepa Dinamani <deepa.kernel@gmail.com>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 8/8] Input: input_event: fix struct padding on sparc64
  2019-11-08 20:34 ` [PATCH 8/8] Input: input_event: fix struct padding on sparc64 Arnd Bergmann
@ 2019-11-11 18:28   ` Dmitry Torokhov
  2019-11-11 19:18     ` Arnd Bergmann
  0 siblings, 1 reply; 18+ messages in thread
From: Dmitry Torokhov @ 2019-11-11 18:28 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: y2038, linux-kernel, sparclinux, David S. Miller, stable,
	Deepa Dinamani, Thomas Gleixner, linux-input

Hi Arnd,

On Fri, Nov 08, 2019 at 09:34:31PM +0100, Arnd Bergmann wrote:
> Going through all uses of timeval, I noticed that we screwed up
> input_event in the previous attempts to fix it:
> 
> The time fields now match between kernel and user space, but
> all following fields are in the wrong place.
> 
> Add the required padding that is implied by the glibc timeval
> definition to fix the layout, and add explicit initialization
> to avoid leaking kernel stack data.
> 
> Cc: sparclinux@vger.kernel.org
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: stable@vger.kernel.org
> Fixes: 141e5dcaa735 ("Input: input_event - fix the CONFIG_SPARC64 mixup")
> Fixes: 2e746942ebac ("Input: input_event - provide override for sparc64")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
>  drivers/input/evdev.c       | 3 +++
>  drivers/input/misc/uinput.c | 3 +++
>  include/uapi/linux/input.h  | 1 +
>  3 files changed, 7 insertions(+)
> 
> diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
> index d7dd6fcf2db0..24a90793caf0 100644
> --- a/drivers/input/evdev.c
> +++ b/drivers/input/evdev.c
> @@ -228,6 +228,9 @@ static void __pass_event(struct evdev_client *client,
>  						event->input_event_sec;
>  		client->buffer[client->tail].input_event_usec =
>  						event->input_event_usec;
> +#ifdef CONFIG_SPARC64
> +		client->buffer[client->tail].__pad = 0;
> +#endif
>  		client->buffer[client->tail].type = EV_SYN;
>  		client->buffer[client->tail].code = SYN_DROPPED;
>  		client->buffer[client->tail].value = 0;

I do not like ifdefs here, do you think we could write:

		client->buffer[client->tail] = (struct input_event) {
			.input_event_sec = event->input_event_sec,
			.input_event_usec = event->input_event_usec,
			.type = EV_SYN,
			.code = SYN_DROPPED,
		};

to ensure all padded fields are initialized? This is not hot path as we
do not expect queue to overfill too often.

Thanks.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 8/8] Input: input_event: fix struct padding on sparc64
  2019-11-11 18:28   ` Dmitry Torokhov
@ 2019-11-11 19:18     ` Arnd Bergmann
  0 siblings, 0 replies; 18+ messages in thread
From: Arnd Bergmann @ 2019-11-11 19:18 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: y2038 Mailman List, linux-kernel, sparclinux, David S. Miller,
	# 3.4.x, Deepa Dinamani, Thomas Gleixner,
	open list:HID CORE LAYER

On Mon, Nov 11, 2019 at 7:28 PM Dmitry Torokhov
<dmitry.torokhov@gmail.com> wrote:

> I do not like ifdefs here, do you think we could write:
>
>                 client->buffer[client->tail] = (struct input_event) {
>                         .input_event_sec = event->input_event_sec,
>                         .input_event_usec = event->input_event_usec,
>                         .type = EV_SYN,
>                         .code = SYN_DROPPED,
>                 };
>
> to ensure all padded fields are initialized? This is not hot path as we
> do not expect queue to overfill too often.

Good idea, changed both instances now. Thanks for taking a look!

      Arnd

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [tip: timers/urgent] ntp/y2038: Remove incorrect time_t truncation
  2019-11-08 20:34 ` [PATCH 1/8] y2038: timex: remove incorrect time_t truncation Arnd Bergmann
  2019-11-10 20:44   ` Deepa Dinamani
@ 2019-11-12  7:16   ` " tip-bot2 for Arnd Bergmann
  1 sibling, 0 replies; 18+ messages in thread
From: tip-bot2 for Arnd Bergmann @ 2019-11-12  7:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Arnd Bergmann, Thomas Gleixner, stable, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/urgent branch of tip:

Commit-ID:     2f5841349df281ecf8f81cc82d869b8476f0db0b
Gitweb:        https://git.kernel.org/tip/2f5841349df281ecf8f81cc82d869b8476f0db0b
Author:        Arnd Bergmann <arnd@arndb.de>
AuthorDate:    Fri, 08 Nov 2019 21:34:24 +01:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Tue, 12 Nov 2019 08:13:44 +01:00

ntp/y2038: Remove incorrect time_t truncation

A cast to 'time_t' was accidentally left in place during the
conversion of __do_adjtimex() to 64-bit timestamps, so the
resulting value is incorrectly truncated.

Remove the cast so the 64-bit time gets propagated correctly.

Fixes: ead25417f82e ("timex: use __kernel_timex internally")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: stable@vger.kernel.org
Link: https://lkml.kernel.org/r/20191108203435.112759-2-arnd@arndb.de

---
 kernel/time/ntp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index 65eb796..069ca78 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -771,7 +771,7 @@ int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts,
 	/* fill PPS status fields */
 	pps_fill_timex(txc);
 
-	txc->time.tv_sec = (time_t)ts->tv_sec;
+	txc->time.tv_sec = ts->tv_sec;
 	txc->time.tv_usec = ts->tv_nsec;
 	if (!(time_status & STA_NANO))
 		txc->time.tv_usec = ts->tv_nsec / NSEC_PER_USEC;

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [tip: timers/core] time: Optimize ns_to_timespec64()
  2019-11-08 20:34 ` [PATCH 2/8] timekeeping: optimize ns_to_timespec64 Arnd Bergmann
  2019-11-10 20:46   ` Deepa Dinamani
@ 2019-11-12  7:22   ` tip-bot2 for Arnd Bergmann
  1 sibling, 0 replies; 18+ messages in thread
From: tip-bot2 for Arnd Bergmann @ 2019-11-12  7:22 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Arnd Bergmann, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     20d087368d38c7350a4519a3b316ef7eb2504692
Gitweb:        https://git.kernel.org/tip/20d087368d38c7350a4519a3b316ef7eb2504692
Author:        Arnd Bergmann <arnd@arndb.de>
AuthorDate:    Fri, 08 Nov 2019 21:34:25 +01:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Tue, 12 Nov 2019 08:15:15 +01:00

time: Optimize ns_to_timespec64()

ns_to_timespec64() calls div_s64_rem(), which is a rather slow function on
32-bit architectures, as it cannot take advantage of the do_div()
optimizations for constant arguments.

Open-code the div_s64_rem() function in ns_to_timespec64(), so a constant
divider can be passed into the optimized div_u64_rem() function.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191108203435.112759-3-arnd@arndb.de
---
 kernel/time/time.c | 21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/kernel/time/time.c b/kernel/time/time.c
index 5c54ca6..45a3589 100644
--- a/kernel/time/time.c
+++ b/kernel/time/time.c
@@ -550,18 +550,21 @@ EXPORT_SYMBOL(set_normalized_timespec64);
  */
 struct timespec64 ns_to_timespec64(const s64 nsec)
 {
-	struct timespec64 ts;
+	struct timespec64 ts = { 0, 0 };
 	s32 rem;
 
-	if (!nsec)
-		return (struct timespec64) {0, 0};
-
-	ts.tv_sec = div_s64_rem(nsec, NSEC_PER_SEC, &rem);
-	if (unlikely(rem < 0)) {
-		ts.tv_sec--;
-		rem += NSEC_PER_SEC;
+	if (likely(nsec > 0)) {
+		ts.tv_sec = div_u64_rem(nsec, NSEC_PER_SEC, &rem);
+		ts.tv_nsec = rem;
+	} else if (nsec < 0) {
+		/*
+		 * With negative times, tv_sec points to the earlier
+		 * second, and tv_nsec counts the nanoseconds since
+		 * then, so tv_nsec is always a positive number.
+		 */
+		ts.tv_sec = -div_u64_rem(-nsec - 1, NSEC_PER_SEC, &rem) - 1;
+		ts.tv_nsec = NSEC_PER_SEC - rem - 1;
 	}
-	ts.tv_nsec = rem;
 
 	return ts;
 }

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 5/8] netfilter: xt_time: use time64_t
  2019-11-08 20:34 ` [PATCH 5/8] netfilter: xt_time: use time64_t Arnd Bergmann
@ 2019-11-15 22:43   ` Pablo Neira Ayuso
  0 siblings, 0 replies; 18+ messages in thread
From: Pablo Neira Ayuso @ 2019-11-15 22:43 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: y2038, Jozsef Kadlecsik, Florian Westphal, David S. Miller,
	linux-kernel, Eric Dumazet, netfilter-devel, coreteam, netdev

On Fri, Nov 08, 2019 at 09:34:28PM +0100, Arnd Bergmann wrote:
> The current xt_time driver suffers from the y2038 overflow on 32-bit
> architectures, when the time of day calculations break.
> 
> Also, on both 32-bit and 64-bit architectures, there is a problem with
> info->date_start/stop, which is part of the user ABI and overflows in
> in 2106.
> 
> Fix the first issue by using time64_t and explicit calls to div_u64()
> and div_u64_rem(), and document the seconds issue.
> 
> The explicit 64-bit division is unfortunately slower on 32-bit
> architectures, but doing it as unsigned lets us use the optimized
> division-through-multiplication path in most configurations.  This should
> be fine, as the code already does not allow any negative time of day
> values.
> 
> Using u32 seconds values consistently would probably also work and
> be a little more efficient, but that doesn't feel right as it would
> propagate the y2106 overflow to more place rather than fewer.

Applied, thanks.

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, back to index

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-08 20:34 [PATCH 0/8] y2038: bug fixes from y2038 work Arnd Bergmann
2019-11-08 20:34 ` [PATCH 1/8] y2038: timex: remove incorrect time_t truncation Arnd Bergmann
2019-11-10 20:44   ` Deepa Dinamani
2019-11-12  7:16   ` [tip: timers/urgent] ntp/y2038: Remove " tip-bot2 for Arnd Bergmann
2019-11-08 20:34 ` [PATCH 2/8] timekeeping: optimize ns_to_timespec64 Arnd Bergmann
2019-11-10 20:46   ` Deepa Dinamani
2019-11-12  7:22   ` [tip: timers/core] time: Optimize ns_to_timespec64() tip-bot2 for Arnd Bergmann
2019-11-08 20:34 ` [PATCH 3/8] powerpc: fix vdso32 for ppc64le Arnd Bergmann
2019-11-08 20:34 ` [PATCH 4/8] ipmi: kill off 'timespec' usage again Arnd Bergmann
2019-11-08 22:11   ` Corey Minyard
2019-11-09 11:23     ` Arnd Bergmann
2019-11-08 20:34 ` [PATCH 5/8] netfilter: xt_time: use time64_t Arnd Bergmann
2019-11-15 22:43   ` Pablo Neira Ayuso
2019-11-08 20:34 ` [PATCH 6/8] lp: fix sparc64 LPSETTIMEOUT ioctl Arnd Bergmann
2019-11-08 20:34 ` [PATCH 7/8] ppdev: fix PPGETTIME/PPSETTIME ioctls Arnd Bergmann
2019-11-08 20:34 ` [PATCH 8/8] Input: input_event: fix struct padding on sparc64 Arnd Bergmann
2019-11-11 18:28   ` Dmitry Torokhov
2019-11-11 19:18     ` Arnd Bergmann

LKML Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/lkml/0 lkml/git/0.git
	git clone --mirror https://lore.kernel.org/lkml/1 lkml/git/1.git
	git clone --mirror https://lore.kernel.org/lkml/2 lkml/git/2.git
	git clone --mirror https://lore.kernel.org/lkml/3 lkml/git/3.git
	git clone --mirror https://lore.kernel.org/lkml/4 lkml/git/4.git
	git clone --mirror https://lore.kernel.org/lkml/5 lkml/git/5.git
	git clone --mirror https://lore.kernel.org/lkml/6 lkml/git/6.git
	git clone --mirror https://lore.kernel.org/lkml/7 lkml/git/7.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 lkml lkml/ https://lore.kernel.org/lkml \
		linux-kernel@vger.kernel.org
	public-inbox-index lkml

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-kernel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git