Add umtx_copyin_timeout() and move parameter checks here.

In collaboration with:	kib
MFC after:	1 week
This commit is contained in:
Peter Holm 2011-12-03 12:30:58 +00:00
parent ff77dfb0c1
commit 662ebe9b53
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=228219

View File

@ -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); 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 static int
__umtx_op_lock_umtx(struct thread *td, struct _umtx_op_args *uap) __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) if (uap->uaddr2 == NULL)
ts = NULL; ts = NULL;
else { else {
error = copyin(uap->uaddr2, &timeout, sizeof(timeout)); error = umtx_copyin_timeout(uap->uaddr2, &timeout);
if (error != 0) if (error != 0)
return (error); return (error);
if (timeout.tv_nsec >= 1000000000 ||
timeout.tv_nsec < 0) {
return (EINVAL);
}
ts = &timeout; ts = &timeout;
} }
return (do_lock_umtx(td, uap->obj, uap->val, ts)); 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) if (uap->uaddr2 == NULL)
ts = NULL; ts = NULL;
else { else {
error = copyin(uap->uaddr2, &timeout, sizeof(timeout)); error = umtx_copyin_timeout(uap->uaddr2, &timeout);
if (error != 0) if (error != 0)
return (error); return (error);
if (timeout.tv_nsec >= 1000000000 ||
timeout.tv_nsec < 0)
return (EINVAL);
ts = &timeout; ts = &timeout;
} }
return do_wait(td, uap->obj, uap->val, ts, 0, 0); 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) if (uap->uaddr2 == NULL)
ts = NULL; ts = NULL;
else { else {
error = copyin(uap->uaddr2, &timeout, sizeof(timeout)); error = umtx_copyin_timeout(uap->uaddr2, &timeout);
if (error != 0) if (error != 0)
return (error); return (error);
if (timeout.tv_nsec >= 1000000000 ||
timeout.tv_nsec < 0)
return (EINVAL);
ts = &timeout; ts = &timeout;
} }
return do_wait(td, uap->obj, uap->val, ts, 1, 0); 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) if (uap->uaddr2 == NULL)
ts = NULL; ts = NULL;
else { else {
error = copyin(uap->uaddr2, &timeout, sizeof(timeout)); error = umtx_copyin_timeout(uap->uaddr2, &timeout);
if (error != 0) if (error != 0)
return (error); return (error);
if (timeout.tv_nsec >= 1000000000 ||
timeout.tv_nsec < 0)
return (EINVAL);
ts = &timeout; ts = &timeout;
} }
return do_wait(td, uap->obj, uap->val, ts, 1, 1); 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) if (uap->uaddr2 == NULL)
ts = NULL; ts = NULL;
else { else {
error = copyin(uap->uaddr2, &timeout, error = umtx_copyin_timeout(uap->uaddr2, &timeout);
sizeof(timeout));
if (error != 0) if (error != 0)
return (error); return (error);
if (timeout.tv_nsec >= 1000000000 ||
timeout.tv_nsec < 0) {
return (EINVAL);
}
ts = &timeout; ts = &timeout;
} }
return do_lock_umutex(td, uap->obj, ts, 0); 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) if (uap->uaddr2 == NULL)
ts = NULL; ts = NULL;
else { else {
error = copyin(uap->uaddr2, &timeout, error = umtx_copyin_timeout(uap->uaddr2, &timeout);
sizeof(timeout));
if (error != 0) if (error != 0)
return (error); return (error);
if (timeout.tv_nsec >= 1000000000 ||
timeout.tv_nsec < 0) {
return (EINVAL);
}
ts = &timeout; ts = &timeout;
} }
return do_lock_umutex(td, uap->obj, ts, _UMUTEX_WAIT); 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) if (uap->uaddr2 == NULL)
ts = NULL; ts = NULL;
else { else {
error = copyin(uap->uaddr2, &timeout, error = umtx_copyin_timeout(uap->uaddr2, &timeout);
sizeof(timeout));
if (error != 0) if (error != 0)
return (error); return (error);
if (timeout.tv_nsec >= 1000000000 ||
timeout.tv_nsec < 0) {
return (EINVAL);
}
ts = &timeout; ts = &timeout;
} }
return (do_cv_wait(td, uap->obj, uap->uaddr1, ts, uap->val)); 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) { if (uap->uaddr2 == NULL) {
error = do_rw_rdlock(td, uap->obj, uap->val, 0); error = do_rw_rdlock(td, uap->obj, uap->val, 0);
} else { } else {
error = copyin(uap->uaddr2, &timeout, error = umtx_copyin_timeout(uap->uaddr2, &timeout);
sizeof(timeout));
if (error != 0) if (error != 0)
return (error); return (error);
if (timeout.tv_nsec >= 1000000000 ||
timeout.tv_nsec < 0) {
return (EINVAL);
}
error = do_rw_rdlock2(td, uap->obj, uap->val, &timeout); error = do_rw_rdlock2(td, uap->obj, uap->val, &timeout);
} }
return (error); return (error);
@ -3162,14 +3144,9 @@ __umtx_op_rw_wrlock(struct thread *td, struct _umtx_op_args *uap)
if (uap->uaddr2 == NULL) { if (uap->uaddr2 == NULL) {
error = do_rw_wrlock(td, uap->obj, 0); error = do_rw_wrlock(td, uap->obj, 0);
} else { } else {
error = copyin(uap->uaddr2, &timeout, error = umtx_copyin_timeout(uap->uaddr2, &timeout);
sizeof(timeout));
if (error != 0) if (error != 0)
return (error); return (error);
if (timeout.tv_nsec >= 1000000000 ||
timeout.tv_nsec < 0) {
return (EINVAL);
}
error = do_rw_wrlock2(td, uap->obj, &timeout); 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) if (uap->uaddr2 == NULL)
ts = NULL; ts = NULL;
else { else {
error = copyin(uap->uaddr2, &timeout, error = umtx_copyin_timeout(uap->uaddr2, &timeout);
sizeof(timeout));
if (error != 0) if (error != 0)
return (error); return (error);
if (timeout.tv_nsec >= 1000000000 ||
timeout.tv_nsec < 0) {
return (EINVAL);
}
ts = &timeout; ts = &timeout;
} }
return (do_sem_wait(td, uap->obj, ts)); return (do_sem_wait(td, uap->obj, ts));