untrusted comment: verify with openbsd-71-base.pub RWR2eHwZTOEiTZu1Ef/K1xXVdqk6Yl1KVYqsIXG14Bs2YkTc1SKAXtCZuWgvbzYT1pnTWKuT1Fct6pq6WYzPzYzqVudcufGaLA4= OpenBSD 7.1 errata 003, May 16, 2022: The kernel could crash due to a race in kqueue. Apply by doing: signify -Vep /etc/signify/openbsd-71-base.pub -x 003_kqueue.patch.sig \ -m - | (cd /usr/src && patch -p0) And then rebuild and install a new kernel: KK=`sysctl -n kern.osversion | cut -d# -f1` cd /usr/src/sys/arch/`machine`/compile/$KK make obj make config make make install Index: sys/kern/kern_event.c =================================================================== RCS file: /cvs/src/sys/kern/kern_event.c,v diff -u -p -r1.186 kern_event.c --- sys/kern/kern_event.c 31 Mar 2022 01:41:22 -0000 1.186 +++ sys/kern/kern_event.c 13 May 2022 20:41:18 -0000 @@ -121,8 +121,8 @@ void knote_dequeue(struct knote *kn); int knote_acquire(struct knote *kn, struct klist *, int); void knote_release(struct knote *kn); void knote_activate(struct knote *kn); -void knote_remove(struct proc *p, struct kqueue *kq, struct knlist *list, - int purge); +void knote_remove(struct proc *p, struct kqueue *kq, struct knlist **plist, + int idx, int purge); void filt_kqdetach(struct knote *kn); int filt_kqueue(struct knote *kn, long hint); @@ -1563,10 +1563,10 @@ kqueue_purge(struct proc *p, struct kque mtx_enter(&kq->kq_lock); for (i = 0; i < kq->kq_knlistsize; i++) - knote_remove(p, kq, &kq->kq_knlist[i], 1); + knote_remove(p, kq, &kq->kq_knlist, i, 1); if (kq->kq_knhashmask != 0) { for (i = 0; i < kq->kq_knhashmask + 1; i++) - knote_remove(p, kq, &kq->kq_knhash[i], 1); + knote_remove(p, kq, &kq->kq_knhash, i, 1); } mtx_leave(&kq->kq_lock); } @@ -1801,13 +1801,15 @@ knote(struct klist *list, long hint) * remove all knotes from a specified knlist */ void -knote_remove(struct proc *p, struct kqueue *kq, struct knlist *list, int purge) +knote_remove(struct proc *p, struct kqueue *kq, struct knlist **plist, int idx, + int purge) { struct knote *kn; MUTEX_ASSERT_LOCKED(&kq->kq_lock); - while ((kn = SLIST_FIRST(list)) != NULL) { + /* Always fetch array pointer as another thread can resize kq_knlist. */ + while ((kn = SLIST_FIRST(*plist + idx)) != NULL) { KASSERT(kn->kn_kq == kq); if (!purge) { @@ -1875,7 +1877,7 @@ knote_fdclose(struct proc *p, int fd) LIST_FOREACH(kq, &fdp->fd_kqlist, kq_next) { mtx_enter(&kq->kq_lock); if (fd < kq->kq_knlistsize) - knote_remove(p, kq, &kq->kq_knlist[fd], 0); + knote_remove(p, kq, &kq->kq_knlist, fd, 0); mtx_leave(&kq->kq_lock); } }