The branch stable/14 has been updated by asomers:

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

commit b797d07560a76d790c0256a70d65b2b684ab6ee7
Author:     Alan Somers <asom...@freebsd.org>
AuthorDate: 2024-12-13 14:00:20 +0000
Commit:     Alan Somers <asom...@freebsd.org>
CommitDate: 2025-01-20 16:36:02 +0000

    fusefs: FUSE_NOTIFY_INVAL_* must busy the mountpoint
    
    Unusually, the FUSE_NOTIFY_INVAL_INODE and FUSE_NOTIFY_INVAL_ENTRY
    messages are fully asynchronous.  The server sends them to the kernel
    unsolicited.  That means that unlike every other fuse message coming
    from the server, these two arrive to a potentially unbusied mountpoint.
    So they must explicitly busy it.  Otherwise a page fault could result if
    the mountpoint were being unmounted.
    
    Reported by:    jsml4thwwbid6...@protonmail.com
    
    (cherry picked from commit 989998529387b4d98dfaa6c499ad88b006f78de8)
---
 sys/fs/fuse/fuse_device.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/sys/fs/fuse/fuse_device.c b/sys/fs/fuse/fuse_device.c
index 5df9be59ce36..2fd43bc742dc 100644
--- a/sys/fs/fuse/fuse_device.c
+++ b/sys/fs/fuse/fuse_device.c
@@ -440,7 +440,6 @@ fuse_device_write(struct cdev *dev, struct uio *uio, int 
ioflag)
        err = devfs_get_cdevpriv((void **)&data);
        if (err != 0)
                return (err);
-       mp = data->mp;
 
        if (uio->uio_resid < sizeof(struct fuse_out_header)) {
                SDT_PROBE2(fusefs, , device, trace, 1,
@@ -543,6 +542,13 @@ fuse_device_write(struct cdev *dev, struct uio *uio, int 
ioflag)
        } else if (ohead.unique == 0){
                /* unique == 0 means asynchronous notification */
                SDT_PROBE1(fusefs, , device, fuse_device_write_notify, &ohead);
+               mp = data->mp;
+               vfs_ref(mp);
+               err = vfs_busy(mp, 0);
+               vfs_rel(mp);
+               if (err)
+                       return (err);
+
                switch (ohead.error) {
                case FUSE_NOTIFY_INVAL_ENTRY:
                        err = fuse_internal_invalidate_entry(mp, uio);
@@ -567,6 +573,7 @@ fuse_device_write(struct cdev *dev, struct uio *uio, int 
ioflag)
                        /* Not implemented */
                        err = ENOSYS;
                }
+               vfs_unbusy(mp);
        } else {
                /* no callback at all! */
                SDT_PROBE1(fusefs, , device, fuse_device_write_missing_ticket, 

Reply via email to