prevent timespec/timeval to ktime_t overflow
authorThomas Gleixner <tglx@linutronix.de>
Sun, 8 Apr 2007 22:03:30 +0000 (00:03 +0200)
committerAdrian Bunk <bunk@stusta.de>
Sun, 8 Apr 2007 22:03:30 +0000 (00:03 +0200)
Frank v.  Waveren pointed out that on 64bit machines the timespec to
ktime_t conversion might overflow.  This is also true for timeval to
time_t conversions.  This breaks a "sleep inf" on 64bit machines.

While a timespec/timeval with tx.sec = MAX_LONG is valid by specification
the internal representation of ktime_t is based on nanoseconds.  The
conversion of seconds to nanoseconds overflows for seconds values >=
(MAX_LONG / NSEC_PER_SEC).

Check the seconds argument to the conversion and limit it to the maximum
time which can be represented by ktime_t.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Adrian Bunk <bunk@stusta.de>
include/linux/ktime.h

index f3dec45ef874d2d40ff883380201eb8d1e540f42..f106701d7dbd87cab64662070e67f2fdf99be02f 100644 (file)
@@ -56,7 +56,8 @@ typedef union {
 #endif
 } ktime_t;
 
-#define KTIME_MAX                      (~((u64)1 << 63))
+#define KTIME_MAX                      ((s64)~((u64)1 << 63))
+#define KTIME_SEC_MAX                  (KTIME_MAX / NSEC_PER_SEC)
 
 /*
  * ktime_t definitions when using the 64-bit scalar representation:
@@ -77,6 +78,10 @@ typedef union {
  */
 static inline ktime_t ktime_set(const long secs, const unsigned long nsecs)
 {
+#if (BITS_PER_LONG == 64)
+       if (unlikely(secs >= KTIME_SEC_MAX))
+               return (ktime_t){ .tv64 = KTIME_MAX };
+#endif
        return (ktime_t) { .tv64 = (s64)secs * NSEC_PER_SEC + (s64)nsecs };
 }