From 662ebe9b53f8c0b83a71db7ce9940e7013823ce2 Mon Sep 17 00:00:00 2001 From: Peter Holm Date: Sat, 3 Dec 2011 12:30:58 +0000 Subject: [PATCH] Add umtx_copyin_timeout() and move parameter checks here. In collaboration with: kib MFC after: 1 week --- sys/kern/kern_umtx.c | 78 ++++++++++++++------------------------------ 1 file changed, 25 insertions(+), 53 deletions(-) diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c index 0247063cd6aa..7d8a781333f7 100644 --- a/sys/kern/kern_umtx.c +++ b/sys/kern/kern_umtx.c @@ -2898,6 +2898,21 @@ sys__umtx_unlock(struct thread *td, struct _umtx_unlock_args *uap) return do_unlock_umtx(td, uap->umtx, td->td_tid); } +inline int +umtx_copyin_timeout(const void *addr, struct timespec *tsp) +{ + int error; + + error = copyin(addr, tsp, sizeof(struct timespec)); + if (error == 0) { + if (tsp->tv_sec < 0 || + tsp->tv_nsec >= 1000000000 || + tsp->tv_nsec < 0) + error = EINVAL; + } + return (error); +} + static int __umtx_op_lock_umtx(struct thread *td, struct _umtx_op_args *uap) { @@ -2908,13 +2923,9 @@ __umtx_op_lock_umtx(struct thread *td, struct _umtx_op_args *uap) if (uap->uaddr2 == NULL) ts = NULL; else { - error = copyin(uap->uaddr2, &timeout, sizeof(timeout)); + error = umtx_copyin_timeout(uap->uaddr2, &timeout); if (error != 0) return (error); - if (timeout.tv_nsec >= 1000000000 || - timeout.tv_nsec < 0) { - return (EINVAL); - } ts = &timeout; } return (do_lock_umtx(td, uap->obj, uap->val, ts)); @@ -2935,12 +2946,9 @@ __umtx_op_wait(struct thread *td, struct _umtx_op_args *uap) if (uap->uaddr2 == NULL) ts = NULL; else { - error = copyin(uap->uaddr2, &timeout, sizeof(timeout)); + error = umtx_copyin_timeout(uap->uaddr2, &timeout); if (error != 0) return (error); - if (timeout.tv_nsec >= 1000000000 || - timeout.tv_nsec < 0) - return (EINVAL); ts = &timeout; } return do_wait(td, uap->obj, uap->val, ts, 0, 0); @@ -2955,12 +2963,9 @@ __umtx_op_wait_uint(struct thread *td, struct _umtx_op_args *uap) if (uap->uaddr2 == NULL) ts = NULL; else { - error = copyin(uap->uaddr2, &timeout, sizeof(timeout)); + error = umtx_copyin_timeout(uap->uaddr2, &timeout); if (error != 0) return (error); - if (timeout.tv_nsec >= 1000000000 || - timeout.tv_nsec < 0) - return (EINVAL); ts = &timeout; } return do_wait(td, uap->obj, uap->val, ts, 1, 0); @@ -2975,12 +2980,9 @@ __umtx_op_wait_uint_private(struct thread *td, struct _umtx_op_args *uap) if (uap->uaddr2 == NULL) ts = NULL; else { - error = copyin(uap->uaddr2, &timeout, sizeof(timeout)); + error = umtx_copyin_timeout(uap->uaddr2, &timeout); if (error != 0) return (error); - if (timeout.tv_nsec >= 1000000000 || - timeout.tv_nsec < 0) - return (EINVAL); ts = &timeout; } return do_wait(td, uap->obj, uap->val, ts, 1, 1); @@ -3034,14 +3036,9 @@ __umtx_op_lock_umutex(struct thread *td, struct _umtx_op_args *uap) if (uap->uaddr2 == NULL) ts = NULL; else { - error = copyin(uap->uaddr2, &timeout, - sizeof(timeout)); + error = umtx_copyin_timeout(uap->uaddr2, &timeout); if (error != 0) return (error); - if (timeout.tv_nsec >= 1000000000 || - timeout.tv_nsec < 0) { - return (EINVAL); - } ts = &timeout; } return do_lock_umutex(td, uap->obj, ts, 0); @@ -3063,14 +3060,9 @@ __umtx_op_wait_umutex(struct thread *td, struct _umtx_op_args *uap) if (uap->uaddr2 == NULL) ts = NULL; else { - error = copyin(uap->uaddr2, &timeout, - sizeof(timeout)); + error = umtx_copyin_timeout(uap->uaddr2, &timeout); if (error != 0) return (error); - if (timeout.tv_nsec >= 1000000000 || - timeout.tv_nsec < 0) { - return (EINVAL); - } ts = &timeout; } return do_lock_umutex(td, uap->obj, ts, _UMUTEX_WAIT); @@ -3104,14 +3096,9 @@ __umtx_op_cv_wait(struct thread *td, struct _umtx_op_args *uap) if (uap->uaddr2 == NULL) ts = NULL; else { - error = copyin(uap->uaddr2, &timeout, - sizeof(timeout)); + error = umtx_copyin_timeout(uap->uaddr2, &timeout); if (error != 0) return (error); - if (timeout.tv_nsec >= 1000000000 || - timeout.tv_nsec < 0) { - return (EINVAL); - } ts = &timeout; } return (do_cv_wait(td, uap->obj, uap->uaddr1, ts, uap->val)); @@ -3139,14 +3126,9 @@ __umtx_op_rw_rdlock(struct thread *td, struct _umtx_op_args *uap) if (uap->uaddr2 == NULL) { error = do_rw_rdlock(td, uap->obj, uap->val, 0); } else { - error = copyin(uap->uaddr2, &timeout, - sizeof(timeout)); + error = umtx_copyin_timeout(uap->uaddr2, &timeout); if (error != 0) return (error); - if (timeout.tv_nsec >= 1000000000 || - timeout.tv_nsec < 0) { - return (EINVAL); - } error = do_rw_rdlock2(td, uap->obj, uap->val, &timeout); } return (error); @@ -3162,14 +3144,9 @@ __umtx_op_rw_wrlock(struct thread *td, struct _umtx_op_args *uap) if (uap->uaddr2 == NULL) { error = do_rw_wrlock(td, uap->obj, 0); } else { - error = copyin(uap->uaddr2, &timeout, - sizeof(timeout)); + error = umtx_copyin_timeout(uap->uaddr2, &timeout); if (error != 0) return (error); - if (timeout.tv_nsec >= 1000000000 || - timeout.tv_nsec < 0) { - return (EINVAL); - } error = do_rw_wrlock2(td, uap->obj, &timeout); } @@ -3192,14 +3169,9 @@ __umtx_op_sem_wait(struct thread *td, struct _umtx_op_args *uap) if (uap->uaddr2 == NULL) ts = NULL; else { - error = copyin(uap->uaddr2, &timeout, - sizeof(timeout)); + error = umtx_copyin_timeout(uap->uaddr2, &timeout); if (error != 0) return (error); - if (timeout.tv_nsec >= 1000000000 || - timeout.tv_nsec < 0) { - return (EINVAL); - } ts = &timeout; } return (do_sem_wait(td, uap->obj, ts));