From 44ee454670122a959112caaa7aad86d8cacab1ff Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 9 Jul 2017 10:50:14 -0400 Subject: semtimedop(): move compat to native ... and finally kill the sodding compat_convert_timespec() Signed-off-by: Al Viro --- include/linux/compat.h | 9 --------- ipc/compat.c | 10 ---------- ipc/sem.c | 44 +++++++++++++++++++++++++++++++++----------- kernel/compat.c | 23 ----------------------- 4 files changed, 33 insertions(+), 53 deletions(-) diff --git a/include/linux/compat.h b/include/linux/compat.h index 5a6a109b4a50..edae425ca8c0 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -171,15 +171,6 @@ extern int get_compat_itimerspec64(struct itimerspec64 *its, extern int put_compat_itimerspec64(const struct itimerspec64 *its, struct compat_itimerspec __user *uits); -/* - * 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 { compat_uptr_t iov_base; compat_size_t iov_len; diff --git a/ipc/compat.c b/ipc/compat.c index 871d07da0a52..b17bf93d7b49 100644 --- a/ipc/compat.c +++ b/ipc/compat.c @@ -79,13 +79,3 @@ void to_compat_ipc_perm(struct compat_ipc_perm *to, struct ipc64_perm *from) to->mode = from->mode; to->seq = from->seq; } - -COMPAT_SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsems, - unsigned, nsops, - const struct compat_timespec __user *, timeout) -{ - struct timespec __user *ts64; - if (compat_convert_timespec(&ts64, timeout)) - return -EFAULT; - return sys_semtimedop(semid, tsems, nsops, ts64); -} diff --git a/ipc/sem.c b/ipc/sem.c index fcf064d6046a..6b832b7fa9fc 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -1855,8 +1855,8 @@ out: return un; } -SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, - unsigned, nsops, const struct timespec __user *, timeout) +static long do_semtimedop(int semid, struct sembuf __user *tsops, + unsigned nsops, const struct timespec *timeout) { int error = -EINVAL; struct sem_array *sma; @@ -1887,17 +1887,12 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, } if (timeout) { - struct timespec _timeout; - if (copy_from_user(&_timeout, timeout, sizeof(*timeout))) { - error = -EFAULT; - goto out_free; - } - if (_timeout.tv_sec < 0 || _timeout.tv_nsec < 0 || - _timeout.tv_nsec >= 1000000000L) { + if (timeout->tv_sec < 0 || timeout->tv_nsec < 0 || + timeout->tv_nsec >= 1000000000L) { error = -EINVAL; goto out_free; } - jiffies_left = timespec_to_jiffies(&_timeout); + jiffies_left = timespec_to_jiffies(timeout); } max = 0; @@ -2112,10 +2107,37 @@ out_free: return error; } +SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, + unsigned, nsops, const struct timespec __user *, timeout) +{ + if (timeout) { + struct timespec ts; + if (copy_from_user(&ts, timeout, sizeof(*timeout))) + return -EFAULT; + return do_semtimedop(semid, tsops, nsops, &ts); + } + return do_semtimedop(semid, tsops, nsops, NULL); +} + +#ifdef CONFIG_COMPAT +COMPAT_SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsems, + unsigned, nsops, + const struct compat_timespec __user *, timeout) +{ + if (timeout) { + struct timespec ts; + if (compat_get_timespec(&ts, timeout)) + return -EFAULT; + return do_semtimedop(semid, tsems, nsops, &ts); + } + return do_semtimedop(semid, tsems, nsops, NULL); +} +#endif + SYSCALL_DEFINE3(semop, int, semid, struct sembuf __user *, tsops, unsigned, nsops) { - return sys_semtimedop(semid, tsops, nsops, NULL); + return do_semtimedop(semid, tsops, nsops, NULL); } /* If CLONE_SYSVSEM is set, establish sharing of SEM_UNDO state between diff --git a/kernel/compat.c b/kernel/compat.c index 6f0a0e723a06..772e038d04d9 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -200,29 +200,6 @@ int compat_put_timespec(const struct timespec *ts, void __user *uts) } 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; -} - int get_compat_itimerval(struct itimerval *o, const struct compat_itimerval __user *i) { struct compat_itimerval v32; -- cgit v1.2.3-58-ga151