Merge branch 'x86-x32-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull compat time conversion changes from Peter Anvin:
 "Despite the branch name this is really neither an x86 nor an
  x32-specific patchset, although it the implementation of the
  discussions that followed the x32 security hole a few months ago.

  This removes get/put_compat_timespec/val() and replaces them with
  compat_get/put_timespec/val() which are savvy as to the current status
  of COMPAT_USE_64BIT_TIME.

  It removes several unused and/or incorrect/misleading functions (like
  compat_put_timeval_convert which doesn't in fact do any conversion)
  and also replaces several open-coded implementations what is now
  called compat_convert_timespec() with that function"

* 'x86-x32-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  compat: Fix sparse address space warnings
  compat: Get rid of (get|put)_compat_time(val|spec)
This commit is contained in:
Linus Torvalds 2014-04-02 12:51:41 -07:00
Родитель c6f21243ce dce44e03b0
Коммит 7125764c5d
7 изменённых файлов: 77 добавлений и 99 удалений

Просмотреть файл

@ -733,7 +733,7 @@ static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *u
copy_to_user(&up->u, &kp->u, sizeof(kp->u)) || copy_to_user(&up->u, &kp->u, sizeof(kp->u)) ||
put_user(kp->pending, &up->pending) || put_user(kp->pending, &up->pending) ||
put_user(kp->sequence, &up->sequence) || put_user(kp->sequence, &up->sequence) ||
put_compat_timespec(&kp->timestamp, &up->timestamp) || compat_put_timespec(&kp->timestamp, &up->timestamp) ||
put_user(kp->id, &up->id) || put_user(kp->id, &up->id) ||
copy_to_user(up->reserved, kp->reserved, 8 * sizeof(__u32))) copy_to_user(up->reserved, kp->reserved, 8 * sizeof(__u32)))
return -EFAULT; return -EFAULT;

Просмотреть файл

