diff options
author | Conrad Meyer <cem@FreeBSD.org> | 2017-01-24 18:05:29 +0000 |
---|---|---|
committer | Conrad Meyer <cem@FreeBSD.org> | 2017-01-24 18:05:29 +0000 |
commit | 90a79ac5765a09d48b085183503324584ef0f956 (patch) | |
tree | 8fcf99b45a360e1521e75d446d98b49dc3d6a9cd /sys/kern | |
parent | 86e01d5addbd93d057433bc0bd8627ea54d2535b (diff) | |
download | src-90a79ac5765a09d48b085183503324584ef0f956.tar.gz src-90a79ac5765a09d48b085183503324584ef0f956.zip |
Use time_t for intermediate values to avoid overflow in clock_ts_to_ct
Add additionally safety and overflow checks to clock_ts_to_ct and the
BCD routines while we're here.
Perform a safety check in sys_clock_settime() first to avoid easy local
root panic, without having to propagate an error value back through
dozens of APIs currently lacking error returns.
PR: 211960, 214300
Submitted by: Justin McOmie <justin.mcomie at gmail.com>, kib@
Reported by: Tim Newsham <tim.newsham at nccgroup.trust>
Reviewed by: kib@
Sponsored by: Dell EMC Isilon, FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D9279
Notes
Notes:
svn path=/head/; revision=312702
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_time.c | 7 | ||||
-rw-r--r-- | sys/kern/subr_clock.c | 16 |
2 files changed, 22 insertions, 1 deletions
diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c index fbc42c986f78..8914ebff0a3b 100644 --- a/sys/kern/kern_time.c +++ b/sys/kern/kern_time.c @@ -387,6 +387,11 @@ sys_clock_settime(struct thread *td, struct clock_settime_args *uap) return (kern_clock_settime(td, uap->clock_id, &ats)); } +static int allow_insane_settime = 0; +SYSCTL_INT(_debug, OID_AUTO, allow_insane_settime, CTLFLAG_RWTUN, + &allow_insane_settime, 0, + "do not perform possibly restrictive checks on settime(2) args"); + int kern_clock_settime(struct thread *td, clockid_t clock_id, struct timespec *ats) { @@ -400,6 +405,8 @@ kern_clock_settime(struct thread *td, clockid_t clock_id, struct timespec *ats) if (ats->tv_nsec < 0 || ats->tv_nsec >= 1000000000 || ats->tv_sec < 0) return (EINVAL); + if (!allow_insane_settime && ats->tv_sec > 9999ULL * 366 * 24 * 60 * 60) + return (EINVAL); /* XXX Don't convert nsec->usec and back */ TIMESPEC_TO_TIMEVAL(&atv, ats); error = settime(td, &atv); diff --git a/sys/kern/subr_clock.c b/sys/kern/subr_clock.c index dea3e5793d88..d14311795ed8 100644 --- a/sys/kern/subr_clock.c +++ b/sys/kern/subr_clock.c @@ -178,7 +178,7 @@ clock_ct_to_ts(struct clocktime *ct, struct timespec *ts) void clock_ts_to_ct(struct timespec *ts, struct clocktime *ct) { - int i, year, days; + time_t i, year, days; time_t rsec; /* remainder seconds */ time_t secs; @@ -214,6 +214,20 @@ clock_ts_to_ct(struct timespec *ts, struct clocktime *ct) print_ct(ct); printf("\n"); } + + KASSERT(ct->year >= 0 && ct->year < 10000, + ("year %d isn't a 4 digit year", ct->year)); + KASSERT(ct->mon >= 1 && ct->mon <= 12, + ("month %d not in 1-12", ct->mon)); + KASSERT(ct->day >= 1 && ct->day <= 31, + ("day %d not in 1-31", ct->day)); + KASSERT(ct->hour >= 0 && ct->hour <= 23, + ("hour %d not in 0-23", ct->hour)); + KASSERT(ct->min >= 0 && ct->min <= 59, + ("minute %d not in 0-59", ct->min)); + /* Not sure if this interface needs to handle leapseconds or not. */ + KASSERT(ct->sec >= 0 && ct->sec <= 60, + ("seconds %d not in 0-60", ct->sec)); } int |