| .. | .. | 
|---|
| 1 | 1 |  // SPDX-License-Identifier: GPL-2.0 | 
|---|
| 2 | 2 |  /* | 
|---|
| 3 |  | - * linux/kernel/itimer.c  | 
|---|
| 4 |  | - *  | 
|---|
| 5 | 3 |   * Copyright (C) 1992 Darren Senn | 
|---|
| 6 | 4 |   */ | 
|---|
| 7 | 5 |   | 
|---|
| .. | .. | 
|---|
| 28 | 26 |   * Returns the delta between the expiry time and now, which can be | 
|---|
| 29 | 27 |   * less than zero or 1usec for an pending expired timer | 
|---|
| 30 | 28 |   */ | 
|---|
| 31 |  | -static struct timeval itimer_get_remtime(struct hrtimer *timer)  | 
|---|
 | 29 | +static struct timespec64 itimer_get_remtime(struct hrtimer *timer)  | 
|---|
| 32 | 30 |  { | 
|---|
| 33 | 31 |  	ktime_t rem = __hrtimer_get_remaining(timer, true); | 
|---|
| 34 | 32 |   | 
|---|
| .. | .. | 
|---|
| 43 | 41 |  	} else | 
|---|
| 44 | 42 |  		rem = 0; | 
|---|
| 45 | 43 |   | 
|---|
| 46 |  | -	return ktime_to_timeval(rem);  | 
|---|
 | 44 | +	return ktime_to_timespec64(rem);  | 
|---|
| 47 | 45 |  } | 
|---|
| 48 | 46 |   | 
|---|
| 49 | 47 |  static void get_cpu_itimer(struct task_struct *tsk, unsigned int clock_id, | 
|---|
| 50 |  | -			   struct itimerval *const value)  | 
|---|
 | 48 | +			   struct itimerspec64 *const value)  | 
