The branch main has been updated by christos:

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

commit d83e42234f76504a1ff7f4309ad629b6644bfb16
Author:     giacomo <[email protected]>
AuthorDate: 2026-07-15 12:10:54 +0000
Commit:     Christos Margiolis <[email protected]>
CommitDate: 2026-07-24 11:20:09 +0000

    cuse: Fix server reference leak in cuse_client_open()
    
    If the server is closing (or the device node is going away), or if
    devfs_set_cdevpriv() fails, cuse_client_open() returns with the server
    reference taken at the top of the function still held and the newly
    allocated client still linked on pcs->hcli.  Since cuse_client_free()
    has not been registered as the cdevpriv destructor at that point,
    nothing ever undoes this work: every open() that races the is_closing
    window permanently leaks one server reference and one cuse_client.
    
    A leaked reference is fatal on server exit: cuse_server_free()
    busy-waits in an uninterruptible pause("W", hz) loop until pcs->refs
    drops to 1, which now never happens, so the exiting server process
    (e.g. virtual_oss(8)) is left wedged in state "D", immune to SIGKILL,
    cuse.ko is pinned (kldunload hangs too), and only a reboot recovers.
    
    Before 634e578ac7b0 the is_closing error path dropped the reference by
    calling devfs_clear_cdevpriv(), which ran the cuse_client_free()
    destructor.  That commit moved devfs_set_cdevpriv() after the
    is_closing check to fix the panic paths, but left both error returns
    without any cleanup.
    
    Fix by calling cuse_client_free() directly on both error paths.  The
    client is fully constructed and linked on pcs->hcli at these points,
    which is exactly the state cuse_client_free() expects.
    
    PR:             296291
    Fixes:          634e578ac7b0 ("cuse: Fix cdevpriv bugs in 
cuse_client_open()")
    Assisted-By:    Claude Opus 4.8 (claude-opus-4-8)
    Signed-off-by:  giacomo <[email protected]>
    MFC after:      2 weeks
    Reviewed by:    christos
    Pull-Request:   https://github.com/freebsd/freebsd-src/pull/2324
---
 sys/fs/cuse/cuse.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/sys/fs/cuse/cuse.c b/sys/fs/cuse/cuse.c
index 8f67c4b5572b..ef786d125c15 100644
--- a/sys/fs/cuse/cuse.c
+++ b/sys/fs/cuse/cuse.c
@@ -1546,11 +1546,19 @@ cuse_client_open(struct cdev *dev, int fflags, int 
devtype, struct thread *td)
        }
        cuse_server_unlock(pcs);
 
-       if (error != 0)
+       /*
+        * On error, free the client and unref the server, so that the
+        * exiting server process does not become unkillable.
+        */
+       if (error != 0) {
+               cuse_client_free(pcc);
                return (error);
+       }
 
-       if ((error = devfs_set_cdevpriv(pcc, &cuse_client_free)) != 0)
+       if ((error = devfs_set_cdevpriv(pcc, &cuse_client_free)) != 0) {
+               cuse_client_free(pcc);
                return (error);
+       }
 
        pccmd = &pcc->cmds[CUSE_CMD_OPEN];
 

Reply via email to