There is a slight inconsistency in klist_invalidate(). If the knote is
already in the event queue and has flag EV_ONESHOT, kqueue_scan() will
not invoke the newly set f_event. In this case, the kevent(2) system
call will return the knote's original event state that no longer
reflects the state that is reachable through the file descriptor
(the caller of klist_invalidate() has already revoked access to the
file or device).

I think a proper fix is to invoke f_event manually to force the state
update.

OK?

Index: kern/kern_event.c
===================================================================
RCS file: src/sys/kern/kern_event.c,v
retrieving revision 1.153
diff -u -p -r1.153 kern_event.c
--- kern/kern_event.c   20 Dec 2020 12:54:05 -0000      1.153
+++ kern/kern_event.c   21 Dec 2020 16:19:30 -0000
@@ -1618,6 +1618,7 @@ klist_invalidate(struct klist *list)
                kn->kn_fop->f_detach(kn);
                if (kn->kn_fop->f_flags & FILTEROP_ISFD) {
                        kn->kn_fop = &dead_filtops;
+                       kn->kn_fop->f_event(kn, 0);
                        knote_activate(kn);
                        s = splhigh();
                        knote_release(kn);

Reply via email to