mirror of
https://github.com/fail0verflow/switch-linux.git
synced 2025-05-04 02:34:21 -04:00
posix-timers: Take compat timer_settime(2) to native one
... and get rid of set_fs() in there Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: John Stultz <john.stultz@linaro.org> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/20170607084241.28657-10-viro@ZenIV.linux.org.uk
This commit is contained in:
parent
3a4d44b616
commit
1acbe7708b
3 changed files with 65 additions and 48 deletions
|
@ -635,29 +635,6 @@ COMPAT_SYSCALL_DEFINE3(timer_create, clockid_t, which_clock,
|
||||||
return sys_timer_create(which_clock, event, created_timer_id);
|
return sys_timer_create(which_clock, event, created_timer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
COMPAT_SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags,
|
|
||||||
struct compat_itimerspec __user *, new,
|
|
||||||
struct compat_itimerspec __user *, old)
|
|
||||||
{
|
|
||||||
long err;
|
|
||||||
mm_segment_t oldfs;
|
|
||||||
struct itimerspec newts, oldts;
|
|
||||||
|
|
||||||
if (!new)
|
|
||||||
return -EINVAL;
|
|
||||||
if (get_compat_itimerspec(&newts, new))
|
|
||||||
return -EFAULT;
|
|
||||||
oldfs = get_fs();
|
|
||||||
set_fs(KERNEL_DS);
|
|
||||||
err = sys_timer_settime(timer_id, flags,
|
|
||||||
(struct itimerspec __user *) &newts,
|
|
||||||
(struct itimerspec __user *) &oldts);
|
|
||||||
set_fs(oldfs);
|
|
||||||
if (!err && old && put_compat_itimerspec(old, &oldts))
|
|
||||||
return -EFAULT;
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
COMPAT_SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id,
|
COMPAT_SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id,
|
||||||
struct compat_itimerspec __user *, setting)
|
struct compat_itimerspec __user *, setting)
|
||||||
{
|
{
|
||||||
|
|
|
@ -42,6 +42,7 @@ SYS_NI(setitimer);
|
||||||
SYS_NI(alarm);
|
SYS_NI(alarm);
|
||||||
#endif
|
#endif
|
||||||
COMPAT_SYS_NI(clock_adjtime);
|
COMPAT_SYS_NI(clock_adjtime);
|
||||||
|
COMPAT_SYS_NI(timer_settime);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC
|
* We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC
|
||||||
|
|
|
@ -819,31 +819,21 @@ int common_timer_set(struct k_itimer *timr, int flags,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set a POSIX.1b interval timer */
|
static int do_timer_settime(timer_t timer_id, int flags,
|
||||||
SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags,
|
struct itimerspec64 *new_spec64,
|
||||||
const struct itimerspec __user *, new_setting,
|
struct itimerspec64 *old_spec64)
|
||||||
struct itimerspec __user *, old_setting)
|
|
||||||
{
|
{
|
||||||
struct itimerspec64 new_spec64, old_spec64;
|
const struct k_clock *kc;
|
||||||
struct itimerspec64 *rtn = old_setting ? &old_spec64 : NULL;
|
|
||||||
struct itimerspec new_spec, old_spec;
|
|
||||||
struct k_itimer *timr;
|
struct k_itimer *timr;
|
||||||
unsigned long flag;
|
unsigned long flag;
|
||||||
const struct k_clock *kc;
|
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
if (!new_setting)
|
if (!timespec64_valid(&new_spec64->it_interval) ||
|
||||||
|
!timespec64_valid(&new_spec64->it_value))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (copy_from_user(&new_spec, new_setting, sizeof (new_spec)))
|
if (old_spec64)
|
||||||
return -EFAULT;
|
memset(old_spec64, 0, sizeof(*old_spec64));
|
||||||
new_spec64 = itimerspec_to_itimerspec64(&new_spec);
|
|
||||||
|
|
||||||
if (!timespec64_valid(&new_spec64.it_interval) ||
|
|
||||||
!timespec64_valid(&new_spec64.it_value))
|
|
||||||
return -EINVAL;
|
|
||||||
if (rtn)
|
|
||||||
memset(rtn, 0, sizeof(*rtn));
|
|
||||||
retry:
|
retry:
|
||||||
timr = lock_timer(timer_id, &flag);
|
timr = lock_timer(timer_id, &flag);
|
||||||
if (!timr)
|
if (!timr)
|
||||||
|
@ -853,22 +843,71 @@ retry:
|
||||||
if (WARN_ON_ONCE(!kc || !kc->timer_set))
|
if (WARN_ON_ONCE(!kc || !kc->timer_set))
|
||||||
error = -EINVAL;
|
error = -EINVAL;
|
||||||
else
|
else
|
||||||
error = kc->timer_set(timr, flags, &new_spec64, rtn);
|
error = kc->timer_set(timr, flags, new_spec64, old_spec64);
|
||||||
|
|
||||||
unlock_timer(timr, flag);
|
unlock_timer(timr, flag);
|
||||||
if (error == TIMER_RETRY) {
|
if (error == TIMER_RETRY) {
|
||||||
rtn = NULL; // We already got the old time...
|
old_spec64 = NULL; // We already got the old time...
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
old_spec = itimerspec64_to_itimerspec(&old_spec64);
|
|
||||||
if (old_setting && !error &&
|
|
||||||
copy_to_user(old_setting, &old_spec, sizeof (old_spec)))
|
|
||||||
error = -EFAULT;
|
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set a POSIX.1b interval timer */
|
||||||
|
SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags,
|
||||||
|
const struct itimerspec __user *, new_setting,
|
||||||
|
struct itimerspec __user *, old_setting)
|
||||||
|
{
|
||||||
|
struct itimerspec64 new_spec64, old_spec64;
|
||||||
|
struct itimerspec64 *rtn = old_setting ? &old_spec64 : NULL;
|
||||||
|
struct itimerspec new_spec;
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
if (!new_setting)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (copy_from_user(&new_spec, new_setting, sizeof (new_spec)))
|
||||||
|
return -EFAULT;
|
||||||
|
new_spec64 = itimerspec_to_itimerspec64(&new_spec);
|
||||||
|
|
||||||
|
error = do_timer_settime(timer_id, flags, &new_spec64, rtn);
|
||||||
|
if (!error && old_setting) {
|
||||||
|
struct itimerspec old_spec;
|
||||||
|
old_spec = itimerspec64_to_itimerspec(&old_spec64);
|
||||||
|
if (copy_to_user(old_setting, &old_spec, sizeof (old_spec)))
|
||||||
|
error = -EFAULT;
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_COMPAT
|
||||||
|
COMPAT_SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags,
|
||||||
|
struct compat_itimerspec __user *, new,
|
||||||
|
struct compat_itimerspec __user *, old)
|
||||||
|
{
|
||||||
|
struct itimerspec64 new_spec64, old_spec64;
|
||||||
|
struct itimerspec64 *rtn = old ? &old_spec64 : NULL;
|
||||||
|
struct itimerspec new_spec;
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
if (!new)
|
||||||
|
return -EINVAL;
|
||||||
|
if (get_compat_itimerspec(&new_spec, new))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
new_spec64 = itimerspec_to_itimerspec64(&new_spec);
|
||||||
|
error = do_timer_settime(timer_id, flags, &new_spec64, rtn);
|
||||||
|
if (!error && old) {
|
||||||
|
struct itimerspec old_spec;
|
||||||
|
old_spec = itimerspec64_to_itimerspec(&old_spec64);
|
||||||
|
if (put_compat_itimerspec(old, &old_spec))
|
||||||
|
error = -EFAULT;
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int common_timer_del(struct k_itimer *timer)
|
int common_timer_del(struct k_itimer *timer)
|
||||||
{
|
{
|
||||||
const struct k_clock *kc = timer->kclock;
|
const struct k_clock *kc = timer->kclock;
|
||||||
|
|
Loading…
Add table
Reference in a new issue