diff options
Diffstat (limited to 'ipc/sem.c')
-rw-r--r-- | ipc/sem.c | 44 |
1 files changed, 33 insertions, 11 deletions
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 |