summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsing <jsing@openbsd.org>2015-10-29 13:20:44 +0000
committerjsing <jsing@openbsd.org>2015-10-29 13:20:44 +0000
commit3de3b7a0000d5e40adfff5a10ca059be9df36036 (patch)
tree282f68ae71455e50418b169ff66a0221408fdd85
parentremove tests for LD_HINTS_VERSION_1; ok kettenis (diff)
downloadwireguard-openbsd-3de3b7a0000d5e40adfff5a10ca059be9df36036.tar.xz
wireguard-openbsd-3de3b7a0000d5e40adfff5a10ca059be9df36036.zip
In knote(), use SLIST_FOREACH_SAFE when walking the klist since a call to
an f_event() handler may remove an entry. Currently knote_processexit() calls knote() with NOTE_EXIT, knote() walks the list and calls f_event(), one of these happens to be filt_proc(), which happily SLIST_REMOVEs the NOTE_EXIT note from the same list that knote() is currently walking, then we get back to knote() and go boom... Flushed out by bluhm@'s invalidation change to sys/queue.h and found the hard way by naddy@. ok doug@ nicm@ tedu@
-rw-r--r--sys/kern/kern_event.c9
1 files changed, 4 insertions, 5 deletions
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index 591114787f6..c03ead97703 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_event.c,v 1.65 2015/10/11 01:53:39 guenther Exp $ */
+/* $OpenBSD: kern_event.c,v 1.66 2015/10/29 13:20:44 jsing Exp $ */
/*-
* Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org>
@@ -955,9 +955,9 @@ knote_activate(struct knote *kn)
void
knote(struct klist *list, long hint)
{
- struct knote *kn;
+ struct knote *kn, *kn0;
- SLIST_FOREACH(kn, list, kn_selnext)
+ SLIST_FOREACH_SAFE(kn, list, kn_selnext, kn0)
if (kn->kn_fop->f_event(kn, hint))
KNOTE_ACTIVATE(kn);
}
@@ -1055,9 +1055,8 @@ knote_drop(struct knote *kn, struct proc *p, struct filedesc *fdp)
SLIST_REMOVE(list, kn, knote, kn_link);
if (kn->kn_status & KN_QUEUED)
knote_dequeue(kn);
- if (kn->kn_fop->f_isfd) {
+ if (kn->kn_fop->f_isfd)
FRELE(kn->kn_fp, p);
- }
knote_free(kn);
}