diff options
| -rw-r--r-- | include/linux/hrtimer.h | 2 | ||||
| -rw-r--r-- | kernel/hrtimer.c | 51 | ||||
| -rw-r--r-- | kernel/posix-timers.c | 17 | 
3 files changed, 31 insertions, 39 deletions
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 600fc3bcf63..1ad56a7b2f7 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -316,7 +316,7 @@ static inline u64 hrtimer_forward_now(struct hrtimer *timer,  /* Precise sleep: */  extern long hrtimer_nanosleep(struct timespec *rqtp, -			      struct timespec *rmtp, +			      struct timespec __user *rmtp,  			      const enum hrtimer_mode mode,  			      const clockid_t clockid);  extern long hrtimer_nanosleep_restart(struct restart_block *restart_block); diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 668f3967eb3..355085f0896 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -1319,11 +1319,26 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod  	return t->task == NULL;  } +static int update_rmtp(struct hrtimer *timer, struct timespec __user *rmtp) +{ +	struct timespec rmt; +	ktime_t rem; + +	rem = ktime_sub(timer->expires, timer->base->get_time()); +	if (rem.tv64 <= 0) +		return 0; +	rmt = ktime_to_timespec(rem); + +	if (copy_to_user(rmtp, &rmt, sizeof(*rmtp))) +		return -EFAULT; + +	return 1; +} +  long __sched hrtimer_nanosleep_restart(struct restart_block *restart)  {  	struct hrtimer_sleeper t; -	struct timespec *rmtp; -	ktime_t time; +	struct timespec __user  *rmtp;  	restart->fn = do_no_restart_syscall; @@ -1333,12 +1348,11 @@ long __sched hrtimer_nanosleep_restart(struct restart_block *restart)  	if (do_nanosleep(&t, HRTIMER_MODE_ABS))  		return 0; -	rmtp = (struct timespec *)restart->arg1; +	rmtp = (struct timespec __user *)restart->arg1;  	if (rmtp) { -		time = ktime_sub(t.timer.expires, t.timer.base->get_time()); -		if (time.tv64 <= 0) -			return 0; -		*rmtp = ktime_to_timespec(time); +		int ret = update_rmtp(&t.timer, rmtp); +		if (ret <= 0) +			return ret;  	}  	restart->fn = hrtimer_nanosleep_restart; @@ -1347,12 +1361,11 @@ long __sched hrtimer_nanosleep_restart(struct restart_block *restart)  	return -ERESTART_RESTARTBLOCK;  } -long hrtimer_nanosleep(struct timespec *rqtp, struct timespec *rmtp, +long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,  		       const enum hrtimer_mode mode, const clockid_t clockid)  {  	struct restart_block *restart;  	struct hrtimer_sleeper t; -	ktime_t rem;  	hrtimer_init(&t.timer, clockid, mode);  	t.timer.expires = timespec_to_ktime(*rqtp); @@ -1364,10 +1377,9 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec *rmtp,  		return -ERESTARTNOHAND;  	if (rmtp) { -		rem = ktime_sub(t.timer.expires, t.timer.base->get_time()); -		if (rem.tv64 <= 0) -			return 0; -		*rmtp = ktime_to_timespec(rem); +		int ret = update_rmtp(&t.timer, rmtp); +		if (ret <= 0) +			return ret;  	}  	restart = ¤t_thread_info()->restart_block; @@ -1383,8 +1395,7 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec *rmtp,  asmlinkage long  sys_nanosleep(struct timespec __user *rqtp, struct timespec __user *rmtp)  { -	struct timespec tu, rmt; -	int ret; +	struct timespec tu;  	if (copy_from_user(&tu, rqtp, sizeof(tu)))  		return -EFAULT; @@ -1392,15 +1403,7 @@ sys_nanosleep(struct timespec __user *rqtp, struct timespec __user *rmtp)  	if (!timespec_valid(&tu))  		return -EINVAL; -	ret = hrtimer_nanosleep(&tu, rmtp ? &rmt : NULL, HRTIMER_MODE_REL, -				CLOCK_MONOTONIC); - -	if (ret && rmtp) { -		if (copy_to_user(rmtp, &rmt, sizeof(*rmtp))) -			return -EFAULT; -	} - -	return ret; +	return hrtimer_nanosleep(&tu, rmtp, HRTIMER_MODE_REL, CLOCK_MONOTONIC);  }  /* diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index ce268966007..022c9c3cee6 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -982,20 +982,9 @@ sys_clock_getres(const clockid_t which_clock, struct timespec __user *tp)  static int common_nsleep(const clockid_t which_clock, int flags,  			 struct timespec *tsave, struct timespec __user *rmtp)  { -	struct timespec rmt; -	int ret; - -	ret = hrtimer_nanosleep(tsave, rmtp ? &rmt : NULL, -				flags & TIMER_ABSTIME ? -				HRTIMER_MODE_ABS : HRTIMER_MODE_REL, -				which_clock); - -	if (ret && rmtp) { -		if (copy_to_user(rmtp, &rmt, sizeof(*rmtp))) -			return -EFAULT; -	} - -	return ret; +	return hrtimer_nanosleep(tsave, rmtp, flags & TIMER_ABSTIME ? +				 HRTIMER_MODE_ABS : HRTIMER_MODE_REL, +				 which_clock);  }  asmlinkage long  |