Commit 5f4d5404ee8af904b8e843a7fc21f27ff8e6cb83
Committed by
Greg Kroah-Hartman
1 parent
cfaa6851b0
time: settimeofday: Validate the values of tv from user
commit 6ada1fc0e1c4775de0e043e1bd3ae9d065491aa5 upstream. An unvalidated user input is multiplied by a constant, which can result in an undefined behaviour for large values. While this is validated later, we should avoid triggering undefined behaviour. Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@kernel.org> Signed-off-by: Sasha Levin <sasha.levin@oracle.com> [jstultz: include trivial milisecond->microsecond correction noticed by Andy] Signed-off-by: John Stultz <john.stultz@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Showing 2 changed files with 17 additions and 0 deletions Side-by-side Diff
include/linux/time.h
... | ... | @@ -99,6 +99,19 @@ |
99 | 99 | return true; |
100 | 100 | } |
101 | 101 | |
102 | +static inline bool timeval_valid(const struct timeval *tv) | |
103 | +{ | |
104 | + /* Dates before 1970 are bogus */ | |
105 | + if (tv->tv_sec < 0) | |
106 | + return false; | |
107 | + | |
108 | + /* Can't have more microseconds then a second */ | |
109 | + if (tv->tv_usec < 0 || tv->tv_usec >= USEC_PER_SEC) | |
110 | + return false; | |
111 | + | |
112 | + return true; | |
113 | +} | |
114 | + | |
102 | 115 | extern struct timespec timespec_trunc(struct timespec t, unsigned gran); |
103 | 116 | |
104 | 117 | #define CURRENT_TIME (current_kernel_time()) |
kernel/time/time.c
... | ... | @@ -196,6 +196,10 @@ |
196 | 196 | if (tv) { |
197 | 197 | if (copy_from_user(&user_tv, tv, sizeof(*tv))) |
198 | 198 | return -EFAULT; |
199 | + | |
200 | + if (!timeval_valid(&user_tv)) | |
201 | + return -EINVAL; | |
202 | + | |
199 | 203 | new_ts.tv_sec = user_tv.tv_sec; |
200 | 204 | new_ts.tv_nsec = user_tv.tv_usec * NSEC_PER_USEC; |
201 | 205 | } |