lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Wed, 6 Mar 2019 21:13:25 +0800
From:   Hongbo Yao <yaohongbo@...wei.com>
To:     <tglx@...utronix.de>, <edumazet@...gle.com>,
        <linux-kernel@...r.kernel.org>, <yaohongbo@...wei.com>
Subject: [RFC PATCH 1/2] ktime: add ktime_sub_safe() to avoid undefined behaviour

This patch add a new ktime_sub_unsafe() helper which won't throw a
UBSAN warning when it does overflows, and then it add ktime_sub_safe()
which will check if the result of ktime_sub_unsafe overflows.This patch
modify the above functions to use ktime_sub_safe instead of ktime_sub();

Signed-off-by: Xiongfeng Wang <wangxiongfeng2@...wei.com>
Signed-off-by: Hongbo Yao <yaohongbo@...wei.com>
---
 include/linux/ktime.h |  8 ++++++++
 kernel/time/hrtimer.c | 16 ++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/include/linux/ktime.h b/include/linux/ktime.h
index b2bb44f87f5a..325e794b0dd1 100644
--- a/include/linux/ktime.h
+++ b/include/linux/ktime.h
@@ -45,6 +45,12 @@ static inline ktime_t ktime_set(const s64 secs, const unsigned long nsecs)
 /* Subtract two ktime_t variables. rem = lhs -rhs: */
 #define ktime_sub(lhs, rhs)	((lhs) - (rhs))
 
+/*
+ * Same as ktime_sub(), but avoids undefined behaviour on overflow; however,
+ * this means that you must check the result for overflow yourself.
+ */
+#define ktime_sub_unsafe(lhs, rhs)      ((u64) (lhs) - (rhs))
+
 /* Add two ktime_t variables. res = lhs + rhs: */
 #define ktime_add(lhs, rhs)	((lhs) + (rhs))
 
@@ -215,6 +221,8 @@ static inline ktime_t ktime_sub_ms(const ktime_t kt, const u64 msec)
 
 extern ktime_t ktime_add_safe(const ktime_t lhs, const ktime_t rhs);
 
+extern ktime_t ktime_sub_safe(const ktime_t lhs, const ktime_t rhs);
+
 /**
  * ktime_to_timespec_cond - convert a ktime_t variable to timespec
  *			    format only if the variable contains data
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index e1a549c9e399..cadc5bcbfc9e 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -317,6 +317,22 @@ s64 __ktime_divns(const ktime_t kt, s64 div)
 EXPORT_SYMBOL_GPL(__ktime_divns);
 #endif /* BITS_PER_LONG >= 64 */
 
+/*
+ * sub two ktime values and do a safety check for overflow:
+ */
+ktime_t ktime_sub_safe(const ktime_t lhs, const ktime_t rhs)
+{
+	ktime_t res = ktime_sub_unsafe(lhs, rhs);
+
+	if (lhs > 0 && rhs < 0 && res < 0)
+		res = ktime_set(KTIME_SEC_MAX, 0);
+	else if (lhs < 0 && rhs > 0 && res > 0)
+		res = ktime_set(-KTIME_SEC_MAX, 0);
+
+	return res;
+}
+EXPORT_SYMBOL_GPL(ktime_sub_safe);
+
 /*
  * Add two ktime values and do a safety check for overflow:
  */
-- 
2.20.1

Powered by blists - more mailing lists