|---|
| 51 | 49 |  { | 
|---|
| 52 | 50 |  	u64 val, interval; | 
|---|
| 53 | 51 |  	struct cpu_itimer *it = &tsk->signal->it[clock_id]; | 
|---|
| .. | .. | 
|---|
| 57 | 55 |  	val = it->expires; | 
|---|
| 58 | 56 |  	interval = it->incr; | 
|---|
| 59 | 57 |  	if (val) { | 
|---|
| 60 |  | -		struct task_cputime cputime;  | 
|---|
| 61 |  | -		u64 t;  | 
|---|
 | 58 | +		u64 t, samples[CPUCLOCK_MAX];  | 
|---|
| 62 | 59 |   | 
|---|
| 63 |  | -		thread_group_cputimer(tsk, &cputime);  | 
|---|
| 64 |  | -		if (clock_id == CPUCLOCK_PROF)  | 
|---|
| 65 |  | -			t = cputime.utime + cputime.stime;  | 
|---|
| 66 |  | -		else  | 
|---|
| 67 |  | -			/* CPUCLOCK_VIRT */  | 
|---|
| 68 |  | -			t = cputime.utime;  | 
|---|
 | 60 | +		thread_group_sample_cputime(tsk, samples);  | 
|---|
 | 61 | +		t = samples[clock_id];  | 
|---|
| 69 | 62 |   | 
|---|
| 70 | 63 |  		if (val < t) | 
|---|
| 71 | 64 |  			/* about to fire */ | 
|---|
| .. | .. | 
|---|
| 76 | 69 |   | 
|---|
| 77 | 70 |  	spin_unlock_irq(&tsk->sighand->siglock); | 
|---|
| 78 | 71 |   | 
|---|
| 79 |  | -	value->it_value = ns_to_timeval(val);  | 
|---|
| 80 |  | -	value->it_interval = ns_to_timeval(interval);  | 
|---|
 | 72 | +	value->it_value = ns_to_timespec64(val);  | 
|---|
 | 73 | +	value->it_interval = ns_to_timespec64(interval);  | 
|---|
| 81 | 74 |  } | 
|---|
| 82 | 75 |   | 
|---|
| 83 |  | -int do_getitimer(int which, struct itimerval *value)  | 
|---|
 | 76 | +static int do_getitimer(int which, struct itimerspec64 *value)  | 
|---|
| 84 | 77 |  { | 
|---|
| 85 | 78 |  	struct task_struct *tsk = current; | 
|---|
| 86 | 79 |   | 
|---|
| .. | .. | 
|---|
| 89 | 82 |  		spin_lock_irq(&tsk->sighand->siglock); | 
|---|
| 90 | 83 |  		value->it_value = itimer_get_remtime(&tsk->signal->real_timer); | 
|---|
| 91 | 84 |  		value->it_interval = | 
|---|
| 92 |  | -			ktime_to_timeval(tsk->signal->it_real_incr);  | 
|---|
 | 85 | +			ktime_to_timespec64(tsk->signal->it_real_incr);  | 
|---|
| 93 | 86 |  		spin_unlock_irq(&tsk->sighand->siglock); | 
|---|
| 94 | 87 |  		break; | 
|---|
| 95 | 88 |  	case ITIMER_VIRTUAL: | 
|---|
| .. | .. | 
|---|
| 104 | 97 |  	return 0; | 
|---|
| 105 | 98 |  } | 
|---|
| 106 | 99 |   | 
|---|
| 107 |  | -SYSCALL_DEFINE2(getitimer, int, which, struct itimerval __user *, value)  | 
|---|
 | 100 | +static int put_itimerval(struct __kernel_old_itimerval __user *o,  | 
|---|
 | 101 | +			 const struct itimerspec64 *i)  | 
|---|
| 108 | 102 |  { | 
|---|
| 109 |  | -	int error = -EFAULT;  | 
|---|
| 110 |  | -	struct itimerval get_buffer;  | 
|---|
 | 103 | +	struct __kernel_old_itimerval v;  | 
|---|
| 111 | 104 |   | 
|---|
| 112 |  | -	if (value) {  | 
|---|
| 113 |  | -		error = do_getitimer(which, &get_buffer);  | 
|---|
| 114 |  | -		if (!error &&  | 
|---|
| 115 |  | -		    copy_to_user(value, &get_buffer, sizeof(get_buffer)))  | 
|---|
| 116 |  | -			error = -EFAULT;  | 
|---|
| 117 |  | -	}  | 
|---|
 | 105 | +	v.it_interval.tv_sec = i->it_interval.tv_sec;  | 
|---|
 | 106 | +	v.it_interval.tv_usec = i->it_interval.tv_nsec / NSEC_PER_USEC;  | 
|---|
 | 107 | +	v.it_value.tv_sec = i->it_value.tv_sec;  | 
|---|
 | 108 | +	v.it_value.tv_usec = i->it_value.tv_nsec / NSEC_PER_USEC;  | 
|---|
 | 109 | +	return copy_to_user(o, &v, sizeof(struct __kernel_old_itimerval)) ? -EFAULT : 0;  | 
|---|
 | 110 | +}  | 
|---|
 | 111 | +  | 
|---|
 | 112 | +  | 
|---|
 | 113 | +SYSCALL_DEFINE2(getitimer, int, which, struct __kernel_old_itimerval __user *, value)  | 
|---|
 | 114 | +{  | 
|---|
 | 115 | +	struct itimerspec64 get_buffer;  | 
|---|
 | 116 | +	int error = do_getitimer(which, &get_buffer);  | 
|---|
 | 117 | +  | 
|---|
 | 118 | +	if (!error && put_itimerval(value, &get_buffer))  | 
|---|
 | 119 | +		error = -EFAULT;  | 
|---|
| 118 | 120 |  	return error; | 
|---|
| 119 | 121 |  } | 
|---|
| 120 | 122 |   | 
|---|
| 121 |  | -#ifdef CONFIG_COMPAT  | 
|---|
| 122 |  | -COMPAT_SYSCALL_DEFINE2(getitimer, int, which,  | 
|---|
| 123 |  | -		       struct compat_itimerval __user *, it)  | 
|---|
| 124 |  | -{  | 
|---|
| 125 |  | -	struct itimerval kit;  | 
|---|
| 126 |  | -	int error = do_getitimer(which, &kit);  | 
|---|
 | 123 | +#if defined(CONFIG_COMPAT) || defined(CONFIG_ALPHA)  | 
|---|
 | 124 | +struct old_itimerval32 {  | 
|---|
 | 125 | +	struct old_timeval32	it_interval;  | 
|---|
 | 126 | +	struct old_timeval32	it_value;  | 
|---|
 | 127 | +};  | 
|---|
| 127 | 128 |   | 
|---|
| 128 |  | -	if (!error && put_compat_itimerval(it, &kit))  | 
|---|
 | 129 | +static int put_old_itimerval32(struct old_itimerval32 __user *o,  | 
|---|
 | 130 | +			       const struct itimerspec64 *i)  | 
|---|
 | 131 | +{  | 
|---|
 | 132 | +	struct old_itimerval32 v32;  | 
|---|
 | 133 | +  | 
|---|
 | 134 | +	v32.it_interval.tv_sec = i->it_interval.tv_sec;  | 
|---|
 | 135 | +	v32.it_interval.tv_usec = i->it_interval.tv_nsec / NSEC_PER_USEC;  | 
|---|
 | 136 | +	v32.it_value.tv_sec = i->it_value.tv_sec;  | 
|---|
 | 137 | +	v32.it_value.tv_usec = i->it_value.tv_nsec / NSEC_PER_USEC;  | 
|---|
 | 138 | +	return copy_to_user(o, &v32, sizeof(struct old_itimerval32)) ? -EFAULT : 0;  | 
|---|
 | 139 | +}  | 
|---|
 | 140 | +  | 
|---|
 | 141 | +COMPAT_SYSCALL_DEFINE2(getitimer, int, which,  | 
|---|
 | 142 | +		       struct old_itimerval32 __user *, value)  | 
|---|
 | 143 | +{  | 
|---|
 | 144 | +	struct itimerspec64 get_buffer;  | 
|---|
 | 145 | +	int error = do_getitimer(which, &get_buffer);  | 
|---|
 | 146 | +  | 
|---|
 | 147 | +	if (!error && put_old_itimerval32(value, &get_buffer))  | 
|---|
| 129 | 148 |  		error = -EFAULT; | 
|---|
| 130 | 149 |  	return error; | 
|---|
| 131 | 150 |  } | 
|---|
| 132 | 151 |  #endif | 
|---|
| 133 |  | -  | 
|---|
| 134 | 152 |   | 
|---|
| 135 | 153 |  /* | 
|---|
| 136 | 154 |   * The timer is automagically restarted, when interval != 0 | 
|---|
| .. | .. | 
|---|
| 148 | 166 |  } | 
|---|
| 149 | 167 |   | 
|---|
| 150 | 168 |  static void set_cpu_itimer(struct task_struct *tsk, unsigned int clock_id, | 
|---|
| 151 |  | -			   const struct itimerval *const value,  | 
|---|
| 152 |  | -			   struct itimerval *const ovalue)  | 
|---|
 | 169 | +			   const struct itimerspec64 *const value,  | 
|---|
 | 170 | +			   struct itimerspec64 *const ovalue)  | 
|---|
| 153 | 171 |  { | 
|---|
| 154 | 172 |  	u64 oval, nval, ointerval, ninterval; | 
|---|
| 155 | 173 |  	struct cpu_itimer *it = &tsk->signal->it[clock_id]; | 
|---|
| 156 | 174 |   | 
|---|
| 157 |  | -	nval = ktime_to_ns(timeval_to_ktime(value->it_value));  | 
|---|
| 158 |  | -	ninterval = ktime_to_ns(timeval_to_ktime(value->it_interval));  | 
|---|
 | 175 | +	nval = timespec64_to_ns(&value->it_value);  | 
|---|
 | 176 | +	ninterval = timespec64_to_ns(&value->it_interval);  | 
|---|
| 159 | 177 |   | 
|---|
| 160 | 178 |  	spin_lock_irq(&tsk->sighand->siglock); | 
|---|
| 161 | 179 |   | 
|---|
| .. | .. | 
|---|
| 174 | 192 |  	spin_unlock_irq(&tsk->sighand->siglock); | 
|---|
| 175 | 193 |   | 
|---|
| 176 | 194 |  	if (ovalue) { | 
|---|
| 177 |  | -		ovalue->it_value = ns_to_timeval(oval);  | 
|---|
| 178 |  | -		ovalue->it_interval = ns_to_timeval(ointerval);  | 
|---|
 | 195 | +		ovalue->it_value = ns_to_timespec64(oval);  | 
|---|
 | 196 | +		ovalue->it_interval = ns_to_timespec64(ointerval);  | 
|---|
| 179 | 197 |  	} | 
|---|
| 180 | 198 |  } | 
|---|
| 181 | 199 |   | 
|---|
| .. | .. | 
|---|
| 185 | 203 |  #define timeval_valid(t) \ | 
|---|
| 186 | 204 |  	(((t)->tv_sec >= 0) && (((unsigned long) (t)->tv_usec) < USEC_PER_SEC)) | 
|---|
| 187 | 205 |   | 
|---|
| 188 |  | -int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)  | 
|---|
 | 206 | +static int do_setitimer(int which, struct itimerspec64 *value,  | 
|---|
 | 207 | +			struct itimerspec64 *ovalue)  | 
|---|
| 189 | 208 |  { | 
|---|
| 190 | 209 |  	struct task_struct *tsk = current; | 
|---|
| 191 | 210 |  	struct hrtimer *timer; | 
|---|
| 192 | 211 |  	ktime_t expires; | 
|---|
| 193 |  | -  | 
|---|
| 194 |  | -	/*  | 
|---|
| 195 |  | -	 * Validate the timevals in value.  | 
|---|
| 196 |  | -	 */  | 
|---|
| 197 |  | -	if (!timeval_valid(&value->it_value) ||  | 
|---|
| 198 |  | -	    !timeval_valid(&value->it_interval))  | 
|---|
| 199 |  | -		return -EINVAL;  | 
|---|
| 200 | 212 |   | 
|---|
| 201 | 213 |  	switch (which) { | 
|---|
| 202 | 214 |  	case ITIMER_REAL: | 
|---|
| .. | .. | 
|---|
| 206 | 218 |  		if (ovalue) { | 
|---|
| 207 | 219 |  			ovalue->it_value = itimer_get_remtime(timer); | 
|---|
| 208 | 220 |  			ovalue->it_interval | 
|---|
| 209 |  | -				= ktime_to_timeval(tsk->signal->it_real_incr);  | 
|---|
 | 221 | +				= ktime_to_timespec64(tsk->signal->it_real_incr);  | 
|---|
| 210 | 222 |  		} | 
|---|
| 211 | 223 |  		/* We are sharing ->siglock with it_real_fn() */ | 
|---|
| 212 | 224 |  		if (hrtimer_try_to_cancel(timer) < 0) { | 
|---|
| 213 | 225 |  			spin_unlock_irq(&tsk->sighand->siglock); | 
|---|
| 214 |  | -			hrtimer_grab_expiry_lock(timer);  | 
|---|
 | 226 | +			hrtimer_cancel_wait_running(timer);  | 
|---|
| 215 | 227 |  			goto again; | 
|---|
| 216 | 228 |  		} | 
|---|
| 217 |  | -		expires = timeval_to_ktime(value->it_value);  | 
|---|
 | 229 | +		expires = timespec64_to_ktime(value->it_value);  | 
|---|
| 218 | 230 |  		if (expires != 0) { | 
|---|
| 219 | 231 |  			tsk->signal->it_real_incr = | 
|---|
| 220 |  | -				timeval_to_ktime(value->it_interval);  | 
|---|
 | 232 | +				timespec64_to_ktime(value->it_interval);  | 
|---|
| 221 | 233 |  			hrtimer_start(timer, expires, HRTIMER_MODE_REL); | 
|---|
| 222 | 234 |  		} else | 
|---|
| 223 | 235 |  			tsk->signal->it_real_incr = 0; | 
|---|
| .. | .. | 
|---|
| 237 | 249 |  	return 0; | 
|---|
| 238 | 250 |  } | 
|---|
| 239 | 251 |   | 
|---|
 | 252 | +#ifdef CONFIG_SECURITY_SELINUX  | 
|---|
 | 253 | +void clear_itimer(void)  | 
|---|
 | 254 | +{  | 
|---|
 | 255 | +	struct itimerspec64 v = {};  | 
|---|
 | 256 | +	int i;  | 
|---|
 | 257 | +  | 
|---|
 | 258 | +	for (i = 0; i < 3; i++)  | 
|---|
 | 259 | +		do_setitimer(i, &v, NULL);  | 
|---|
 | 260 | +}  | 
|---|
 | 261 | +#endif  | 
|---|
 | 262 | +  | 
|---|
| 240 | 263 |  #ifdef __ARCH_WANT_SYS_ALARM | 
|---|
| 241 | 264 |   | 
|---|
| 242 | 265 |  /** | 
|---|
| .. | .. | 
|---|
| 253 | 276 |   */ | 
|---|
| 254 | 277 |  static unsigned int alarm_setitimer(unsigned int seconds) | 
|---|
| 255 | 278 |  { | 
|---|
| 256 |  | -	struct itimerval it_new, it_old;  | 
|---|
 | 279 | +	struct itimerspec64 it_new, it_old;  | 
|---|
| 257 | 280 |   | 
|---|
| 258 | 281 |  #if BITS_PER_LONG < 64 | 
|---|
| 259 | 282 |  	if (seconds > INT_MAX) | 
|---|
| 260 | 283 |  		seconds = INT_MAX; | 
|---|
| 261 | 284 |  #endif | 
|---|
| 262 | 285 |  	it_new.it_value.tv_sec = seconds; | 
|---|
| 263 |  | -	it_new.it_value.tv_usec = 0;  | 
|---|
| 264 |  | -	it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0;  | 
|---|
 | 286 | +	it_new.it_value.tv_nsec = 0;  | 
|---|
 | 287 | +	it_new.it_interval.tv_sec = it_new.it_interval.tv_nsec = 0;  | 
|---|
| 265 | 288 |   | 
|---|
| 266 | 289 |  	do_setitimer(ITIMER_REAL, &it_new, &it_old); | 
|---|
| 267 | 290 |   | 
|---|
| .. | .. | 
|---|
| 269 | 292 |  	 * We can't return 0 if we have an alarm pending ...  And we'd | 
|---|
| 270 | 293 |  	 * better return too much than too little anyway | 
|---|
| 271 | 294 |  	 */ | 
|---|
| 272 |  | -	if ((!it_old.it_value.tv_sec && it_old.it_value.tv_usec) ||  | 
|---|
| 273 |  | -	      it_old.it_value.tv_usec >= 500000)  | 
|---|
 | 295 | +	if ((!it_old.it_value.tv_sec && it_old.it_value.tv_nsec) ||  | 
|---|
 | 296 | +	      it_old.it_value.tv_nsec >= (NSEC_PER_SEC / 2))  | 
|---|
| 274 | 297 |  		it_old.it_value.tv_sec++; | 
|---|
| 275 | 298 |   | 
|---|
| 276 | 299 |  	return it_old.it_value.tv_sec; | 
|---|
| .. | .. | 
|---|
| 287 | 310 |   | 
|---|
| 288 | 311 |  #endif | 
|---|
| 289 | 312 |   | 
|---|
| 290 |  | -SYSCALL_DEFINE3(setitimer, int, which, struct itimerval __user *, value,  | 
|---|
| 291 |  | -		struct itimerval __user *, ovalue)  | 
|---|
 | 313 | +static int get_itimerval(struct itimerspec64 *o, const struct __kernel_old_itimerval __user *i)  | 
|---|
| 292 | 314 |  { | 
|---|
| 293 |  | -	struct itimerval set_buffer, get_buffer;  | 
|---|
 | 315 | +	struct __kernel_old_itimerval v;  | 
|---|
 | 316 | +  | 
|---|
 | 317 | +	if (copy_from_user(&v, i, sizeof(struct __kernel_old_itimerval)))  | 
|---|
 | 318 | +		return -EFAULT;  | 
|---|
 | 319 | +  | 
|---|
 | 320 | +	/* Validate the timevals in value. */  | 
|---|
 | 321 | +	if (!timeval_valid(&v.it_value) ||  | 
|---|
 | 322 | +	    !timeval_valid(&v.it_interval))  | 
|---|
 | 323 | +		return -EINVAL;  | 
|---|
 | 324 | +  | 
|---|
 | 325 | +	o->it_interval.tv_sec = v.it_interval.tv_sec;  | 
|---|
 | 326 | +	o->it_interval.tv_nsec = v.it_interval.tv_usec * NSEC_PER_USEC;  | 
|---|
 | 327 | +	o->it_value.tv_sec = v.it_value.tv_sec;  | 
|---|
 | 328 | +	o->it_value.tv_nsec = v.it_value.tv_usec * NSEC_PER_USEC;  | 
|---|
 | 329 | +	return 0;  | 
|---|
 | 330 | +}  | 
|---|
 | 331 | +  | 
|---|
 | 332 | +SYSCALL_DEFINE3(setitimer, int, which, struct __kernel_old_itimerval __user *, value,  | 
|---|
 | 333 | +		struct __kernel_old_itimerval __user *, ovalue)  | 
|---|
 | 334 | +{  | 
|---|
 | 335 | +	struct itimerspec64 set_buffer, get_buffer;  | 
|---|
| 294 | 336 |  	int error; | 
|---|
| 295 | 337 |   | 
|---|
| 296 | 338 |  	if (value) { | 
|---|
| 297 |  | -		if(copy_from_user(&set_buffer, value, sizeof(set_buffer)))  | 
|---|
| 298 |  | -			return -EFAULT;  | 
|---|
 | 339 | +		error = get_itimerval(&set_buffer, value);  | 
|---|
 | 340 | +		if (error)  | 
|---|
 | 341 | +			return error;  | 
|---|
| 299 | 342 |  	} else { | 
|---|
| 300 | 343 |  		memset(&set_buffer, 0, sizeof(set_buffer)); | 
|---|
| 301 | 344 |  		printk_once(KERN_WARNING "%s calls setitimer() with new_value NULL pointer." | 
|---|
| .. | .. | 
|---|
| 307 | 350 |  	if (error || !ovalue) | 
|---|
| 308 | 351 |  		return error; | 
|---|
| 309 | 352 |   | 
|---|
| 310 |  | -	if (copy_to_user(ovalue, &get_buffer, sizeof(get_buffer)))  | 
|---|
 | 353 | +	if (put_itimerval(ovalue, &get_buffer))  | 
|---|
| 311 | 354 |  		return -EFAULT; | 
|---|
| 312 | 355 |  	return 0; | 
|---|
| 313 | 356 |  } | 
|---|
| 314 | 357 |   | 
|---|
| 315 |  | -#ifdef CONFIG_COMPAT  | 
|---|
| 316 |  | -COMPAT_SYSCALL_DEFINE3(setitimer, int, which,  | 
|---|
| 317 |  | -		       struct compat_itimerval __user *, in,  | 
|---|
| 318 |  | -		       struct compat_itimerval __user *, out)  | 
|---|
 | 358 | +#if defined(CONFIG_COMPAT) || defined(CONFIG_ALPHA)  | 
|---|
 | 359 | +static int get_old_itimerval32(struct itimerspec64 *o, const struct old_itimerval32 __user *i)  | 
|---|
| 319 | 360 |  { | 
|---|
| 320 |  | -	struct itimerval kin, kout;  | 
|---|
 | 361 | +	struct old_itimerval32 v32;  | 
|---|
 | 362 | +  | 
|---|
 | 363 | +	if (copy_from_user(&v32, i, sizeof(struct old_itimerval32)))  | 
|---|
 | 364 | +		return -EFAULT;  | 
|---|
 | 365 | +  | 
|---|
 | 366 | +	/* Validate the timevals in value.  */  | 
|---|
 | 367 | +	if (!timeval_valid(&v32.it_value) ||  | 
|---|
 | 368 | +	    !timeval_valid(&v32.it_interval))  | 
|---|
 | 369 | +		return -EINVAL;  | 
|---|
 | 370 | +  | 
|---|
 | 371 | +	o->it_interval.tv_sec = v32.it_interval.tv_sec;  | 
|---|
 | 372 | +	o->it_interval.tv_nsec = v32.it_interval.tv_usec * NSEC_PER_USEC;  | 
|---|
 | 373 | +	o->it_value.tv_sec = v32.it_value.tv_sec;  | 
|---|
 | 374 | +	o->it_value.tv_nsec = v32.it_value.tv_usec * NSEC_PER_USEC;  | 
|---|
 | 375 | +	return 0;  | 
|---|
 | 376 | +}  | 
|---|
 | 377 | +  | 
|---|
 | 378 | +COMPAT_SYSCALL_DEFINE3(setitimer, int, which,  | 
|---|
 | 379 | +		       struct old_itimerval32 __user *, value,  | 
|---|
 | 380 | +		       struct old_itimerval32 __user *, ovalue)  | 
|---|
 | 381 | +{  | 
|---|
 | 382 | +	struct itimerspec64 set_buffer, get_buffer;  | 
|---|
| 321 | 383 |  	int error; | 
|---|
| 322 | 384 |   | 
|---|
| 323 |  | -	if (in) {  | 
|---|
| 324 |  | -		if (get_compat_itimerval(&kin, in))  | 
|---|
| 325 |  | -			return -EFAULT;  | 
|---|
 | 385 | +	if (value) {  | 
|---|
 | 386 | +		error = get_old_itimerval32(&set_buffer, value);  | 
|---|
 | 387 | +		if (error)  | 
|---|
 | 388 | +			return error;  | 
|---|
| 326 | 389 |  	} else { | 
|---|
| 327 |  | -		memset(&kin, 0, sizeof(kin));  | 
|---|
 | 390 | +		memset(&set_buffer, 0, sizeof(set_buffer));  | 
|---|
 | 391 | +		printk_once(KERN_WARNING "%s calls setitimer() with new_value NULL pointer."  | 
|---|
 | 392 | +			    " Misfeature support will be removed\n",  | 
|---|
 | 393 | +			    current->comm);  | 
|---|
| 328 | 394 |  	} | 
|---|
| 329 | 395 |   | 
|---|
| 330 |  | -	error = do_setitimer(which, &kin, out ? &kout : NULL);  | 
|---|
| 331 |  | -	if (error || !out)  | 
|---|
 | 396 | +	error = do_setitimer(which, &set_buffer, ovalue ? &get_buffer : NULL);  | 
|---|
 | 397 | +	if (error || !ovalue)  | 
|---|
| 332 | 398 |  		return error; | 
|---|
| 333 |  | -	if (put_compat_itimerval(out, &kout))  | 
|---|
 | 399 | +	if (put_old_itimerval32(ovalue, &get_buffer))  | 
|---|
| 334 | 400 |  		return -EFAULT; | 
|---|
| 335 | 401 |  	return 0; | 
|---|
| 336 | 402 |  } | 
|---|