kqueue: fix recent assertion

NOTE_ABSTIME may also have a zero timeout, which indicates that we
should still fire immediately as an absolute time in the past.  A test
has been added for this one as well.

Fixes:	9c999a259f ("kqueue: don't arbitrarily restrict long-past...")
Point hat:	kevans
Reported by:	syzbot+1c8d1154f560b3930042@syzkaller.appspotmail.com
This commit is contained in:
Kyle Evans 2021-10-01 11:59:31 -05:00
parent 4aed5c3c9d
commit 2f4dbe279f
2 changed files with 32 additions and 1 deletions

View File

@ -819,7 +819,8 @@ filt_timerattach(struct knote *kn)
error = filt_timervalidate(kn, &to);
if (error != 0)
return (error);
KASSERT((kn->kn_flags & EV_ONESHOT) != 0 || to > 0,
KASSERT(to > 0 || (kn->kn_flags & EV_ONESHOT) != 0 ||
(kn->kn_sfflags & NOTE_ABSTIME) != 0,
("%s: periodic timer has a calculated zero timeout", __func__));
KASSERT(to >= 0,
("%s: timer has a calculated negative timeout", __func__));

View File

@ -247,6 +247,35 @@ test_abstime(void)
success();
}
static void
test_abstime_epoch(void)
{
const char *test_id = "kevent(EVFILT_TIMER (EPOCH), NOTE_ABSTIME)";
struct kevent kev;
test_begin(test_id);
test_no_kevents();
EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD, NOTE_ABSTIME, 0,
NULL);
if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
err(1, "%s", test_id);
/* Retrieve the event */
kev.flags = EV_ADD;
kev.data = 1;
kev.fflags = 0;
kevent_cmp(&kev, kevent_get(kqfd));
/* Delete the event */
kev.flags = EV_DELETE;
if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
err(1, "%s", test_id);
success();
}
static void
test_abstime_preboot(void)
{
@ -599,6 +628,7 @@ test_evfilt_timer(void)
test_oneshot();
test_periodic();
test_abstime();
test_abstime_epoch();
test_abstime_preboot();
test_abstime_postboot();
test_update();