diff options
author | 2015-10-29 13:20:44 +0000 | |
---|---|---|
committer | 2015-10-29 13:20:44 +0000 | |
commit | 3de3b7a0000d5e40adfff5a10ca059be9df36036 (patch) | |
tree | 282f68ae71455e50418b169ff66a0221408fdd85 | |
parent | remove tests for LD_HINTS_VERSION_1; ok kettenis (diff) | |
download | wireguard-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.c | 9 |
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); } |