|
@@ -213,82 +213,6 @@ int compat_convert_timespec(struct timespec __user **kts,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static long compat_nanosleep_restart(struct restart_block *restart)
|
|
|
-{
|
|
|
- struct compat_timespec __user *rmtp;
|
|
|
- struct timespec rmt;
|
|
|
- mm_segment_t oldfs;
|
|
|
- long ret;
|
|
|
-
|
|
|
- restart->nanosleep.rmtp = (struct timespec __user *) &rmt;
|
|
|
- oldfs = get_fs();
|
|
|
- set_fs(KERNEL_DS);
|
|
|
- ret = hrtimer_nanosleep_restart(restart);
|
|
|
- set_fs(oldfs);
|
|
|
-
|
|
|
- if (ret == -ERESTART_RESTARTBLOCK) {
|
|
|
- rmtp = restart->nanosleep.compat_rmtp;
|
|
|
-
|
|
|
- if (rmtp && compat_put_timespec(&rmt, rmtp))
|
|
|
- return -EFAULT;
|
|
|
- }
|
|
|
-
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp,
|
|
|
- struct compat_timespec __user *, rmtp)
|
|
|
-{
|
|
|
- struct timespec tu, rmt;
|
|
|
- struct timespec64 tu64;
|
|
|
- mm_segment_t oldfs;
|
|
|
- long ret;
|
|
|
-
|
|
|
- if (compat_get_timespec(&tu, rqtp))
|
|
|
- return -EFAULT;
|
|
|
-
|
|
|
- tu64 = timespec_to_timespec64(tu);
|
|
|
- if (!timespec64_valid(&tu64))
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- oldfs = get_fs();
|
|
|
- set_fs(KERNEL_DS);
|
|
|
- current->restart_block.nanosleep.rmtp =
|
|
|
- rmtp ? (struct timespec __user *)&rmt : NULL;
|
|
|
- ret = hrtimer_nanosleep(&tu64, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
|
|
|
- set_fs(oldfs);
|
|
|
-
|
|
|
- /*
|
|
|
- * hrtimer_nanosleep() can only return 0 or
|
|
|
- * -ERESTART_RESTARTBLOCK here because:
|
|
|
- *
|
|
|
- * - we call it with HRTIMER_MODE_REL and therefor exclude the
|
|
|
- * -ERESTARTNOHAND return path.
|
|
|
- *
|
|
|
- * - we supply the rmtp argument from the task stack (due to
|
|
|
- * the necessary compat conversion. So the update cannot
|
|
|
- * fail, which excludes the -EFAULT return path as well. If
|
|
|
- * it fails nevertheless we have a bigger problem and wont
|
|
|
- * reach this place anymore.
|
|
|
- *
|
|
|
- * - if the return value is 0, we do not have to update rmtp
|
|
|
- * because there is no remaining time.
|
|
|
- *
|
|
|
- * We check for -ERESTART_RESTARTBLOCK nevertheless if the
|
|
|
- * core implementation decides to return random nonsense.
|
|
|
- */
|
|
|
- if (ret == -ERESTART_RESTARTBLOCK) {
|
|
|
- struct restart_block *restart = ¤t->restart_block;
|
|
|
-
|
|
|
- restart->fn = compat_nanosleep_restart;
|
|
|
- restart->nanosleep.compat_rmtp = rmtp;
|
|
|
-
|
|
|
- if (rmtp && compat_put_timespec(&rmt, rmtp))
|
|
|
- return -EFAULT;
|
|
|
- }
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
static inline long get_compat_itimerval(struct itimerval *o,
|
|
|
struct compat_itimerval __user *i)
|
|
|
{
|
|
@@ -821,61 +745,6 @@ COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock,
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-static long compat_clock_nanosleep_restart(struct restart_block *restart)
|
|
|
-{
|
|
|
- long err;
|
|
|
- mm_segment_t oldfs;
|
|
|
- struct timespec tu;
|
|
|
- struct compat_timespec __user *rmtp = restart->nanosleep.compat_rmtp;
|
|
|
-
|
|
|
- restart->nanosleep.rmtp = (struct timespec __user *) &tu;
|
|
|
- oldfs = get_fs();
|
|
|
- set_fs(KERNEL_DS);
|
|
|
- err = clock_nanosleep_restart(restart);
|
|
|
- set_fs(oldfs);
|
|
|
-
|
|
|
- if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
|
|
|
- compat_put_timespec(&tu, rmtp))
|
|
|
- return -EFAULT;
|
|
|
-
|
|
|
- if (err == -ERESTART_RESTARTBLOCK) {
|
|
|
- restart->fn = compat_clock_nanosleep_restart;
|
|
|
- restart->nanosleep.compat_rmtp = rmtp;
|
|
|
- }
|
|
|
- return err;
|
|
|
-}
|
|
|
-
|
|
|
-COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
|
|
|
- struct compat_timespec __user *, rqtp,
|
|
|
- struct compat_timespec __user *, rmtp)
|
|
|
-{
|
|
|
- long err;
|
|
|
- mm_segment_t oldfs;
|
|
|
- struct timespec in, out;
|
|
|
- struct restart_block *restart;
|
|
|
-
|
|
|
- if (compat_get_timespec(&in, rqtp))
|
|
|
- return -EFAULT;
|
|
|
-
|
|
|
- oldfs = get_fs();
|
|
|
- set_fs(KERNEL_DS);
|
|
|
- err = sys_clock_nanosleep(which_clock, flags,
|
|
|
- (struct timespec __user *) &in,
|
|
|
- (struct timespec __user *) &out);
|
|
|
- set_fs(oldfs);
|
|
|
-
|
|
|
- if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
|
|
|
- compat_put_timespec(&out, rmtp))
|
|
|
- return -EFAULT;
|
|
|
-
|
|
|
- if (err == -ERESTART_RESTARTBLOCK) {
|
|
|
- restart = ¤t->restart_block;
|
|
|
- restart->fn = compat_clock_nanosleep_restart;
|
|
|
- restart->nanosleep.compat_rmtp = rmtp;
|
|
|
- }
|
|
|
- return err;
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* We currently only need the following fields from the sigevent
|
|
|
* structure: sigev_value, sigev_signo, sig_notify and (sometimes
|