From ce1591e9cb9181593e791fd1aafd256351177d94 Mon Sep 17 00:00:00 2001 From: visa Date: Sat, 25 Dec 2021 11:04:58 +0000 Subject: [PATCH] kqueue: Invalidate revoked vnodes' knotes on the fly When a tty device is revoked, the associated knotes should be invalidated. Otherwise the user processes can keep on receiving events from the device. It appears tricky to do the invalidation as part of revocation in a way that does not allow unwanted event registration or clutter the tty code. For now, make the knotes invalid lazily before delivery. OK mpi@ --- sys/kern/kern_event.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index 109f7895455..33f30f27be8 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_event.c,v 1.177 2021/12/20 16:24:32 visa Exp $ */ +/* $OpenBSD: kern_event.c,v 1.178 2021/12/25 11:04:58 visa Exp $ */ /*- * Copyright (c) 1999,2000,2001 Jonathan Lemon @@ -55,6 +55,7 @@ #include #include #include +#include #include #ifdef DIAGNOSTIC @@ -1381,6 +1382,36 @@ retry: continue; } + /* + * Invalidate knotes whose vnodes have been revoked. + * This is a workaround; it is tricky to clear existing + * knotes and prevent new ones from being registered + * with the current revocation mechanism. + */ + if ((kn->kn_fop->f_flags & FILTEROP_ISFD) && + kn->kn_fp != NULL && + kn->kn_fp->f_type == DTYPE_VNODE) { + struct vnode *vp = kn->kn_fp->f_data; + + if (__predict_false(vp->v_op == &dead_vops && + kn->kn_fop != &dead_filtops)) { + filter_detach(kn); + kn->kn_fop = &dead_filtops; + + /* + * Check if the event should be delivered. + * Use f_event directly because this is + * a special situation. + */ + if (kn->kn_fop->f_event(kn, 0) == 0) { + filter_detach(kn); + knote_drop(kn, p); + mtx_enter(&kq->kq_lock); + continue; + } + } + } + memset(kevp, 0, sizeof(*kevp)); if (filter_process(kn, kevp) == 0) { mtx_enter(&kq->kq_lock); -- 2.20.1