| From 5a581b367b5df0531265311fc681c2abd377e5e6 Mon Sep 17 00:00:00 2001 |
| From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> |
| Date: Sat, 27 Jul 2013 03:53:54 -0700 |
| Subject: jiffies: Avoid undefined behavior from signed overflow |
| |
| From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> |
| |
| commit 5a581b367b5df0531265311fc681c2abd377e5e6 upstream. |
| |
| According to the C standard 3.4.3p3, overflow of a signed integer results |
| in undefined behavior. This commit therefore changes the definitions |
| of time_after(), time_after_eq(), time_after64(), and time_after_eq64() |
| to avoid this undefined behavior. The trick is that the subtraction |
| is done using unsigned arithmetic, which according to 6.2.5p9 cannot |
| overflow because it is defined as modulo arithmetic. This has the added |
| (though admittedly quite small) benefit of shortening four lines of code |
| by four characters each. |
| |
| Note that the C standard considers the cast from unsigned to |
| signed to be implementation-defined, see 6.3.1.3p3. However, on a |
| two's-complement system, an implementation that defines anything other |
| than a reinterpretation of the bits is free to come to me, and I will be |
| happy to act as a witness for its being committed to an insane asylum. |
| (Although I have nothing against saturating arithmetic or signals in some |
| cases, these things really should not be the default when compiling an |
| operating-system kernel.) |
| |
| Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> |
| Cc: John Stultz <john.stultz@linaro.org> |
| Cc: "David S. Miller" <davem@davemloft.net> |
| Cc: Arnd Bergmann <arnd@arndb.de> |
| Cc: Ingo Molnar <mingo@kernel.org> |
| Cc: Linus Torvalds <torvalds@linux-foundation.org> |
| Cc: Eric Dumazet <eric.dumazet@gmail.com> |
| Cc: Kevin Easton <kevin@guarana.org> |
| [ paulmck: Included time_after64() and time_after_eq64(), as suggested |
| by Eric Dumazet, also fixed commit message.] |
| Reviewed-by: Josh Triplett <josh@joshtriplett.org> |
| Ruchi Kandoi <kandoiruchi@google.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| include/linux/jiffies.h | 8 ++++---- |
| 1 file changed, 4 insertions(+), 4 deletions(-) |
| |
| --- a/include/linux/jiffies.h |
| +++ b/include/linux/jiffies.h |
| @@ -106,13 +106,13 @@ static inline u64 get_jiffies_64(void) |
| #define time_after(a,b) \ |
| (typecheck(unsigned long, a) && \ |
| typecheck(unsigned long, b) && \ |
| - ((long)(b) - (long)(a) < 0)) |
| + ((long)((b) - (a)) < 0)) |
| #define time_before(a,b) time_after(b,a) |
| |
| #define time_after_eq(a,b) \ |
| (typecheck(unsigned long, a) && \ |
| typecheck(unsigned long, b) && \ |
| - ((long)(a) - (long)(b) >= 0)) |
| + ((long)((a) - (b)) >= 0)) |
| #define time_before_eq(a,b) time_after_eq(b,a) |
| |
| /* |
| @@ -135,13 +135,13 @@ static inline u64 get_jiffies_64(void) |
| #define time_after64(a,b) \ |
| (typecheck(__u64, a) && \ |
| typecheck(__u64, b) && \ |
| - ((__s64)(b) - (__s64)(a) < 0)) |
| + ((__s64)((b) - (a)) < 0)) |
| #define time_before64(a,b) time_after64(b,a) |
| |
| #define time_after_eq64(a,b) \ |
| (typecheck(__u64, a) && \ |
| typecheck(__u64, b) && \ |
| - ((__s64)(a) - (__s64)(b) >= 0)) |
| + ((__s64)((a) - (b)) >= 0)) |
| #define time_before_eq64(a,b) time_after_eq64(b,a) |
| |
| /* |