Fix signed division error (rhbz 1200353)
This commit is contained in:
parent
822316b626
commit
6611dce123
|
@ -0,0 +1,125 @@
|
|||
From f7bcb70ebae0dcdb5a2d859b09e4465784d99029 Mon Sep 17 00:00:00 2001
|
||||
From: John Stultz <john.stultz@linaro.org>
|
||||
Date: Fri, 8 May 2015 13:47:23 -0700
|
||||
Subject: [PATCH] ktime: Fix ktime_divns to do signed division
|
||||
|
||||
It was noted that the 32bit implementation of ktime_divns()
|
||||
was doing unsigned division and didn't properly handle
|
||||
negative values.
|
||||
|
||||
And when a ktime helper was changed to utilize
|
||||
ktime_divns, it caused a regression on some IR blasters.
|
||||
See the following bugzilla for details:
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=1200353
|
||||
|
||||
This patch fixes the problem in ktime_divns by checking
|
||||
and preserving the sign bit, and then reapplying it if
|
||||
appropriate after the division, it also changes the return
|
||||
type to a s64 to make it more obvious this is expected.
|
||||
|
||||
Nicolas also pointed out that negative dividers would
|
||||
cause infinite loops on 32bit systems, negative dividers
|
||||
is unlikely for users of this function, but out of caution
|
||||
this patch adds checks for negative dividers for both
|
||||
32-bit (BUG_ON) and 64-bit(WARN_ON) versions to make sure
|
||||
no such use cases creep in.
|
||||
|
||||
[ tglx: Hand an u64 to do_div() to avoid the compiler warning ]
|
||||
|
||||
Fixes: 166afb64511e 'ktime: Sanitize ktime_to_us/ms conversion'
|
||||
Reported-and-tested-by: Trevor Cordes <trevor@tecnopolis.ca>
|
||||
Signed-off-by: John Stultz <john.stultz@linaro.org>
|
||||
Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org>
|
||||
Cc: Ingo Molnar <mingo@kernel.org>
|
||||
Cc: Josh Boyer <jwboyer@redhat.com>
|
||||
Cc: One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk>
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Link: http://lkml.kernel.org/r/1431118043-23452-1-git-send-email-john.stultz@linaro.org
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
---
|
||||
include/linux/ktime.h | 27 +++++++++++++++++++++------
|
||||
kernel/time/hrtimer.c | 14 ++++++++------
|
||||
2 files changed, 29 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/include/linux/ktime.h b/include/linux/ktime.h
|
||||
index 5fc3d10..2b6a204 100644
|
||||
--- a/include/linux/ktime.h
|
||||
+++ b/include/linux/ktime.h
|
||||
@@ -166,19 +166,34 @@ static inline bool ktime_before(const ktime_t cmp1, const ktime_t cmp2)
|
||||
}
|
||||
|
||||
#if BITS_PER_LONG < 64
|
||||
-extern u64 __ktime_divns(const ktime_t kt, s64 div);
|
||||
-static inline u64 ktime_divns(const ktime_t kt, s64 div)
|
||||
+extern s64 __ktime_divns(const ktime_t kt, s64 div);
|
||||
+static inline s64 ktime_divns(const ktime_t kt, s64 div)
|
||||
{
|
||||
+ /*
|
||||
+ * Negative divisors could cause an inf loop,
|
||||
+ * so bug out here.
|
||||
+ */
|
||||
+ BUG_ON(div < 0);
|
||||
if (__builtin_constant_p(div) && !(div >> 32)) {
|
||||
- u64 ns = kt.tv64;
|
||||
- do_div(ns, div);
|
||||
- return ns;
|
||||
+ s64 ns = kt.tv64;
|
||||
+ u64 tmp = ns < 0 ? -ns : ns;
|
||||
+
|
||||
+ do_div(tmp, div);
|
||||
+ return ns < 0 ? -tmp : tmp;
|
||||
} else {
|
||||
return __ktime_divns(kt, div);
|
||||
}
|
||||
}
|
||||
#else /* BITS_PER_LONG < 64 */
|
||||
-# define ktime_divns(kt, div) (u64)((kt).tv64 / (div))
|
||||
+static inline s64 ktime_divns(const ktime_t kt, s64 div)
|
||||
+{
|
||||
+ /*
|
||||
+ * 32-bit implementation cannot handle negative divisors,
|
||||
+ * so catch them on 64bit as well.
|
||||
+ */
|
||||
+ WARN_ON(div < 0);
|
||||
+ return kt.tv64 / div;
|
||||
+}
|
||||
#endif
|
||||
|
||||
static inline s64 ktime_to_us(const ktime_t kt)
|
||||
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
|
||||
index 76d4bd9..93ef7190 100644
|
||||
--- a/kernel/time/hrtimer.c
|
||||
+++ b/kernel/time/hrtimer.c
|
||||
@@ -266,21 +266,23 @@ lock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags)
|
||||
/*
|
||||
* Divide a ktime value by a nanosecond value
|
||||
*/
|
||||
-u64 __ktime_divns(const ktime_t kt, s64 div)
|
||||
+s64 __ktime_divns(const ktime_t kt, s64 div)
|
||||
{
|
||||
- u64 dclc;
|
||||
int sft = 0;
|
||||
+ s64 dclc;
|
||||
+ u64 tmp;
|
||||
|
||||
dclc = ktime_to_ns(kt);
|
||||
+ tmp = dclc < 0 ? -dclc : dclc;
|
||||
+
|
||||
/* Make sure the divisor is less than 2^32: */
|
||||
while (div >> 32) {
|
||||
sft++;
|
||||
div >>= 1;
|
||||
}
|
||||
- dclc >>= sft;
|
||||
- do_div(dclc, (unsigned long) div);
|
||||
-
|
||||
- return dclc;
|
||||
+ tmp >>= sft;
|
||||
+ do_div(tmp, (unsigned long) div);
|
||||
+ return dclc < 0 ? -tmp : tmp;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__ktime_divns);
|
||||
#endif /* BITS_PER_LONG >= 64 */
|
||||
--
|
||||
2.4.0
|
||||
|
|
@ -675,6 +675,9 @@ Patch26207: md-raid0-fix-restore-to-sector-variable-in-raid0_mak.patch
|
|||
#rhbz 1220519
|
||||
Patch26208: sched-always-use-blk_schedule_flush_plug-in-io_sched.patch
|
||||
|
||||
#rhbz 1200353
|
||||
Patch26209: 0001-ktime-Fix-ktime_divns-to-do-signed-division.patch
|
||||
|
||||
# END OF PATCH DEFINITIONS
|
||||
|
||||
%endif
|
||||
|
@ -1453,6 +1456,9 @@ ApplyPatch md-raid0-fix-restore-to-sector-variable-in-raid0_mak.patch
|
|||
#rhbz 1220519
|
||||
ApplyPatch sched-always-use-blk_schedule_flush_plug-in-io_sched.patch
|
||||
|
||||
#rhbz 1200353
|
||||
ApplyPatch 0001-ktime-Fix-ktime_divns-to-do-signed-division.patch
|
||||
|
||||
# END OF PATCH APPLICATIONS
|
||||
|
||||
%endif
|
||||
|
@ -2312,6 +2318,9 @@ fi
|
|||
# ||----w |
|
||||
# || ||
|
||||
%changelog
|
||||
* Tue May 26 2015 Laura Abbott <labbott@fedoraproject.org>
|
||||
- Fix signed division error (rhbz 1200353)
|
||||
|
||||
* Tue May 26 2015 Josh Boyer <jwboyer@fedoraproject.org>
|
||||
- Backport patch to fix might_sleep splat (rhbz 1220519)
|
||||
|
||||
|
|
Loading…
Reference in New Issue