svn commit: r312702 - in head/sys: kern libkern sys

Conrad E. Meyer cem at FreeBSD.org
Tue Jan 24 18:05:31 UTC 2017


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 <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

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 <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include <sys/param.h>
 #include <sys/libkern.h>
 
 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); }


More information about the svn-src-head mailing list