1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 25cee9645SThomas Gleixner /* 35cee9645SThomas Gleixner * Copyright (C) 1992 Darren Senn 45cee9645SThomas Gleixner */ 55cee9645SThomas Gleixner 65cee9645SThomas Gleixner /* These are all the functions necessary to implement itimers */ 75cee9645SThomas Gleixner 85cee9645SThomas Gleixner #include <linux/mm.h> 95cee9645SThomas Gleixner #include <linux/interrupt.h> 105cee9645SThomas Gleixner #include <linux/syscalls.h> 115cee9645SThomas Gleixner #include <linux/time.h> 123f07c014SIngo Molnar #include <linux/sched/signal.h> 1332ef5517SIngo Molnar #include <linux/sched/cputime.h> 145cee9645SThomas Gleixner #include <linux/posix-timers.h> 155cee9645SThomas Gleixner #include <linux/hrtimer.h> 165cee9645SThomas Gleixner #include <trace/events/timer.h> 1754ad9c46SAl Viro #include <linux/compat.h> 185cee9645SThomas Gleixner 197c0f6ba6SLinus Torvalds #include <linux/uaccess.h> 205cee9645SThomas Gleixner 215cee9645SThomas Gleixner /** 225cee9645SThomas Gleixner * itimer_get_remtime - get remaining time for the timer 235cee9645SThomas Gleixner * 245cee9645SThomas Gleixner * @timer: the timer to read 255cee9645SThomas Gleixner * 265cee9645SThomas Gleixner * Returns the delta between the expiry time and now, which can be 275cee9645SThomas Gleixner * less than zero or 1usec for an pending expired timer 285cee9645SThomas Gleixner */ 29bd40a175SArnd Bergmann static struct timespec64 itimer_get_remtime(struct hrtimer *timer) 305cee9645SThomas Gleixner { 3151cbb524SThomas Gleixner ktime_t rem = __hrtimer_get_remaining(timer, true); 325cee9645SThomas Gleixner 335cee9645SThomas Gleixner /* 345cee9645SThomas Gleixner * Racy but safe: if the itimer expires after the above 355cee9645SThomas Gleixner * hrtimer_get_remtime() call but before this condition 365cee9645SThomas Gleixner * then we return 0 - which is correct. 375cee9645SThomas Gleixner */ 385cee9645SThomas Gleixner if (hrtimer_active(timer)) { 392456e855SThomas Gleixner if (rem <= 0) 402456e855SThomas Gleixner rem = NSEC_PER_USEC; 415cee9645SThomas Gleixner } else 422456e855SThomas Gleixner rem = 0; 435cee9645SThomas Gleixner 44bd40a175SArnd Bergmann return ktime_to_timespec64(rem); 455cee9645SThomas Gleixner } 465cee9645SThomas Gleixner 475cee9645SThomas Gleixner static void get_cpu_itimer(struct task_struct *tsk, unsigned int clock_id, 48bd40a175SArnd Bergmann struct itimerspec64 *const value) 495cee9645SThomas Gleixner { 50858cf3a8SFrederic Weisbecker u64 val, interval; 515cee9645SThomas Gleixner struct cpu_itimer *it = &tsk->signal->it[clock_id]; 525cee9645SThomas Gleixner 535cee9645SThomas Gleixner spin_lock_irq(&tsk->sighand->siglock); 545cee9645SThomas Gleixner 55858cf3a8SFrederic Weisbecker val = it->expires; 56858cf3a8SFrederic Weisbecker interval = it->incr; 57858cf3a8SFrederic Weisbecker if (val) { 58b7be4ef1SThomas Gleixner u64 t, samples[CPUCLOCK_MAX]; 595cee9645SThomas Gleixner 60b7be4ef1SThomas Gleixner thread_group_sample_cputime(tsk, samples); 61b7be4ef1SThomas Gleixner t = samples[clock_id]; 625cee9645SThomas Gleixner 63858cf3a8SFrederic Weisbecker if (val < t) 645cee9645SThomas Gleixner /* about to fire */ 65858cf3a8SFrederic Weisbecker val = TICK_NSEC; 665cee9645SThomas Gleixner else 67858cf3a8SFrederic Weisbecker val -= t; 685cee9645SThomas Gleixner } 695cee9645SThomas Gleixner 705cee9645SThomas Gleixner spin_unlock_irq(&tsk->sighand->siglock); 715cee9645SThomas Gleixner 72bd40a175SArnd Bergmann value->it_value = ns_to_timespec64(val); 73bd40a175SArnd Bergmann value->it_interval = ns_to_timespec64(interval); 745cee9645SThomas Gleixner } 755cee9645SThomas Gleixner 76bd40a175SArnd Bergmann static int do_getitimer(int which, struct itimerspec64 *value) 775cee9645SThomas Gleixner { 785cee9645SThomas Gleixner struct task_struct *tsk = current; 795cee9645SThomas Gleixner 805cee9645SThomas Gleixner switch (which) { 815cee9645SThomas Gleixner case ITIMER_REAL: 825cee9645SThomas Gleixner spin_lock_irq(&tsk->sighand->siglock); 835cee9645SThomas Gleixner value->it_value = itimer_get_remtime(&tsk->signal->real_timer); 845cee9645SThomas Gleixner value->it_interval = 85bd40a175SArnd Bergmann ktime_to_timespec64(tsk->signal->it_real_incr); 865cee9645SThomas Gleixner spin_unlock_irq(&tsk->sighand->siglock); 875cee9645SThomas Gleixner break; 885cee9645SThomas Gleixner case ITIMER_VIRTUAL: 895cee9645SThomas Gleixner get_cpu_itimer(tsk, CPUCLOCK_VIRT, value); 905cee9645SThomas Gleixner break; 915cee9645SThomas Gleixner case ITIMER_PROF: 925cee9645SThomas Gleixner get_cpu_itimer(tsk, CPUCLOCK_PROF, value); 935cee9645SThomas Gleixner break; 945cee9645SThomas Gleixner default: 955cee9645SThomas Gleixner return(-EINVAL); 965cee9645SThomas Gleixner } 975cee9645SThomas Gleixner return 0; 985cee9645SThomas Gleixner } 995cee9645SThomas Gleixner 100bd40a175SArnd Bergmann static int put_itimerval(struct itimerval __user *o, 101bd40a175SArnd Bergmann const struct itimerspec64 *i) 102bd40a175SArnd Bergmann { 103bd40a175SArnd Bergmann struct itimerval v; 104bd40a175SArnd Bergmann 105bd40a175SArnd Bergmann v.it_interval.tv_sec = i->it_interval.tv_sec; 106bd40a175SArnd Bergmann v.it_interval.tv_usec = i->it_interval.tv_nsec / NSEC_PER_USEC; 107bd40a175SArnd Bergmann v.it_value.tv_sec = i->it_value.tv_sec; 108bd40a175SArnd Bergmann v.it_value.tv_usec = i->it_value.tv_nsec / NSEC_PER_USEC; 109bd40a175SArnd Bergmann return copy_to_user(o, &v, sizeof(struct itimerval)) ? -EFAULT : 0; 110bd40a175SArnd Bergmann } 111bd40a175SArnd Bergmann 112bd40a175SArnd Bergmann 1135cee9645SThomas Gleixner SYSCALL_DEFINE2(getitimer, int, which, struct itimerval __user *, value) 1145cee9645SThomas Gleixner { 115bd40a175SArnd Bergmann struct itimerspec64 get_buffer; 116bd40a175SArnd Bergmann int error = do_getitimer(which, &get_buffer); 1175cee9645SThomas Gleixner 118bd40a175SArnd Bergmann if (!error && put_itimerval(value, &get_buffer)) 1195cee9645SThomas Gleixner error = -EFAULT; 1205cee9645SThomas Gleixner return error; 1215cee9645SThomas Gleixner } 1225cee9645SThomas Gleixner 1234c22ea2bSArnd Bergmann #if defined(CONFIG_COMPAT) || defined(CONFIG_ALPHA) 124c1745f84SArnd Bergmann struct old_itimerval32 { 125c1745f84SArnd Bergmann struct old_timeval32 it_interval; 126c1745f84SArnd Bergmann struct old_timeval32 it_value; 127c1745f84SArnd Bergmann }; 128c1745f84SArnd Bergmann 129bd40a175SArnd Bergmann static int put_old_itimerval32(struct old_itimerval32 __user *o, 130bd40a175SArnd Bergmann const struct itimerspec64 *i) 131c1745f84SArnd Bergmann { 132c1745f84SArnd Bergmann struct old_itimerval32 v32; 133c1745f84SArnd Bergmann 134c1745f84SArnd Bergmann v32.it_interval.tv_sec = i->it_interval.tv_sec; 135bd40a175SArnd Bergmann v32.it_interval.tv_usec = i->it_interval.tv_nsec / NSEC_PER_USEC; 136c1745f84SArnd Bergmann v32.it_value.tv_sec = i->it_value.tv_sec; 137bd40a175SArnd Bergmann v32.it_value.tv_usec = i->it_value.tv_nsec / NSEC_PER_USEC; 138c1745f84SArnd Bergmann return copy_to_user(o, &v32, sizeof(struct old_itimerval32)) ? -EFAULT : 0; 139c1745f84SArnd Bergmann } 140c1745f84SArnd Bergmann 14154ad9c46SAl Viro COMPAT_SYSCALL_DEFINE2(getitimer, int, which, 142bd40a175SArnd Bergmann struct old_itimerval32 __user *, value) 14354ad9c46SAl Viro { 144bd40a175SArnd Bergmann struct itimerspec64 get_buffer; 145bd40a175SArnd Bergmann int error = do_getitimer(which, &get_buffer); 14654ad9c46SAl Viro 147bd40a175SArnd Bergmann if (!error && put_old_itimerval32(value, &get_buffer)) 14854ad9c46SAl Viro error = -EFAULT; 14954ad9c46SAl Viro return error; 15054ad9c46SAl Viro } 15154ad9c46SAl Viro #endif 15254ad9c46SAl Viro 1535cee9645SThomas Gleixner /* 1545cee9645SThomas Gleixner * The timer is automagically restarted, when interval != 0 1555cee9645SThomas Gleixner */ 1565cee9645SThomas Gleixner enum hrtimer_restart it_real_fn(struct hrtimer *timer) 1575cee9645SThomas Gleixner { 1585cee9645SThomas Gleixner struct signal_struct *sig = 1595cee9645SThomas Gleixner container_of(timer, struct signal_struct, real_timer); 1606883f81aSEric W. Biederman struct pid *leader_pid = sig->pids[PIDTYPE_TGID]; 1615cee9645SThomas Gleixner 1626883f81aSEric W. Biederman trace_itimer_expire(ITIMER_REAL, leader_pid, 0); 1636883f81aSEric W. Biederman kill_pid_info(SIGALRM, SEND_SIG_PRIV, leader_pid); 1645cee9645SThomas Gleixner 1655cee9645SThomas Gleixner return HRTIMER_NORESTART; 1665cee9645SThomas Gleixner } 1675cee9645SThomas Gleixner 1685cee9645SThomas Gleixner static void set_cpu_itimer(struct task_struct *tsk, unsigned int clock_id, 169bd40a175SArnd Bergmann const struct itimerspec64 *const value, 170bd40a175SArnd Bergmann struct itimerspec64 *const ovalue) 1715cee9645SThomas Gleixner { 172858cf3a8SFrederic Weisbecker u64 oval, nval, ointerval, ninterval; 1735cee9645SThomas Gleixner struct cpu_itimer *it = &tsk->signal->it[clock_id]; 1745cee9645SThomas Gleixner 17535eb7258SThomas Gleixner /* 17635eb7258SThomas Gleixner * Use the to_ktime conversion because that clamps the maximum 17735eb7258SThomas Gleixner * value to KTIME_MAX and avoid multiplication overflows. 17835eb7258SThomas Gleixner */ 179bd40a175SArnd Bergmann nval = timespec64_to_ns(&value->it_value); 180bd40a175SArnd Bergmann ninterval = timespec64_to_ns(&value->it_interval); 1815cee9645SThomas Gleixner 1825cee9645SThomas Gleixner spin_lock_irq(&tsk->sighand->siglock); 1835cee9645SThomas Gleixner 184858cf3a8SFrederic Weisbecker oval = it->expires; 185858cf3a8SFrederic Weisbecker ointerval = it->incr; 186858cf3a8SFrederic Weisbecker if (oval || nval) { 1875cee9645SThomas Gleixner if (nval > 0) 188858cf3a8SFrederic Weisbecker nval += TICK_NSEC; 189858cf3a8SFrederic Weisbecker set_process_cpu_timer(tsk, clock_id, &nval, &oval); 1905cee9645SThomas Gleixner } 1915cee9645SThomas Gleixner it->expires = nval; 1925cee9645SThomas Gleixner it->incr = ninterval; 1935cee9645SThomas Gleixner trace_itimer_state(clock_id == CPUCLOCK_VIRT ? 1945cee9645SThomas Gleixner ITIMER_VIRTUAL : ITIMER_PROF, value, nval); 1955cee9645SThomas Gleixner 1965cee9645SThomas Gleixner spin_unlock_irq(&tsk->sighand->siglock); 1975cee9645SThomas Gleixner 1985cee9645SThomas Gleixner if (ovalue) { 199bd40a175SArnd Bergmann ovalue->it_value = ns_to_timespec64(oval); 200bd40a175SArnd Bergmann ovalue->it_interval = ns_to_timespec64(ointerval); 2015cee9645SThomas Gleixner } 2025cee9645SThomas Gleixner } 2035cee9645SThomas Gleixner 2045cee9645SThomas Gleixner /* 2055cee9645SThomas Gleixner * Returns true if the timeval is in canonical form 2065cee9645SThomas Gleixner */ 2075cee9645SThomas Gleixner #define timeval_valid(t) \ 2085cee9645SThomas Gleixner (((t)->tv_sec >= 0) && (((unsigned long) (t)->tv_usec) < USEC_PER_SEC)) 2095cee9645SThomas Gleixner 210bd40a175SArnd Bergmann static int do_setitimer(int which, struct itimerspec64 *value, 211bd40a175SArnd Bergmann struct itimerspec64 *ovalue) 2125cee9645SThomas Gleixner { 2135cee9645SThomas Gleixner struct task_struct *tsk = current; 2145cee9645SThomas Gleixner struct hrtimer *timer; 2155cee9645SThomas Gleixner ktime_t expires; 2165cee9645SThomas Gleixner 2175cee9645SThomas Gleixner switch (which) { 2185cee9645SThomas Gleixner case ITIMER_REAL: 2195cee9645SThomas Gleixner again: 2205cee9645SThomas Gleixner spin_lock_irq(&tsk->sighand->siglock); 2215cee9645SThomas Gleixner timer = &tsk->signal->real_timer; 2225cee9645SThomas Gleixner if (ovalue) { 2235cee9645SThomas Gleixner ovalue->it_value = itimer_get_remtime(timer); 2245cee9645SThomas Gleixner ovalue->it_interval 225bd40a175SArnd Bergmann = ktime_to_timespec64(tsk->signal->it_real_incr); 2265cee9645SThomas Gleixner } 2275cee9645SThomas Gleixner /* We are sharing ->siglock with it_real_fn() */ 2285cee9645SThomas Gleixner if (hrtimer_try_to_cancel(timer) < 0) { 2295cee9645SThomas Gleixner spin_unlock_irq(&tsk->sighand->siglock); 230c7e6d704SAnna-Maria Gleixner hrtimer_cancel_wait_running(timer); 2315cee9645SThomas Gleixner goto again; 2325cee9645SThomas Gleixner } 233bd40a175SArnd Bergmann expires = timespec64_to_ktime(value->it_value); 2342456e855SThomas Gleixner if (expires != 0) { 2355cee9645SThomas Gleixner tsk->signal->it_real_incr = 236bd40a175SArnd Bergmann timespec64_to_ktime(value->it_interval); 2375cee9645SThomas Gleixner hrtimer_start(timer, expires, HRTIMER_MODE_REL); 2385cee9645SThomas Gleixner } else 2392456e855SThomas Gleixner tsk->signal->it_real_incr = 0; 2405cee9645SThomas Gleixner 2415cee9645SThomas Gleixner trace_itimer_state(ITIMER_REAL, value, 0); 2425cee9645SThomas Gleixner spin_unlock_irq(&tsk->sighand->siglock); 2435cee9645SThomas Gleixner break; 2445cee9645SThomas Gleixner case ITIMER_VIRTUAL: 2455cee9645SThomas Gleixner set_cpu_itimer(tsk, CPUCLOCK_VIRT, value, ovalue); 2465cee9645SThomas Gleixner break; 2475cee9645SThomas Gleixner case ITIMER_PROF: 2485cee9645SThomas Gleixner set_cpu_itimer(tsk, CPUCLOCK_PROF, value, ovalue); 2495cee9645SThomas Gleixner break; 2505cee9645SThomas Gleixner default: 2515cee9645SThomas Gleixner return -EINVAL; 2525cee9645SThomas Gleixner } 2535cee9645SThomas Gleixner return 0; 2545cee9645SThomas Gleixner } 2555cee9645SThomas Gleixner 256ddbc7d06SArnd Bergmann #ifdef CONFIG_SECURITY_SELINUX 257ddbc7d06SArnd Bergmann void clear_itimer(void) 258ddbc7d06SArnd Bergmann { 259bd40a175SArnd Bergmann struct itimerspec64 v = {}; 260ddbc7d06SArnd Bergmann int i; 261ddbc7d06SArnd Bergmann 262ddbc7d06SArnd Bergmann for (i = 0; i < 3; i++) 263ddbc7d06SArnd Bergmann do_setitimer(i, &v, NULL); 264ddbc7d06SArnd Bergmann } 265ddbc7d06SArnd Bergmann #endif 266ddbc7d06SArnd Bergmann 26774ba181eSNicolas Pitre #ifdef __ARCH_WANT_SYS_ALARM 26874ba181eSNicolas Pitre 2695cee9645SThomas Gleixner /** 2705cee9645SThomas Gleixner * alarm_setitimer - set alarm in seconds 2715cee9645SThomas Gleixner * 2725cee9645SThomas Gleixner * @seconds: number of seconds until alarm 2735cee9645SThomas Gleixner * 0 disables the alarm 2745cee9645SThomas Gleixner * 2755cee9645SThomas Gleixner * Returns the remaining time in seconds of a pending timer or 0 when 2765cee9645SThomas Gleixner * the timer is not active. 2775cee9645SThomas Gleixner * 2785cee9645SThomas Gleixner * On 32 bit machines the seconds value is limited to (INT_MAX/2) to avoid 2795cee9645SThomas Gleixner * negative timeval settings which would cause immediate expiry. 2805cee9645SThomas Gleixner */ 28174ba181eSNicolas Pitre static unsigned int alarm_setitimer(unsigned int seconds) 2825cee9645SThomas Gleixner { 283bd40a175SArnd Bergmann struct itimerspec64 it_new, it_old; 2845cee9645SThomas Gleixner 2855cee9645SThomas Gleixner #if BITS_PER_LONG < 64 2865cee9645SThomas Gleixner if (seconds > INT_MAX) 2875cee9645SThomas Gleixner seconds = INT_MAX; 2885cee9645SThomas Gleixner #endif 2895cee9645SThomas Gleixner it_new.it_value.tv_sec = seconds; 290bd40a175SArnd Bergmann it_new.it_value.tv_nsec = 0; 291bd40a175SArnd Bergmann it_new.it_interval.tv_sec = it_new.it_interval.tv_nsec = 0; 2925cee9645SThomas Gleixner 2935cee9645SThomas Gleixner do_setitimer(ITIMER_REAL, &it_new, &it_old); 2945cee9645SThomas Gleixner 2955cee9645SThomas Gleixner /* 2965cee9645SThomas Gleixner * We can't return 0 if we have an alarm pending ... And we'd 2975cee9645SThomas Gleixner * better return too much than too little anyway 2985cee9645SThomas Gleixner */ 299bd40a175SArnd Bergmann if ((!it_old.it_value.tv_sec && it_old.it_value.tv_nsec) || 300bd40a175SArnd Bergmann it_old.it_value.tv_nsec >= 500000) 3015cee9645SThomas Gleixner it_old.it_value.tv_sec++; 3025cee9645SThomas Gleixner 3035cee9645SThomas Gleixner return it_old.it_value.tv_sec; 3045cee9645SThomas Gleixner } 3055cee9645SThomas Gleixner 30674ba181eSNicolas Pitre /* 30774ba181eSNicolas Pitre * For backwards compatibility? This can be done in libc so Alpha 30874ba181eSNicolas Pitre * and all newer ports shouldn't need it. 30974ba181eSNicolas Pitre */ 31074ba181eSNicolas Pitre SYSCALL_DEFINE1(alarm, unsigned int, seconds) 31174ba181eSNicolas Pitre { 31274ba181eSNicolas Pitre return alarm_setitimer(seconds); 31374ba181eSNicolas Pitre } 31474ba181eSNicolas Pitre 31574ba181eSNicolas Pitre #endif 31674ba181eSNicolas Pitre 317bd40a175SArnd Bergmann static int get_itimerval(struct itimerspec64 *o, const struct itimerval __user *i) 318bd40a175SArnd Bergmann { 319bd40a175SArnd Bergmann struct itimerval v; 320bd40a175SArnd Bergmann 321bd40a175SArnd Bergmann if (copy_from_user(&v, i, sizeof(struct itimerval))) 322bd40a175SArnd Bergmann return -EFAULT; 323bd40a175SArnd Bergmann 324bd40a175SArnd Bergmann /* Validate the timevals in value. */ 325bd40a175SArnd Bergmann if (!timeval_valid(&v.it_value) || 326bd40a175SArnd Bergmann !timeval_valid(&v.it_interval)) 327bd40a175SArnd Bergmann return -EINVAL; 328bd40a175SArnd Bergmann 329bd40a175SArnd Bergmann o->it_interval.tv_sec = v.it_interval.tv_sec; 330bd40a175SArnd Bergmann o->it_interval.tv_nsec = v.it_interval.tv_usec * NSEC_PER_USEC; 331bd40a175SArnd Bergmann o->it_value.tv_sec = v.it_value.tv_sec; 332bd40a175SArnd Bergmann o->it_value.tv_nsec = v.it_value.tv_usec * NSEC_PER_USEC; 333bd40a175SArnd Bergmann return 0; 334bd40a175SArnd Bergmann } 335bd40a175SArnd Bergmann 3365cee9645SThomas Gleixner SYSCALL_DEFINE3(setitimer, int, which, struct itimerval __user *, value, 3375cee9645SThomas Gleixner struct itimerval __user *, ovalue) 3385cee9645SThomas Gleixner { 339bd40a175SArnd Bergmann struct itimerspec64 set_buffer, get_buffer; 3405cee9645SThomas Gleixner int error; 3415cee9645SThomas Gleixner 3425cee9645SThomas Gleixner if (value) { 343bd40a175SArnd Bergmann error = get_itimerval(&set_buffer, value); 344bd40a175SArnd Bergmann if (error) 345bd40a175SArnd Bergmann return error; 3465cee9645SThomas Gleixner } else { 3475cee9645SThomas Gleixner memset(&set_buffer, 0, sizeof(set_buffer)); 3485cee9645SThomas Gleixner printk_once(KERN_WARNING "%s calls setitimer() with new_value NULL pointer." 3495cee9645SThomas Gleixner " Misfeature support will be removed\n", 3505cee9645SThomas Gleixner current->comm); 3515cee9645SThomas Gleixner } 3525cee9645SThomas Gleixner 3535cee9645SThomas Gleixner error = do_setitimer(which, &set_buffer, ovalue ? &get_buffer : NULL); 3545cee9645SThomas Gleixner if (error || !ovalue) 3555cee9645SThomas Gleixner return error; 3565cee9645SThomas Gleixner 357bd40a175SArnd Bergmann if (put_itimerval(ovalue, &get_buffer)) 3585cee9645SThomas Gleixner return -EFAULT; 3595cee9645SThomas Gleixner return 0; 3605cee9645SThomas Gleixner } 36154ad9c46SAl Viro 3624c22ea2bSArnd Bergmann #if defined(CONFIG_COMPAT) || defined(CONFIG_ALPHA) 363bd40a175SArnd Bergmann static int get_old_itimerval32(struct itimerspec64 *o, const struct old_itimerval32 __user *i) 364c1745f84SArnd Bergmann { 365c1745f84SArnd Bergmann struct old_itimerval32 v32; 366c1745f84SArnd Bergmann 367c1745f84SArnd Bergmann if (copy_from_user(&v32, i, sizeof(struct old_itimerval32))) 368c1745f84SArnd Bergmann return -EFAULT; 369bd40a175SArnd Bergmann 370bd40a175SArnd Bergmann /* Validate the timevals in value. */ 371bd40a175SArnd Bergmann if (!timeval_valid(&v32.it_value) || 372bd40a175SArnd Bergmann !timeval_valid(&v32.it_interval)) 373bd40a175SArnd Bergmann return -EINVAL; 374bd40a175SArnd Bergmann 375c1745f84SArnd Bergmann o->it_interval.tv_sec = v32.it_interval.tv_sec; 376bd40a175SArnd Bergmann o->it_interval.tv_nsec = v32.it_interval.tv_usec * NSEC_PER_USEC; 377c1745f84SArnd Bergmann o->it_value.tv_sec = v32.it_value.tv_sec; 378bd40a175SArnd Bergmann o->it_value.tv_nsec = v32.it_value.tv_usec * NSEC_PER_USEC; 379c1745f84SArnd Bergmann return 0; 380c1745f84SArnd Bergmann } 381c1745f84SArnd Bergmann 38254ad9c46SAl Viro COMPAT_SYSCALL_DEFINE3(setitimer, int, which, 383bd40a175SArnd Bergmann struct old_itimerval32 __user *, value, 384bd40a175SArnd Bergmann struct old_itimerval32 __user *, ovalue) 38554ad9c46SAl Viro { 386bd40a175SArnd Bergmann struct itimerspec64 set_buffer, get_buffer; 38754ad9c46SAl Viro int error; 38854ad9c46SAl Viro 389bd40a175SArnd Bergmann if (value) { 390bd40a175SArnd Bergmann error = get_old_itimerval32(&set_buffer, value); 391bd40a175SArnd Bergmann if (error) 392bd40a175SArnd Bergmann return error; 39354ad9c46SAl Viro } else { 394bd40a175SArnd Bergmann memset(&set_buffer, 0, sizeof(set_buffer)); 395bd40a175SArnd Bergmann printk_once(KERN_WARNING "%s calls setitimer() with new_value NULL pointer." 396bd40a175SArnd Bergmann " Misfeature support will be removed\n", 397bd40a175SArnd Bergmann current->comm); 39854ad9c46SAl Viro } 39954ad9c46SAl Viro 400bd40a175SArnd Bergmann error = do_setitimer(which, &set_buffer, ovalue ? &get_buffer : NULL); 401bd40a175SArnd Bergmann if (error || !ovalue) 40254ad9c46SAl Viro return error; 403bd40a175SArnd Bergmann if (put_old_itimerval32(ovalue, &get_buffer)) 40454ad9c46SAl Viro return -EFAULT; 40554ad9c46SAl Viro return 0; 40654ad9c46SAl Viro } 40754ad9c46SAl Viro #endif 408