summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorPatrick Mooney <pmooney@pfmooney.com>2016-08-02 20:58:15 +0000
committerPatrick Mooney <pmooney@pfmooney.com>2016-08-04 01:28:38 +0000
commit6fa006e8e0f6560b5ad4df46db0b9cac31cb5e16 (patch)
treec74dbf5b6731567a8643e28732da2465633877a8 /usr/src
parent63ecec4455ffe4397ed23edace7c0409015800a4 (diff)
downloadillumos-joyent-6fa006e8e0f6560b5ad4df46db0b9cac31cb5e16.tar.gz
OS-5566 ppoll timeout calculation can overflow
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com> Reviewed by: Robert Mustacchi <rm@joyent.com> Reviewed by: Alex Wilson <alex.wilson@joyent.com> Approved by: Robert Mustacchi <rm@joyent.com>
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/sys/time.h9
-rw-r--r--usr/src/uts/common/syscall/poll.c30
2 files changed, 35 insertions, 4 deletions
diff --git a/usr/src/uts/common/sys/time.h b/usr/src/uts/common/sys/time.h
index 05cc855a4b..ee64131403 100644
--- a/usr/src/uts/common/sys/time.h
+++ b/usr/src/uts/common/sys/time.h
@@ -15,6 +15,7 @@
* Use is subject to license terms.
*
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2016 Joyent, Inc.
*/
/*
@@ -261,6 +262,14 @@ typedef longlong_t hrtime_t;
#if defined(_KERNEL) || defined(_FAKE_KERNEL)
+/*
+ * Unsigned counterpart to hrtime_t
+ */
+typedef u_longlong_t uhrtime_t;
+
+#define HRTIME_MAX LLONG_MAX
+#define UHRTIME_MAX ULLONG_MAX
+
#include <sys/time_impl.h>
#include <sys/mutex.h>
diff --git a/usr/src/uts/common/syscall/poll.c b/usr/src/uts/common/syscall/poll.c
index 3d0a5cc04b..7b159ddc37 100644
--- a/usr/src/uts/common/syscall/poll.c
+++ b/usr/src/uts/common/syscall/poll.c
@@ -364,7 +364,6 @@ poll_common(pollstate_t *ps, pollfd_t *fds, nfds_t nfds, timespec_t *tsp,
int *fdcnt)
{
kthread_t *t = curthread;
- proc_t *p = ttoproc(t);
hrtime_t deadline; /* hrtime value when we want to return */
pollfd_t *pollfdp;
pollcache_t *pcp;
@@ -378,11 +377,34 @@ poll_common(pollstate_t *ps, pollfd_t *fds, nfds_t nfds, timespec_t *tsp,
deadline = -1;
} else if (tsp->tv_sec == 0 && tsp->tv_nsec == 0) {
deadline = 0;
+ } else if (tsp->tv_sec >= HRTIME_MAX/NANOSEC) {
+ /* Use an indefinite timeout if tv_sec would cause overflow */
+ deadline = -1;
} else {
+ /*
+ * The above check, when combined with the protections offered
+ * by itimerspecfix (ensuring that neither field is negative
+ * and that tv_nsec represents less than a whole second), will
+ * prevent overflow during the conversion from timespec_t to
+ * uhrtime_t.
+ */
+ uhrtime_t utime = tsp->tv_sec * NANOSEC;
+ utime += tsp->tv_nsec;
+
/* They must wait at least a tick. */
- deadline = ((hrtime_t)tsp->tv_sec * NANOSEC) + tsp->tv_nsec;
- deadline = MAX(deadline, nsec_per_tick);
- deadline += gethrtime();
+ utime = MAX(utime, nsec_per_tick);
+
+ /*
+ * Since utime has an upper bound of HRTIME_MAX, adding the
+ * gethrtime() result cannot incur an overflow as the unsigned
+ * type has an adequate bound.
+ */
+ utime += (uhrtime_t)gethrtime();
+ if (utime > HRTIME_MAX) {
+ deadline = -1;
+ } else {
+ deadline = (hrtime_t)utime;
+ }
}
/*