diff options
Diffstat (limited to 'kernel/time/itimer.c')
-rw-r--r-- | kernel/time/itimer.c | 46 |
1 files changed, 44 insertions, 2 deletions
diff --git a/kernel/time/itimer.c b/kernel/time/itimer.c index 087d6a1279b8..2ef98a02376a 100644 --- a/kernel/time/itimer.c +++ b/kernel/time/itimer.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/posix-timers.h> | 15 | #include <linux/posix-timers.h> |
16 | #include <linux/hrtimer.h> | 16 | #include <linux/hrtimer.h> |
17 | #include <trace/events/timer.h> | 17 | #include <trace/events/timer.h> |
18 | #include <linux/compat.h> | ||
18 | 19 | ||
19 | #include <linux/uaccess.h> | 20 | #include <linux/uaccess.h> |
20 | 21 | ||
@@ -116,6 +117,19 @@ SYSCALL_DEFINE2(getitimer, int, which, struct itimerval __user *, value) | |||
116 | return error; | 117 | return error; |
117 | } | 118 | } |
118 | 119 | ||
120 | #ifdef CONFIG_COMPAT | ||
121 | COMPAT_SYSCALL_DEFINE2(getitimer, int, which, | ||
122 | struct compat_itimerval __user *, it) | ||
123 | { | ||
124 | struct itimerval kit; | ||
125 | int error = do_getitimer(which, &kit); | ||
126 | |||
127 | if (!error && put_compat_itimerval(it, &kit)) | ||
128 | error = -EFAULT; | ||
129 | return error; | ||
130 | } | ||
131 | #endif | ||
132 | |||
119 | 133 | ||
120 | /* | 134 | /* |
121 | * The timer is automagically restarted, when interval != 0 | 135 | * The timer is automagically restarted, when interval != 0 |
@@ -138,8 +152,12 @@ static void set_cpu_itimer(struct task_struct *tsk, unsigned int clock_id, | |||
138 | u64 oval, nval, ointerval, ninterval; | 152 | u64 oval, nval, ointerval, ninterval; |
139 | struct cpu_itimer *it = &tsk->signal->it[clock_id]; | 153 | struct cpu_itimer *it = &tsk->signal->it[clock_id]; |
140 | 154 | ||
141 | nval = timeval_to_ns(&value->it_value); | 155 | /* |
142 | ninterval = timeval_to_ns(&value->it_interval); | 156 | * Use the to_ktime conversion because that clamps the maximum |
157 | * value to KTIME_MAX and avoid multiplication overflows. | ||
158 | */ | ||
159 | nval = ktime_to_ns(timeval_to_ktime(value->it_value)); | ||
160 | ninterval = ktime_to_ns(timeval_to_ktime(value->it_interval)); | ||
143 | 161 | ||
144 | spin_lock_irq(&tsk->sighand->siglock); | 162 | spin_lock_irq(&tsk->sighand->siglock); |
145 | 163 | ||
@@ -294,3 +312,27 @@ SYSCALL_DEFINE3(setitimer, int, which, struct itimerval __user *, value, | |||
294 | return -EFAULT; | 312 | return -EFAULT; |
295 | return 0; | 313 | return 0; |
296 | } | 314 | } |
315 | |||
316 | #ifdef CONFIG_COMPAT | ||
317 | COMPAT_SYSCALL_DEFINE3(setitimer, int, which, | ||
318 | struct compat_itimerval __user *, in, | ||
319 | struct compat_itimerval __user *, out) | ||
320 | { | ||
321 | struct itimerval kin, kout; | ||
322 | int error; | ||
323 | |||
324 | if (in) { | ||
325 | if (get_compat_itimerval(&kin, in)) | ||
326 | return -EFAULT; | ||
327 | } else { | ||
328 | memset(&kin, 0, sizeof(kin)); | ||
329 | } | ||
330 | |||
331 | error = do_setitimer(which, &kin, out ? &kout : NULL); | ||
332 | if (error || !out) | ||
333 | return error; | ||
334 | if (put_compat_itimerval(out, &kout)) | ||
335 | return -EFAULT; | ||
336 | return 0; | ||
337 | } | ||
338 | #endif | ||