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);
}
}