summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcheloha <cheloha@cvs.openbsd.org>2019-01-18 05:06:39 +0000
committercheloha <cheloha@cvs.openbsd.org>2019-01-18 05:06:39 +0000
commitd571f38fd5117df0370712be6a0b207950943329 (patch)
tree90ae60b6eba356f9eb87fc4b9fdd747de64ed6be
parent1018edf4e57ce0fab8eddf572afe4b57c448ba07 (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.29
-rw-r--r--sys/kern/sys_futex.c4
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)