int get_compat_itimerspec(struct itimerspec *dst, const struct compat_itimerspec __user *src) { if (get_compat_timespec(&dst->it_interval, &src->it_interval) || get_compat_timespec(&dst->it_value, &src->it_value)) return -EFAULT; return 0; }
asmlinkage long compat_sys_utimensat(unsigned int dfd, const char __user *filename, struct compat_timespec __user *t, int flags) { struct timespec tv[2]; if (t) { if (get_compat_timespec(&tv[0], &t[0]) || get_compat_timespec(&tv[1], &t[1])) return -EFAULT; if (tv[0].tv_nsec == UTIME_OMIT && tv[1].tv_nsec == UTIME_OMIT) return 0; } return do_utimes(dfd, filename, t ? tv : NULL, flags); }
asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg, unsigned int vlen, unsigned int flags, struct compat_timespec __user *timeout) { int datagrams; struct timespec ktspec; if (COMPAT_USE_64BIT_TIME) return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, flags | MSG_CMSG_COMPAT, (struct timespec *) timeout); if (timeout == NULL) return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, flags | MSG_CMSG_COMPAT, NULL); if (get_compat_timespec(&ktspec, timeout)) return -EFAULT; datagrams = __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, flags | MSG_CMSG_COMPAT, &ktspec); if (datagrams > 0 && put_compat_timespec(&ktspec, timeout)) datagrams = -EFAULT; return datagrams; }
asmlinkage long compat_sys_io_getevents(aio_context_t ctx_id, unsigned long min_nr, unsigned long nr, struct io_event __user *events, struct compat_timespec __user *timeout) { long ret; struct timespec t; struct timespec __user *ut = NULL; ret = -EFAULT; if (unlikely(!access_ok(VERIFY_WRITE, events, nr * sizeof(struct io_event)))) goto out; if (timeout) { if (get_compat_timespec(&t, timeout)) goto out; ut = compat_alloc_user_space(sizeof(*ut)); if (copy_to_user(ut, &t, sizeof(t)) ) goto out; } ret = sys_io_getevents(ctx_id, min_nr, nr, events, ut); out: return ret; }
asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp, struct compat_timespec __user *rmtp) { struct timespec tu, rmt; mm_segment_t oldfs; long ret; if (get_compat_timespec(&tu, rqtp)) return -EFAULT; if (!timespec_valid(&tu)) return -EINVAL; oldfs = get_fs(); set_fs(KERNEL_DS); ret = hrtimer_nanosleep(&tu, rmtp ? (struct timespec __user *)&rmt : NULL, HRTIMER_MODE_REL, CLOCK_MONOTONIC); set_fs(oldfs); if (ret) { struct restart_block *restart = ¤t_thread_info()->restart_block; restart->fn = compat_nanosleep_restart; restart->nanosleep.compat_rmtp = rmtp; if (rmtp && put_compat_timespec(&rmt, rmtp)) return -EFAULT; } return ret; }
asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp, struct compat_timespec __user *rmtp) { struct timespec t; struct restart_block *restart; unsigned long expire; if (get_compat_timespec(&t, rqtp)) return -EFAULT; if ((t.tv_nsec >= 1000000000L) || (t.tv_nsec < 0) || (t.tv_sec < 0)) return -EINVAL; expire = timespec_to_jiffies(&t) + (t.tv_sec || t.tv_nsec); expire = schedule_timeout_interruptible(expire); if (expire == 0) return 0; if (rmtp) { jiffies_to_timespec(expire, &t); if (put_compat_timespec(&t, rmtp)) return -EFAULT; } restart = ¤t_thread_info()->restart_block; restart->fn = compat_nanosleep_restart; restart->arg0 = jiffies + expire; restart->arg1 = (unsigned long) rmtp; return -ERESTART_RESTARTBLOCK; }
asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val, struct compat_timespec __user *utime, u32 __user *uaddr2, u32 val3) { struct timespec ts; ktime_t t, *tp = NULL; int val2 = 0; int cmd = op & FUTEX_CMD_MASK; if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI || cmd == FUTEX_WAIT_BITSET || cmd == FUTEX_WAIT_REQUEUE_PI)) { if (get_compat_timespec(&ts, utime)) return -EFAULT; if (!timespec_valid(&ts)) return -EINVAL; t = timespec_to_ktime(ts); if (cmd == FUTEX_WAIT) t = ktime_add_safe(ktime_get(), t); tp = &t; } if (cmd == FUTEX_REQUEUE || cmd == FUTEX_CMP_REQUEUE || cmd == FUTEX_CMP_REQUEUE_PI || cmd == FUTEX_WAKE_OP) val2 = (int) (unsigned long) utime; return do_futex(uaddr, op, val, tp, uaddr2, val2, val3); }
int compat_get_timespec(struct timespec *ts, const void __user *uts) { if (COMPAT_USE_64BIT_TIME) return copy_from_user(ts, uts, sizeof *ts) ? -EFAULT : 0; else return get_compat_timespec(ts, uts); }
asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val, struct compat_timespec __user *utime, u32 __user *uaddr2, u32 val3) { struct timespec t; unsigned long timeout = MAX_SCHEDULE_TIMEOUT; int val2 = 0; if (utime && (op == FUTEX_WAIT || op == FUTEX_LOCK_PI)) { if (get_compat_timespec(&t, utime)) return -EFAULT; if (!timespec_valid(&t)) return -EINVAL; if (op == FUTEX_WAIT) timeout = timespec_to_jiffies(&t) + 1; else { timeout = t.tv_sec; val2 = t.tv_nsec; } } if (op == FUTEX_REQUEUE || op == FUTEX_CMP_REQUEUE) val2 = (int) (unsigned long) utime; return do_futex(uaddr, op, val, timeout, uaddr2, val2, val3); }
static int sis33_get_compat_acq_desc(struct sis33_acq_desc __user *desc, struct sis33_compat_acq_desc __user *compat_desc) { struct timespec ts; u32 uint; int err; if (!access_ok(VERIFY_READ, compat_desc, sizeof(*compat_desc)) || !access_ok(VERIFY_WRITE, desc, sizeof(*desc))) return -EFAULT; err = 0; err |= __get_user(uint, &compat_desc->segment); err |= __put_user(uint, &desc->segment); err |= __get_user(uint, &compat_desc->nr_events); err |= __put_user(uint, &desc->nr_events); err |= __get_user(uint, &compat_desc->ev_length); err |= __put_user(uint, &desc->ev_length); err |= __get_user(uint, &compat_desc->flags); err |= __put_user(uint, &desc->flags); err |= get_compat_timespec(&ts, &compat_desc->timeout); err |= copy_to_user(&desc->timeout, &ts, sizeof(ts)); if (err) return -EFAULT; return 0; }
long compat_get_v4l2_event_data(struct v4l2_event __user *pdata, struct v4l2_event32 __user *pdata32) { long ret = 0; compat_uint_t type; compat_uint_t pending; compat_uint_t sequence; struct timespec timestamp; compat_uint_t id; if (!access_ok(VERIFY_READ, pdata32, sizeof(struct v4l2_event32))) return -EFAULT; ret = get_user(type, &pdata32->type); ret |= put_user(type, &pdata->type); ret |= copy_in_user(&pdata->u, &pdata32->u, sizeof(pdata->u)); ret |= get_user(pending, &pdata32->pending); ret |= put_user(pending, &pdata->pending); ret |= get_user(sequence, &pdata32->sequence); ret |= put_user(sequence, &pdata->sequence); ret |= get_compat_timespec(×tamp, &pdata32->timestamp); /* ret |= put_compat_timespec(×tamp, &pdata->timestamp); */ ret |= copy_to_user(&pdata->timestamp, ×tamp, sizeof(timestamp)); ret |= get_user(id, &pdata32->id); ret |= put_user(id, &pdata->id); ret |= copy_in_user(pdata->reserved, pdata32->reserved, 8 * sizeof(__u32)); return ret; }
static int compat_prepare_timeout(struct timespec __user * *p, const struct compat_timespec __user *u) { struct timespec ts; if (!u) { *p = NULL; return 0; } *p = compat_alloc_user_space(sizeof(ts)); if (get_compat_timespec(&ts, u) || copy_to_user(*p, &ts, sizeof(ts))) return -EFAULT; return 0; }
long compat_sys_semtimedop(int semid, struct sembuf __user *tsems, unsigned nsops, const struct compat_timespec __user *timeout) { struct timespec __user *ts64 = NULL; if (timeout) { struct timespec ts; ts64 = compat_alloc_user_space(sizeof(*ts64)); if (get_compat_timespec(&ts, timeout)) return -EFAULT; if (copy_to_user(ts64, &ts, sizeof(ts))) return -EFAULT; } return sys_semtimedop(semid, tsems, nsops, ts64); }
long compat_get_v4l2_event_data(struct v4l2_event *kp, struct v4l2_event32 __user *up) { long ret = 0; ret = get_user(kp->type, &up->type); ret |= copy_in_user(&kp->u, &up->u, sizeof(kp->u)); ret |= get_user(kp->pending, &up->pending); ret |= get_user(kp->sequence, &up->sequence); ret |= get_compat_timespec(&kp->timestamp, &up->timestamp); ret |= get_user(kp->id, &up->id); ret |= copy_in_user(kp->reserved, up->reserved, 8 * sizeof(__u32)); return ret; }
static int sis33_get_compat_acq_list(struct sis33_acq_list __user *list, struct sis33_compat_acq_list __user *compat_list, struct sis33_acq *acqs) { struct sis33_compat_acq __user *compat_acqs; struct timeval ktime; struct timespec ts; compat_uptr_t uptr; u32 n_acqs; u32 uint; int err; int i; if (!access_ok(VERIFY_READ, compat_list, sizeof(*compat_list)) || !access_ok(VERIFY_WRITE, list, sizeof(*list))) return -EFAULT; err = 0; err |= __get_user(n_acqs, &compat_list->n_acqs); err |= __put_user(n_acqs, &list->n_acqs); err |= __get_user(uint, &compat_list->segment); err |= __put_user(uint, &list->segment); err |= __get_user(uint, &compat_list->channel); err |= __put_user(uint, &list->channel); err |= __get_user(uint, &compat_list->flags); err |= __put_user(uint, &list->flags); err |= __put_user(acqs, &list->acqs); err |= get_compat_timespec(&ts, &compat_list->timeout); err |= copy_to_user(&list->timeout, &ts, sizeof(ts)); err |= __get_user(ktime.tv_sec, &compat_list->endtime.tv_sec); err |= __put_user(ktime.tv_sec, &list->endtime.tv_sec); err |= __get_user(ktime.tv_usec, &compat_list->endtime.tv_usec); err |= __put_user(ktime.tv_usec, &list->endtime.tv_usec); err |= __get_user(uptr, &compat_list->acqs); compat_acqs = compat_ptr(uptr); if (err) return -EFAULT; for (i = 0; i < n_acqs; i++) { err = sis33_get_compat_acq(&list->acqs[i], &compat_acqs[i]); if (err) return err; } return 0; }
asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, int val, struct compat_timespec __user *utime, u32 __user *uaddr2, int val3) { struct timespec t; unsigned long timeout = MAX_SCHEDULE_TIMEOUT; int val2 = 0; if ((op == FUTEX_WAIT) && utime) { if (get_compat_timespec(&t, utime)) return -EFAULT; timeout = timespec_to_jiffies(&t) + 1; } if (op >= FUTEX_REQUEUE) val2 = (int) (unsigned long) utime; return do_futex((unsigned long)uaddr, op, val, timeout, (unsigned long)uaddr2, val2, val3); }