From owner-svn-src-head@freebsd.org Tue Jan 24 18:05:31 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 08161CC0E7F; Tue, 24 Jan 2017 18:05:31 +0000 (UTC) (envelope-from cem@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id BCDDD813; Tue, 24 Jan 2017 18:05:30 +0000 (UTC) (envelope-from cem@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v0OI5TMU043553; Tue, 24 Jan 2017 18:05:29 GMT (envelope-from cem@FreeBSD.org) Received: (from cem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v0OI5Tb6043549; Tue, 24 Jan 2017 18:05:29 GMT (envelope-from cem@FreeBSD.org) Message-Id: <201701241805.v0OI5Tb6043549@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: cem set sender to cem@FreeBSD.org using -f From: "Conrad E. Meyer" Date: Tue, 24 Jan 2017 18:05:29 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r312702 - in head/sys: kern libkern sys X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 24 Jan 2017 18:05:31 -0000 Author: cem Date: Tue Jan 24 18:05:29 2017 New Revision: 312702 URL: https://svnweb.freebsd.org/changeset/base/312702 Log: 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 , kib@ Reported by: Tim Newsham Reviewed by: kib@ Sponsored by: Dell EMC Isilon, FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D9279 Modified: head/sys/kern/kern_time.c head/sys/kern/subr_clock.c head/sys/libkern/bcd.c head/sys/sys/libkern.h Modified: head/sys/kern/kern_time.c ============================================================================== --- head/sys/kern/kern_time.c Tue Jan 24 17:30:13 2017 (r312701) +++ head/sys/kern/kern_time.c Tue Jan 24 18:05:29 2017 (r312702) @@ -387,6 +387,11 @@ sys_clock_settime(struct thread *td, str 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, cl 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); Modified: head/sys/kern/subr_clock.c ============================================================================== --- head/sys/kern/subr_clock.c Tue Jan 24 17:30:13 2017 (r312701) +++ head/sys/kern/subr_clock.c Tue Jan 24 18:05:29 2017 (r312702) @@ -178,7 +178,7 @@ clock_ct_to_ts(struct clocktime *ct, str 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, stru 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 Modified: head/sys/libkern/bcd.c ============================================================================== --- head/sys/libkern/bcd.c Tue Jan 24 17:30:13 2017 (r312701) +++ head/sys/libkern/bcd.c Tue Jan 24 18:05:29 2017 (r312702) @@ -6,6 +6,7 @@ #include __FBSDID("$FreeBSD$"); +#include #include u_char const bcd2bin_data[] = { @@ -20,6 +21,7 @@ u_char const bcd2bin_data[] = { 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 0, 0, 0, 0, 0, 0, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 }; +CTASSERT(nitems(bcd2bin_data) == LIBKERN_LEN_BCD2BIN); u_char const bin2bcd_data[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, @@ -33,6 +35,8 @@ u_char const bin2bcd_data[] = { 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99 }; +CTASSERT(nitems(bin2bcd_data) == LIBKERN_LEN_BIN2BCD); /* This is actually used with radix [2..36] */ char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz"; +CTASSERT(nitems(hex2ascii_data) == LIBKERN_LEN_HEX2ASCII + 1); Modified: head/sys/sys/libkern.h ============================================================================== --- head/sys/sys/libkern.h Tue Jan 24 17:30:13 2017 (r312701) +++ head/sys/sys/libkern.h Tue Jan 24 18:05:29 2017 (r312702) @@ -49,9 +49,36 @@ extern u_char const bcd2bin_data[]; extern u_char const bin2bcd_data[]; extern char const hex2ascii_data[]; -#define bcd2bin(bcd) (bcd2bin_data[bcd]) -#define bin2bcd(bin) (bin2bcd_data[bin]) -#define hex2ascii(hex) (hex2ascii_data[hex]) +#define LIBKERN_LEN_BCD2BIN 154 +#define LIBKERN_LEN_BIN2BCD 100 +#define LIBKERN_LEN_HEX2ASCII 36 + +static inline u_char +bcd2bin(int bcd) +{ + + KASSERT(bcd >= 0 && bcd < LIBKERN_LEN_BCD2BIN, + ("invalid bcd %d", bcd)); + return (bcd2bin_data[bcd]); +} + +static inline u_char +bin2bcd(int bin) +{ + + KASSERT(bin >= 0 && bin < LIBKERN_LEN_BIN2BCD, + ("invalid bin %d", bin)); + return (bin2bcd_data[bin]); +} + +static inline char +hex2ascii(int hex) +{ + + KASSERT(hex >= 0 && hex < LIBKERN_LEN_HEX2ASCII, + ("invalid hex %d", hex)); + return (hex2ascii_data[hex]); +} static __inline int imax(int a, int b) { return (a > b ? a : b); } static __inline int imin(int a, int b) { return (a < b ? a : b); }