The branch main has been updated by kevans:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=7259ca31048e5ced8e7f90657a3d7084aeafdf51

commit 7259ca31048e5ced8e7f90657a3d7084aeafdf51
Author:     Kyle Evans <kev...@freebsd.org>
AuthorDate: 2021-10-02 05:23:03 +0000
Commit:     Kyle Evans <kev...@freebsd.org>
CommitDate: 2021-10-12 07:43:07 +0000

    fifos: delegate unhandled kqueue filters to underlying filesystem
    
    This gives the vfs layer a chance to provide handling for EVFILT_VNODE,
    for instance.  Change pipe_specops to use the default vop_kqfilter to
    accommodate fifoops that don't specify the method (i.e. all in-tree).
    
    Based on a patch by Jan Kokemüller.
    
    PR:             225934
    Reviewed by:    kib, markj (both pre-KASSERT)
    Differential Revision:  https://reviews.freebsd.org/D32271
---
 sys/fs/fifofs/fifo_vnops.c          |  1 -
 sys/kern/sys_pipe.c                 |  4 +++
 sys/kern/vfs_subr.c                 |  3 ++
 tests/sys/kqueue/libkqueue/common.h |  2 ++
 tests/sys/kqueue/libkqueue/vnode.c  | 59 +++++++++++++++++++++++++++++++++++++
 5 files changed, 68 insertions(+), 1 deletion(-)

diff --git a/sys/fs/fifofs/fifo_vnops.c b/sys/fs/fifofs/fifo_vnops.c
index 1b941620b080..d9dc8eee8e60 100644
--- a/sys/fs/fifofs/fifo_vnops.c
+++ b/sys/fs/fifofs/fifo_vnops.c
@@ -83,7 +83,6 @@ struct vop_vector fifo_specops = {
        .vop_create =           VOP_PANIC,
        .vop_getattr =          VOP_EBADF,
        .vop_ioctl =            VOP_PANIC,
-       .vop_kqfilter =         VOP_PANIC,
        .vop_link =             VOP_PANIC,
        .vop_mkdir =            VOP_PANIC,
        .vop_mknod =            VOP_PANIC,
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
index 7bd7fea28e76..1d5d7329692e 100644
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -1751,6 +1751,10 @@ pipe_kqfilter(struct file *fp, struct knote *kn)
                cpipe = PIPE_PEER(cpipe);
                break;
        default:
+               if ((cpipe->pipe_type & PIPE_TYPE_NAMED) != 0) {
+                       PIPE_UNLOCK(cpipe);
+                       return (vnops.fo_kqfilter(fp, kn));
+               }
                PIPE_UNLOCK(cpipe);
                return (EINVAL);
        }
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 69ac73bd3954..d4b7ac71eb97 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -6172,6 +6172,9 @@ vfs_kqfilter(struct vop_kqfilter_args *ap)
        struct knote *kn = ap->a_kn;
        struct knlist *knl;
 
+       KASSERT(vp->v_type != VFIFO || (kn->kn_filter != EVFILT_READ &&
+           kn->kn_filter != EVFILT_WRITE),
+           ("READ/WRITE filter on a FIFO leaked through"));
        switch (kn->kn_filter) {
        case EVFILT_READ:
                kn->kn_fop = &vfsread_filtops;
diff --git a/tests/sys/kqueue/libkqueue/common.h 
b/tests/sys/kqueue/libkqueue/common.h
index d621a8bf1e00..a92e544910ba 100644
--- a/tests/sys/kqueue/libkqueue/common.h
+++ b/tests/sys/kqueue/libkqueue/common.h
@@ -36,6 +36,8 @@
 #include <stdint.h>
 #include <sys/socket.h>
 #include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
 #include <unistd.h>
 
 #include <sys/event.h>
diff --git a/tests/sys/kqueue/libkqueue/vnode.c 
b/tests/sys/kqueue/libkqueue/vnode.c
index 8f4311e90745..b6c0915b2654 100644
--- a/tests/sys/kqueue/libkqueue/vnode.c
+++ b/tests/sys/kqueue/libkqueue/vnode.c
@@ -64,6 +64,64 @@ test_kevent_vnode_note_delete(void)
     success();
 }
 
+static void
+test_kevent_vnode_note_delete_fifo(void)
+{
+    const char *test_id = "kevent(EVFILT_VNODE, NOTE_DELETE, FIFO)";
+    const char *fifo_path = "./kqueue-fifo.tmp";
+    struct kevent kev;
+    int fd;
+    pid_t pid;
+
+    test_begin(test_id);
+
+    if (mkfifo(fifo_path, 0600) != 0)
+        err(1, "mkfifo");
+
+    pid = fork();
+    if (pid == -1)
+        err(1, "fork");
+
+    if (pid == 0) {
+        char buf[4];
+
+        fd = open(fifo_path, O_RDONLY);
+        if (fd == -1)
+            _exit(1);
+
+        while (read(fd, buf, sizeof(buf)) != 0) {
+        }
+
+        _exit(0);
+    }
+
+    sleep(1);
+    if (waitpid(pid, NULL, WNOHANG) == pid) {
+        unlink(fifo_path);
+        err(1, "open");
+    }
+
+    fd = open(fifo_path, O_WRONLY);
+    if (fd < 0) {
+        unlink(fifo_path);
+        err(1, "open");
+    }
+
+    EV_SET(&kev, fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_DELETE, 0, NULL);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) {
+        unlink(fifo_path);
+        err(1, "%s", test_id);
+    }
+
+    if (unlink(fifo_path) < 0)
+        err(1, "unlink");
+
+    kevent_cmp(&kev, kevent_get(kqfd));
+    close(fd);
+
+    success();
+}
+
 static void
 test_kevent_vnode_note_write(void)
 {
@@ -261,5 +319,6 @@ test_evfilt_vnode(void)
     test_kevent_vnode_note_attrib();
     test_kevent_vnode_note_rename();
     test_kevent_vnode_note_delete();
+    test_kevent_vnode_note_delete_fifo();
     close(kqfd);
 }

Reply via email to