1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-19 10:53:58 +00:00

Fix time math overflows and improve zero intervals handling in poll(),

select(), nanosleep() and kevent() functions after calloutng changes.

Reported by:	bde
This commit is contained in:
Alexander Motin 2013-03-06 19:37:38 +00:00
parent 9461964cc9
commit 980c545d76
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=247898
3 changed files with 42 additions and 18 deletions

View File

@ -1329,11 +1329,16 @@ kqueue_scan(struct kqueue *kq, int maxevents, struct kevent_copyops *k_ops,
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

View File

@ -484,13 +484,20 @@ kern_nanosleep(struct thread *td, struct timespec *rqt, struct timespec *rmt)
{
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 timespec *rqt, struct timespec *rmt)
TIMESEL(&sbtt, tmp);
if (rmt != NULL) {
ts = sbttots(sbt - sbtt);
ts.tv_sec += over;
if (ts.tv_sec < 0)
timespecclear(&ts);
*rmt = ts;

View File

@ -1051,12 +1051,19 @@ kern_select(struct thread *td, int nd, fd_set *fd_in, fd_set *fd_ou,
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);