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);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to