kern: Avoid arithmetic overflow in gettimeleft.

Sprinkle assertions in to verify we're monotonically counting the
time left down to zero.

Reported-by: syzbot+5f6a6329d139810dfe3c@syzkaller.appspotmail.com
This commit is contained in:
riastradh 2022-06-28 02:04:51 +00:00
parent 9515e06261
commit eaf33ef422
1 changed files with 15 additions and 6 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: subr_time.c,v 1.34 2022/06/26 22:31:47 riastradh Exp $ */ /* $NetBSD: subr_time.c,v 1.35 2022/06/28 02:04:51 riastradh Exp $ */
/* /*
* Copyright (c) 1982, 1986, 1989, 1993 * Copyright (c) 1982, 1986, 1989, 1993
@ -33,7 +33,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: subr_time.c,v 1.34 2022/06/26 22:31:47 riastradh Exp $"); __KERNEL_RCSID(0, "$NetBSD: subr_time.c,v 1.35 2022/06/28 02:04:51 riastradh Exp $");
#include <sys/param.h> #include <sys/param.h>
#include <sys/kernel.h> #include <sys/kernel.h>
@ -207,6 +207,7 @@ inittimeleft(struct timespec *ts, struct timespec *sleepts)
if (itimespecfix(ts)) { if (itimespecfix(ts)) {
return -1; return -1;
} }
KASSERT(ts->tv_sec >= 0);
getnanouptime(sleepts); getnanouptime(sleepts);
return 0; return 0;
} }
@ -214,15 +215,23 @@ inittimeleft(struct timespec *ts, struct timespec *sleepts)
int int
gettimeleft(struct timespec *ts, struct timespec *sleepts) gettimeleft(struct timespec *ts, struct timespec *sleepts)
{ {
struct timespec sleptts; struct timespec now, sleptts;
KASSERT(ts->tv_sec >= 0);
/* /*
* Reduce ts by elapsed time based on monotonic time scale. * Reduce ts by elapsed time based on monotonic time scale.
*/ */
getnanouptime(&sleptts); getnanouptime(&now);
timespecadd(ts, sleepts, ts); KASSERT(timespeccmp(sleepts, &now, <=));
timespecsub(&now, sleepts, &sleptts);
*sleepts = now;
if (timespeccmp(ts, &sleptts, <=)) { /* timed out */
timespecclear(ts);
return 0;
}
timespecsub(ts, &sleptts, ts); timespecsub(ts, &sleptts, ts);
*sleepts = sleptts;
return tstohz(ts); return tstohz(ts);
} }