From: visa Date: Wed, 27 Jan 2021 02:58:03 +0000 (+0000) Subject: kqueue: Fix termination assert X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=715db9d67ba37ce7fc5743a27870b51982740725;p=openbsd kqueue: Fix termination assert When a kqueue file is closed, the kqueue can still have threads scanning it. Consequently, kqueue_terminate() can see scan markers in the event queue. These markers are removed when the scanning threads leave the kqueue. Take this into account when checking the queue's state, to avoid a panic when kqueue is closed from under a thread. OK anton@ Reported-by: syzbot+757c60a2aa1125137cce@syzkaller.appspotmail.com --- diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index c5d47d33bdc..5471b2913d6 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_event.c,v 1.159 2021/01/17 05:56:32 visa Exp $ */ +/* $OpenBSD: kern_event.c,v 1.160 2021/01/27 02:58:03 visa Exp $ */ /*- * Copyright (c) 1999,2000,2001 Jonathan Lemon @@ -206,6 +206,8 @@ KQRELE(struct kqueue *kq) fdpunlock(fdp); } + KASSERT(TAILQ_EMPTY(&kq->kq_head)); + free(kq->kq_knlist, M_KEVENT, kq->kq_knlistsize * sizeof(struct knlist)); hashfree(kq->kq_knhash, KN_HASHSIZE, M_KEVENT); @@ -1265,7 +1267,15 @@ kqueue_purge(struct proc *p, struct kqueue *kq) void kqueue_terminate(struct proc *p, struct kqueue *kq) { - KASSERT(TAILQ_EMPTY(&kq->kq_head)); + struct knote *kn; + + /* + * Any remaining entries should be scan markers. + * They are removed when the ongoing scans finish. + */ + KASSERT(kq->kq_count == 0); + TAILQ_FOREACH(kn, &kq->kq_head, kn_tqe) + KASSERT(kn->kn_filter == EVFILT_MARKER); kq->kq_state |= KQ_DYING; kqueue_wakeup(kq);