aboutsummaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorConrad Meyer <cem@FreeBSD.org>2017-01-24 18:05:29 +0000
committerConrad Meyer <cem@FreeBSD.org>2017-01-24 18:05:29 +0000
commit90a79ac5765a09d48b085183503324584ef0f956 (patch)
tree8fcf99b45a360e1521e75d446d98b49dc3d6a9cd /sys/kern
parent86e01d5addbd93d057433bc0bd8627ea54d2535b (diff)
downloadsrc-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.c7
-rw-r--r--sys/kern/subr_clock.c16
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