@ -92,8 +92,8 @@ COMPAT_SYSCALL_DEFINE4(utimensat, unsigned int, dfd, const char __user *, filena
struct timespec tv[2]; struct timespec tv[2];
if (t) { if (t) {
if (get_compat_timespec(&tv[0], &t[0]) || if (compat_get_timespec(&tv[0], &t[0]) ||
get_compat_timespec(&tv[1], &t[1])) compat_get_timespec(&tv[1], &t[1]))
return -EFAULT; return -EFAULT;
if (tv[0].tv_nsec == UTIME_OMIT && tv[1].tv_nsec == UTIME_OMIT) if (tv[0].tv_nsec == UTIME_OMIT && tv[1].tv_nsec == UTIME_OMIT)
@ -505,7 +505,7 @@ COMPAT_SYSCALL_DEFINE5(io_getevents, compat_aio_context_t, ctx_id,
struct timespec __user *ut = NULL; struct timespec __user *ut = NULL;
if (timeout) { if (timeout) {
if (get_compat_timespec(&t, timeout)) if (compat_get_timespec(&t, timeout))
return -EFAULT; return -EFAULT;
ut = compat_alloc_user_space(sizeof(*ut)); ut = compat_alloc_user_space(sizeof(*ut));

Просмотреть файл

@ -146,27 +146,24 @@ struct compat_sigaction {
compat_sigset_t sa_mask __packed; compat_sigset_t sa_mask __packed;
}; };
/*
* These functions operate strictly on struct compat_time*
*/
extern int get_compat_timespec(struct timespec *,
const struct compat_timespec __user *);
extern int put_compat_timespec(const struct timespec *,
struct compat_timespec __user *);
extern int get_compat_timeval(struct timeval *,
const struct compat_timeval __user *);
extern int put_compat_timeval(const struct timeval *,
struct compat_timeval __user *);
/* /*
* These functions operate on 32- or 64-bit specs depending on * These functions operate on 32- or 64-bit specs depending on
* COMPAT_USE_64BIT_TIME, hence the void user pointer arguments and the * COMPAT_USE_64BIT_TIME, hence the void user pointer arguments.
* naming as compat_get/put_ rather than get/put_compat_.
*/ */
extern int compat_get_timespec(struct timespec *, const void __user *); extern int compat_get_timespec(struct timespec *, const void __user *);
extern int compat_put_timespec(const struct timespec *, void __user *); extern int compat_put_timespec(const struct timespec *, void __user *);
extern int compat_get_timeval(struct timeval *, const void __user *); extern int compat_get_timeval(struct timeval *, const void __user *);
extern int compat_put_timeval(const struct timeval *, void __user *); extern int compat_put_timeval(const struct timeval *, void __user *);
/*
* This function convert a timespec if necessary and returns a *user
* space* pointer. If no conversion is necessary, it returns the
* initial pointer. NULL is a legitimate argument and will always
* output NULL.
*/
extern int compat_convert_timespec(struct timespec __user **,
const void __user *);
struct compat_iovec { struct compat_iovec {
compat_uptr_t iov_base; compat_uptr_t iov_base;
compat_size_t iov_len; compat_size_t iov_len;

Просмотреть файл

@ -753,14 +753,8 @@ COMPAT_SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsems,
unsigned, nsops, unsigned, nsops,
const struct compat_timespec __user *, timeout) const struct compat_timespec __user *, timeout)
{ {
struct timespec __user *ts64 = NULL; struct timespec __user *ts64;
if (timeout) { if (compat_convert_timespec(&ts64, timeout))
struct timespec ts; return -EFAULT;
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); return sys_semtimedop(semid, tsems, nsops, ts64);
} }

Просмотреть файл

@ -64,20 +64,6 @@ COMPAT_SYSCALL_DEFINE4(mq_open, const char __user *, u_name,
return sys_mq_open(u_name, oflag, mode, p); return sys_mq_open(u_name, oflag, mode, p);
} }
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;
}
COMPAT_SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, COMPAT_SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes,
const char __user *, u_msg_ptr, const char __user *, u_msg_ptr,
compat_size_t, msg_len, unsigned int, msg_prio, compat_size_t, msg_len, unsigned int, msg_prio,
@ -85,7 +71,7 @@ COMPAT_SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes,
{ {
struct timespec __user *u_ts; struct timespec __user *u_ts;
if (compat_prepare_timeout(&u_ts, u_abs_timeout)) if (compat_convert_timespec(&u_ts, u_abs_timeout))
return -EFAULT; return -EFAULT;
return sys_mq_timedsend(mqdes, u_msg_ptr, msg_len, return sys_mq_timedsend(mqdes, u_msg_ptr, msg_len,
@ -98,7 +84,8 @@ COMPAT_SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes,
const struct compat_timespec __user *, u_abs_timeout) const struct compat_timespec __user *, u_abs_timeout)
{ {
struct timespec __user *u_ts; struct timespec __user *u_ts;
if (compat_prepare_timeout(&u_ts, u_abs_timeout))
if (compat_convert_timespec(&u_ts, u_abs_timeout))
return -EFAULT; return -EFAULT;
return sys_mq_timedreceive(mqdes, u_msg_ptr, msg_len, return sys_mq_timedreceive(mqdes, u_msg_ptr, msg_len,

Просмотреть файл

@ -30,28 +30,6 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
/*
* Get/set struct timeval with struct timespec on the native side
*/
static int compat_get_timeval_convert(struct timespec *o,
struct compat_timeval __user *i)
{
long usec;
if (get_user(o->tv_sec, &i->tv_sec) ||
get_user(usec, &i->tv_usec))
return -EFAULT;
o->tv_nsec = usec * 1000;
return 0;
}
static int compat_put_timeval_convert(struct compat_timeval __user *o,
struct timeval *i)
{
return (put_user(i->tv_sec, &o->tv_sec) ||
put_user(i->tv_usec, &o->tv_usec)) ? -EFAULT : 0;
}
static int compat_get_timex(struct timex *txc, struct compat_timex __user *utp) static int compat_get_timex(struct timex *txc, struct compat_timex __user *utp)
{ {
memset(txc, 0, sizeof(struct timex)); memset(txc, 0, sizeof(struct timex));
@ -116,7 +94,7 @@ COMPAT_SYSCALL_DEFINE2(gettimeofday, struct compat_timeval __user *, tv,
if (tv) { if (tv) {
struct timeval ktv; struct timeval ktv;
do_gettimeofday(&ktv); do_gettimeofday(&ktv);
if (compat_put_timeval_convert(tv, &ktv)) if (compat_put_timeval(&ktv, tv))
return -EFAULT; return -EFAULT;
} }
if (tz) { if (tz) {
@ -130,59 +108,58 @@ COMPAT_SYSCALL_DEFINE2(gettimeofday, struct compat_timeval __user *, tv,
COMPAT_SYSCALL_DEFINE2(settimeofday, struct compat_timeval __user *, tv, COMPAT_SYSCALL_DEFINE2(settimeofday, struct compat_timeval __user *, tv,
struct timezone __user *, tz) struct timezone __user *, tz)
{ {
struct timespec kts; struct timeval user_tv;
struct timezone ktz; struct timespec new_ts;
struct timezone new_tz;
if (tv) { if (tv) {
if (compat_get_timeval_convert(&kts, tv)) if (compat_get_timeval(&user_tv, tv))
return -EFAULT; return -EFAULT;
new_ts.tv_sec = user_tv.tv_sec;
new_ts.tv_nsec = user_tv.tv_usec * NSEC_PER_USEC;
} }
if (tz) { if (tz) {
if (copy_from_user(&ktz, tz, sizeof(ktz))) if (copy_from_user(&new_tz, tz, sizeof(*tz)))
return -EFAULT; return -EFAULT;
} }
return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); return do_sys_settimeofday(tv ? &new_ts : NULL, tz ? &new_tz : NULL);
} }
int get_compat_timeval(struct timeval *tv, const struct compat_timeval __user *ctv) static int __compat_get_timeval(struct timeval *tv, const struct compat_timeval __user *ctv)
{ {
return (!access_ok(VERIFY_READ, ctv, sizeof(*ctv)) || return (!access_ok(VERIFY_READ, ctv, sizeof(*ctv)) ||
__get_user(tv->tv_sec, &ctv->tv_sec) || __get_user(tv->tv_sec, &ctv->tv_sec) ||
__get_user(tv->tv_usec, &ctv->tv_usec)) ? -EFAULT : 0; __get_user(tv->tv_usec, &ctv->tv_usec)) ? -EFAULT : 0;
} }
EXPORT_SYMBOL_GPL(get_compat_timeval);
int put_compat_timeval(const struct timeval *tv, struct compat_timeval __user *ctv) static int __compat_put_timeval(const struct timeval *tv, struct compat_timeval __user *ctv)
{ {
return (!access_ok(VERIFY_WRITE, ctv, sizeof(*ctv)) || return (!access_ok(VERIFY_WRITE, ctv, sizeof(*ctv)) ||
__put_user(tv->tv_sec, &ctv->tv_sec) || __put_user(tv->tv_sec, &ctv->tv_sec) ||
__put_user(tv->tv_usec, &ctv->tv_usec)) ? -EFAULT : 0; __put_user(tv->tv_usec, &ctv->tv_usec)) ? -EFAULT : 0;
} }
EXPORT_SYMBOL_GPL(put_compat_timeval);
int get_compat_timespec(struct timespec *ts, const struct compat_timespec __user *cts) static int __compat_get_timespec(struct timespec *ts, const struct compat_timespec __user *cts)
{ {
return (!access_ok(VERIFY_READ, cts, sizeof(*cts)) || return (!access_ok(VERIFY_READ, cts, sizeof(*cts)) ||
__get_user(ts->tv_sec, &cts->tv_sec) || __get_user(ts->tv_sec, &cts->tv_sec) ||
__get_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0; __get_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
} }
EXPORT_SYMBOL_GPL(get_compat_timespec);
int put_compat_timespec(const struct timespec *ts, struct compat_timespec __user *cts) static int __compat_put_timespec(const struct timespec *ts, struct compat_timespec __user *cts)
{ {
return (!access_ok(VERIFY_WRITE, cts, sizeof(*cts)) || return (!access_ok(VERIFY_WRITE, cts, sizeof(*cts)) ||
__put_user(ts->tv_sec, &cts->tv_sec) || __put_user(ts->tv_sec, &cts->tv_sec) ||
__put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0; __put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
} }
EXPORT_SYMBOL_GPL(put_compat_timespec);
int compat_get_timeval(struct timeval *tv, const void __user *utv) int compat_get_timeval(struct timeval *tv, const void __user *utv)
{ {
if (COMPAT_USE_64BIT_TIME) if (COMPAT_USE_64BIT_TIME)
return copy_from_user(tv, utv, sizeof *tv) ? -EFAULT : 0; return copy_from_user(tv, utv, sizeof *tv) ? -EFAULT : 0;
else else
return get_compat_timeval(tv, utv); return __compat_get_timeval(tv, utv);
} }
EXPORT_SYMBOL_GPL(compat_get_timeval); EXPORT_SYMBOL_GPL(compat_get_timeval);
@ -191,7 +168,7 @@ int compat_put_timeval(const struct timeval *tv, void __user *utv)
if (COMPAT_USE_64BIT_TIME) if (COMPAT_USE_64BIT_TIME)
return copy_to_user(utv, tv, sizeof *tv) ? -EFAULT : 0; return copy_to_user(utv, tv, sizeof *tv) ? -EFAULT : 0;
else else
return put_compat_timeval(tv, utv); return __compat_put_timeval(tv, utv);
} }
EXPORT_SYMBOL_GPL(compat_put_timeval); EXPORT_SYMBOL_GPL(compat_put_timeval);
@ -200,7 +177,7 @@ int compat_get_timespec(struct timespec *ts, const void __user *uts)
if (COMPAT_USE_64BIT_TIME) if (COMPAT_USE_64BIT_TIME)
return copy_from_user(ts, uts, sizeof *ts) ? -EFAULT : 0; return copy_from_user(ts, uts, sizeof *ts) ? -EFAULT : 0;
else else
return get_compat_timespec(ts, uts); return __compat_get_timespec(ts, uts);
} }
EXPORT_SYMBOL_GPL(compat_get_timespec); EXPORT_SYMBOL_GPL(compat_get_timespec);
@ -209,10 +186,33 @@ int compat_put_timespec(const struct timespec *ts, void __user *uts)
if (COMPAT_USE_64BIT_TIME) if (COMPAT_USE_64BIT_TIME)
return copy_to_user(uts, ts, sizeof *ts) ? -EFAULT : 0; return copy_to_user(uts, ts, sizeof *ts) ? -EFAULT : 0;
else else
return put_compat_timespec(ts, uts); return __compat_put_timespec(ts, uts);
} }
EXPORT_SYMBOL_GPL(compat_put_timespec); EXPORT_SYMBOL_GPL(compat_put_timespec);
int compat_convert_timespec(struct timespec __user **kts,
const void __user *cts)
{
struct timespec ts;
struct timespec __user *uts;
if (!cts || COMPAT_USE_64BIT_TIME) {
*kts = (struct timespec __user *)cts;
return 0;
}
uts = compat_alloc_user_space(sizeof(ts));
if (!uts)
return -EFAULT;
if (compat_get_timespec(&ts, cts))
return -EFAULT;
if (copy_to_user(uts, &ts, sizeof(ts)))
return -EFAULT;
*kts = uts;
return 0;
}
static long compat_nanosleep_restart(struct restart_block *restart) static long compat_nanosleep_restart(struct restart_block *restart)
{ {
struct compat_timespec __user *rmtp; struct compat_timespec __user *rmtp;
@ -229,7 +229,7 @@ static long compat_nanosleep_restart(struct restart_block *restart)
if (ret) { if (ret) {
rmtp = restart->nanosleep.compat_rmtp; rmtp = restart->nanosleep.compat_rmtp;
if (rmtp && put_compat_timespec(&rmt, rmtp)) if (rmtp && compat_put_timespec(&rmt, rmtp))
return -EFAULT; return -EFAULT;
} }
@ -243,7 +243,7 @@ COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp,
mm_segment_t oldfs; mm_segment_t oldfs;
long ret; long ret;
if (get_compat_timespec(&tu, rqtp)) if (compat_get_timespec(&tu, rqtp))
return -EFAULT; return -EFAULT;
if (!timespec_valid(&tu)) if (!timespec_valid(&tu))
@ -263,7 +263,7 @@ COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp,
restart->fn = compat_nanosleep_restart; restart->fn = compat_nanosleep_restart;
restart->nanosleep.compat_rmtp = rmtp; restart->nanosleep.compat_rmtp = rmtp;
if (rmtp && put_compat_timespec(&rmt, rmtp)) if (rmtp && compat_put_timespec(&rmt, rmtp))
return -EFAULT; return -EFAULT;
} }
@ -451,7 +451,7 @@ COMPAT_SYSCALL_DEFINE2(old_getrlimit, unsigned int, resource,
mm_segment_t old_fs = get_fs(); mm_segment_t old_fs = get_fs();
set_fs(KERNEL_DS); set_fs(KERNEL_DS);
ret = sys_old_getrlimit(resource, &r); ret = sys_old_getrlimit(resource, (struct rlimit __user *)&r);
set_fs(old_fs); set_fs(old_fs);
if (!ret) { if (!ret) {
@ -647,8 +647,8 @@ COMPAT_SYSCALL_DEFINE3(sched_getaffinity, compat_pid_t, pid, unsigned int, len,
int get_compat_itimerspec(struct itimerspec *dst, int get_compat_itimerspec(struct itimerspec *dst,
const struct compat_itimerspec __user *src) const struct compat_itimerspec __user *src)
{ {
if (get_compat_timespec(&dst->it_interval, &src->it_interval) || if (__compat_get_timespec(&dst->it_interval, &src->it_interval) ||
get_compat_timespec(&dst->it_value, &src->it_value)) __compat_get_timespec(&dst->it_value, &src->it_value))
return -EFAULT; return -EFAULT;
return 0; return 0;
} }
@ -656,8 +656,8 @@ int get_compat_itimerspec(struct itimerspec *dst,
int put_compat_itimerspec(struct compat_itimerspec __user *dst, int put_compat_itimerspec(struct compat_itimerspec __user *dst,
const struct itimerspec *src) const struct itimerspec *src)
{ {
if (put_compat_timespec(&src->it_interval, &dst->it_interval) || if (__compat_put_timespec(&src->it_interval, &dst->it_interval) ||
put_compat_timespec(&src->it_value, &dst->it_value)) __compat_put_timespec(&src->it_value, &dst->it_value))
return -EFAULT; return -EFAULT;
return 0; return 0;
} }
@ -727,7 +727,7 @@ COMPAT_SYSCALL_DEFINE2(clock_settime, clockid_t, which_clock,
mm_segment_t oldfs; mm_segment_t oldfs;
struct timespec ts; struct timespec ts;
if (get_compat_timespec(&ts, tp)) if (compat_get_timespec(&ts, tp))
return -EFAULT; return -EFAULT;
oldfs = get_fs(); oldfs = get_fs();
set_fs(KERNEL_DS); set_fs(KERNEL_DS);
@ -749,7 +749,7 @@ COMPAT_SYSCALL_DEFINE2(clock_gettime, clockid_t, which_clock,
err = sys_clock_gettime(which_clock, err = sys_clock_gettime(which_clock,
(struct timespec __user *) &ts); (struct timespec __user *) &ts);
set_fs(oldfs); set_fs(oldfs);
if (!err && put_compat_timespec(&ts, tp)) if (!err && compat_put_timespec(&ts, tp))
return -EFAULT; return -EFAULT;
return err; return err;
} }
@ -789,7 +789,7 @@ COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock,
err = sys_clock_getres(which_clock, err = sys_clock_getres(which_clock,
(struct timespec __user *) &ts); (struct timespec __user *) &ts);
set_fs(oldfs); set_fs(oldfs);
if (!err && tp && put_compat_timespec(&ts, tp)) if (!err && tp && compat_put_timespec(&ts, tp))
return -EFAULT; return -EFAULT;
return err; return err;
} }
@ -799,7 +799,7 @@ static long compat_clock_nanosleep_restart(struct restart_block *restart)
long err; long err;
mm_segment_t oldfs; mm_segment_t oldfs;
struct timespec tu; struct timespec tu;
struct compat_timespec *rmtp = restart->nanosleep.compat_rmtp; struct compat_timespec __user *rmtp = restart->nanosleep.compat_rmtp;
restart->nanosleep.rmtp = (struct timespec __user *) &tu; restart->nanosleep.rmtp = (struct timespec __user *) &tu;
oldfs = get_fs(); oldfs = get_fs();
@ -808,7 +808,7 @@ static long compat_clock_nanosleep_restart(struct restart_block *restart)
set_fs(oldfs); set_fs(oldfs);
if ((err == -ERESTART_RESTARTBLOCK) && rmtp && if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
put_compat_timespec(&tu, rmtp)) compat_put_timespec(&tu, rmtp))
return -EFAULT; return -EFAULT;
if (err == -ERESTART_RESTARTBLOCK) { if (err == -ERESTART_RESTARTBLOCK) {
@ -827,7 +827,7 @@ COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
struct timespec in, out; struct timespec in, out;
struct restart_block *restart; struct restart_block *restart;
if (get_compat_timespec(&in, rqtp)) if (compat_get_timespec(&in, rqtp))
return -EFAULT; return -EFAULT;
oldfs = get_fs(); oldfs = get_fs();
@ -838,7 +838,7 @@ COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
set_fs(oldfs); set_fs(oldfs);
if ((err == -ERESTART_RESTARTBLOCK) && rmtp && if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
put_compat_timespec(&out, rmtp)) compat_put_timespec(&out, rmtp))
return -EFAULT; return -EFAULT;
if (err == -ERESTART_RESTARTBLOCK) { if (err == -ERESTART_RESTARTBLOCK) {
@ -1130,7 +1130,7 @@ COMPAT_SYSCALL_DEFINE2(sched_rr_get_interval,
set_fs(KERNEL_DS); set_fs(KERNEL_DS);
ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t); ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t);
set_fs(old_fs); set_fs(old_fs);
if (put_compat_timespec(&t, interval)) if (compat_put_timespec(&t, interval))
return -EFAULT; return -EFAULT;
return ret; return ret;
} }

Просмотреть файл

@ -183,7 +183,7 @@ COMPAT_SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val,
if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI || if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI ||
cmd == FUTEX_WAIT_BITSET || cmd == FUTEX_WAIT_BITSET ||
cmd == FUTEX_WAIT_REQUEUE_PI)) { cmd == FUTEX_WAIT_REQUEUE_PI)) {
if (get_compat_timespec(&ts, utime)) if (compat_get_timespec(&ts, utime))
return -EFAULT; return -EFAULT;
if (!timespec_valid(&ts)) if (!timespec_valid(&ts))
return -EINVAL; return -EINVAL;