diff options
| author | Patrick Mooney <pmooney@pfmooney.com> | 2016-08-02 20:58:15 +0000 |
|---|---|---|
| committer | Patrick Mooney <pmooney@pfmooney.com> | 2016-08-04 01:28:38 +0000 |
| commit | 6fa006e8e0f6560b5ad4df46db0b9cac31cb5e16 (patch) | |
| tree | c74dbf5b6731567a8643e28732da2465633877a8 /usr/src | |
| parent | 63ecec4455ffe4397ed23edace7c0409015800a4 (diff) | |
| download | illumos-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.h | 9 | ||||
| -rw-r--r-- | usr/src/uts/common/syscall/poll.c | 30 |
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; + } } /* |
