From: AMEET M. PARANJAPE <aparanja@redhat.com> Date: Thu, 26 Mar 2009 17:20:43 -0400 Subject: [misc] hrtimer: check relative timeouts for overflow Message-id: 20090326211835.28676.70244.sendpatchset@squad5-lp1.lab.bos.redhat.com O-Subject: [PATCH RHEL5.4 BZ492230] hrtimer: check relative timeouts for overflow Bugzilla: 492230 RHBZ#: ====== https://bugzilla.redhat.com/show_bug.cgi?id=492230 Description: =========== This patch backport the mainline operations on itimers to avoid the sec -> nanosecs overflow when using 64-bit variables. Instead of putting overflow checks into each place add a function which does the sanity checking and convert all affected callers to use it. RHEL Version Found: ================ RHEL 5.3 kABI Status: ============ No symbols were harmed. Brew: ===== Built on all platforms. http://brewweb.devel.redhat.com/brew/taskinfo?taskID=1739525 Upstream Status: ================ http://lkml.org/lkml/2008/2/22/534 Test Status: ============ There is a test script in the Bugzilla. Without the patch the getitimer function fails if the timer ITIMER_REAL is used. With the patch applied the test script does not fail. ================================== ============================= Ameet Paranjape 978-392-3903 ext 23903 IBM on-site partner Proposed Patch: =============== diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 8479e6f..6088238 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -295,6 +295,24 @@ static unsigned long ktime_divns(const ktime_t kt, s64 div) #endif /* BITS_PER_LONG >= 64 */ /* + * Add two ktime values and do a safety check for overflow: + */ +ktime_t ktime_add_safe(const ktime_t lhs, const ktime_t rhs) +{ + ktime_t res = ktime_add(lhs, rhs); + + /* + * We use KTIME_SEC_MAX here, the maximum timeout which we can + * return to user space in a timespec: + */ + if (res.tv64 < 0 || res.tv64 < lhs.tv64 || res.tv64 < rhs.tv64) + res = ktime_set(KTIME_SEC_MAX, 0); + + return res; +} + + +/* * Counterpart to lock_timer_base above: */ static inline @@ -447,7 +465,7 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode) new_base = switch_hrtimer_base(timer, base); if (mode == HRTIMER_REL) { - tim = ktime_add(tim, new_base->get_time()); + tim = ktime_add_safe(tim, new_base->get_time()); /* * CONFIG_TIME_LOW_RES is a temporary way for architectures * to signal that they simply return xtime in @@ -456,7 +474,7 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode) * timeouts. This will go away with the GTOD framework. */ #ifdef CONFIG_TIME_LOW_RES - tim = ktime_add(tim, base->resolution); + tim = ktime_add_safe(tim, base->resolution); #endif } timer->expires = tim;