diff options
author | cheloha <cheloha@cvs.openbsd.org> | 2019-01-18 05:06:39 +0000 |
---|---|---|
committer | cheloha <cheloha@cvs.openbsd.org> | 2019-01-18 05:06:39 +0000 |
commit | d571f38fd5117df0370712be6a0b207950943329 (patch) | |
tree | 90ae60b6eba356f9eb87fc4b9fdd747de64ed6be | |
parent | 1018edf4e57ce0fab8eddf572afe4b57c448ba07 (diff) |
futex(2): validate relative timeout before sleeping.
Linux does validation.
Document this new failure case as an EINVAL, like Linux.
"stop waiting" deraadt
-rw-r--r-- | lib/libc/sys/futex.2 | 9 | ||||
-rw-r--r-- | sys/kern/sys_futex.c | 4 |
2 files changed, 10 insertions, 3 deletions
diff --git a/lib/libc/sys/futex.2 b/lib/libc/sys/futex.2 index 1fc2d080a95..6dfc12f0617 100644 --- a/lib/libc/sys/futex.2 +++ b/lib/libc/sys/futex.2 @@ -1,4 +1,4 @@ -.\" $OpenBSD: futex.2,v 1.4 2018/04/24 17:19:35 pirofti Exp $ +.\" $OpenBSD: futex.2,v 1.5 2019/01/18 05:06:37 cheloha Exp $ .\" .\" Copyright (c) 2017 Martin Pieuchot .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: April 24 2018 $ +.Dd $Mdocdate: January 18 2019 $ .Dt FUTEX 2 .Os .Sh NAME @@ -116,6 +116,11 @@ The value pointed to by .Fa uaddr is not the same as the expected value .Fa val . +.It Bq Er EINVAL +The +.Fa timeout +specified a second value less than zero, +or a nanosecond value less than zero or greater than or equal to 1000 million. .It Bq Er ETIMEDOUT The .Fa timeout diff --git a/sys/kern/sys_futex.c b/sys/kern/sys_futex.c index 8e0b1be1af0..0434e16acf1 100644 --- a/sys/kern/sys_futex.c +++ b/sys/kern/sys_futex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sys_futex.c,v 1.9 2018/08/30 03:30:25 visa Exp $ */ +/* $OpenBSD: sys_futex.c,v 1.10 2019/01/18 05:06:38 cheloha Exp $ */ /* * Copyright (c) 2016-2017 Martin Pieuchot @@ -242,6 +242,8 @@ futex_wait(uint32_t *uaddr, uint32_t val, const struct timespec *timeout, if (KTRPOINT(p, KTR_STRUCT)) ktrabstimespec(p, &ts); #endif + if (ts.tv_sec < 0 || ts.tv_nsec < 0 || ts.tv_nsec >= 1000000000) + return EINVAL; to_ticks = (uint64_t)hz * ts.tv_sec + (ts.tv_nsec + tick * 1000 - 1) / (tick * 1000) + 1; if (to_ticks > INT_MAX) |