Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 6 Mar 2013 19:37:39 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r247898 - head/sys/kern
Message-ID:  <201303061937.r26JbdNR044058@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Wed Mar  6 19:37:38 2013
New Revision: 247898
URL: http://svnweb.freebsd.org/changeset/base/247898

Log:
  Fix time math overflows and improve zero intervals handling in poll(),
  select(), nanosleep() and kevent() functions after calloutng changes.
  
  Reported by:	bde

Modified:
  head/sys/kern/kern_event.c
  head/sys/kern/kern_time.c
  head/sys/kern/sys_generic.c

Modified: head/sys/kern/kern_event.c
==============================================================================
--- head/sys/kern/kern_event.c	Wed Mar  6 18:45:11 2013	(r247897)
+++ head/sys/kern/kern_event.c	Wed Mar  6 19:37:38 2013	(r247898)
@@ -1329,11 +1329,16 @@ kqueue_scan(struct kqueue *kq, int maxev
 			goto done_nl;
 		}
 		if (timespecisset(tsp)) {
-			rsbt = tstosbt(*tsp);
-			if (TIMESEL(&asbt, rsbt))
-				asbt += tc_tick_sbt;
-			asbt += rsbt;
-			rsbt >>= tc_precexp;
+			if (tsp->tv_sec < INT32_MAX) {
+				rsbt = tstosbt(*tsp);
+				if (TIMESEL(&asbt, rsbt))
+					asbt += tc_tick_sbt;
+				asbt += rsbt;
+				if (asbt < rsbt)
+					asbt = 0;
+				rsbt >>= tc_precexp;
+			} else
+				asbt = 0;
 		} else
 			asbt = -1;
 	} else

Modified: head/sys/kern/kern_time.c
==============================================================================
--- head/sys/kern/kern_time.c	Wed Mar  6 18:45:11 2013	(r247897)
+++ head/sys/kern/kern_time.c	Wed Mar  6 19:37:38 2013	(r247898)
@@ -484,13 +484,20 @@ kern_nanosleep(struct thread *td, struct
 {
 	struct timespec ts;
 	sbintime_t sbt, sbtt, prec, tmp;
+	time_t over;
 	int error;
 
 	if (rqt->tv_nsec < 0 || rqt->tv_nsec >= 1000000000)
 		return (EINVAL);
 	if (rqt->tv_sec < 0 || (rqt->tv_sec == 0 && rqt->tv_nsec == 0))
 		return (0);
-	tmp = tstosbt(*rqt);
+	ts = *rqt;
+	if (ts.tv_sec > INT32_MAX / 2) {
+		over = ts.tv_sec - INT32_MAX / 2;
+		ts.tv_sec -= over;
+	} else
+		over = 0;
+	tmp = tstosbt(ts);
 	prec = tmp;
 	prec >>= tc_precexp;
 	if (TIMESEL(&sbt, tmp))
@@ -504,6 +511,7 @@ kern_nanosleep(struct thread *td, struct
 		TIMESEL(&sbtt, tmp);
 		if (rmt != NULL) {
 			ts = sbttots(sbt - sbtt);
+			ts.tv_sec += over;
 			if (ts.tv_sec < 0)
 				timespecclear(&ts);
 			*rmt = ts;

Modified: head/sys/kern/sys_generic.c
==============================================================================
--- head/sys/kern/sys_generic.c	Wed Mar  6 18:45:11 2013	(r247897)
+++ head/sys/kern/sys_generic.c	Wed Mar  6 19:37:38 2013	(r247898)
@@ -1051,12 +1051,19 @@ kern_select(struct thread *td, int nd, f
 			error = EINVAL;
 			goto done;
 		}
-		rsbt = tvtosbt(rtv);
-		precision = rsbt;
-		precision >>= tc_precexp;
-		if (TIMESEL(&asbt, rsbt))
-			asbt += tc_tick_sbt;
-		asbt += rsbt;
+		if (rtv.tv_sec == 0 && rtv.tv_usec == 0)
+			asbt = 0;
+		else if (rtv.tv_sec < INT32_MAX) {
+			rsbt = tvtosbt(rtv);
+			precision = rsbt;
+			precision >>= tc_precexp;
+			if (TIMESEL(&asbt, rsbt))
+				asbt += tc_tick_sbt;
+			asbt += rsbt;
+			if (asbt < rsbt)
+				asbt = -1;
+		} else
+			asbt = -1;
 	} else
 		asbt = -1;
 	seltdinit(td);
@@ -1295,12 +1302,16 @@ sys_poll(td, uap)
 			error = EINVAL;
 			goto done;
 		}
-		rsbt = SBT_1MS * uap->timeout;
-		precision = rsbt;
-		precision >>= tc_precexp;
-		if (TIMESEL(&asbt, rsbt))
-			asbt += tc_tick_sbt;
-		asbt += rsbt;
+		if (uap->timeout == 0)
+			asbt = 0;
+		else {
+			rsbt = SBT_1MS * uap->timeout;
+			precision = rsbt;
+			precision >>= tc_precexp;
+			if (TIMESEL(&asbt, rsbt))
+				asbt += tc_tick_sbt;
+			asbt += rsbt;
+		}
 	} else
 		asbt = -1;
 	seltdinit(td);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201303061937.r26JbdNR044058>