git: d26b3c9b3415 - stable/15 - cuse: Fix cdevpriv bugs in cuse_client_open()

From: Christos Margiolis <christos_at_FreeBSD.org>
Date: Thu, 20 Nov 2025 13:31:39 UTC
The branch stable/15 has been updated by christos:

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

commit d26b3c9b341522090885ec362aa5cd1f90eb57c9
Author:     Christos Margiolis <christos@FreeBSD.org>
AuthorDate: 2025-11-13 12:11:06 +0000
Commit:     Christos Margiolis <christos@FreeBSD.org>
CommitDate: 2025-11-20 13:28:14 +0000

    cuse: Fix cdevpriv bugs in cuse_client_open()
    
    If devfs_set_cdevpriv() fails, we will panic when we enter the
    cuse_client_free() callback, for a number of reasons:
    
    - pcc->server is not yet assigned, so we'll use a NULL pointer.
    - pcc has not yet been added to the pcs->hcli TAILQ, but we'll try to
      remove it.
    - pccmd->sx and pccmd->cv are not yet initializated, but we'll try to
      destroy them.
    
    Even if we'd get past all these somehow, we'd still get two errors in
    the devfs_set_cdevpriv() failure block:
    
    - We'll unref the server twice, once in cuse_client_free(), and again in
      cuse_client_open().
    - A double-free panic, since we'd be trying to free(pcc), which has
      already been freed in cuse_client_free().
    
    Fix all those issues. While here, also get rid of some unnecessary
    devfs_clear_cdevpriv().
    
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Reviewed by:    kib
    Differential Revision:  https://reviews.freebsd.org/D53708
    
    (cherry picked from commit 634e578ac7b0a03ae25427c723c0da27e894a340)
---
 sys/fs/cuse/cuse.c | 18 +++++-------------
 1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/sys/fs/cuse/cuse.c b/sys/fs/cuse/cuse.c
index b2524324584a..b914b2d5017c 100644
--- a/sys/fs/cuse/cuse.c
+++ b/sys/fs/cuse/cuse.c
@@ -1516,13 +1516,6 @@ cuse_client_open(struct cdev *dev, int fflags, int devtype, struct thread *td)
 	}
 
 	pcc = malloc(sizeof(*pcc), M_CUSE, M_WAITOK | M_ZERO);
-	if (devfs_set_cdevpriv(pcc, &cuse_client_free)) {
-		printf("Cuse: Cannot set cdevpriv.\n");
-		/* drop reference on server */
-		cuse_server_unref(pcs);
-		free(pcc, M_CUSE);
-		return (ENOMEM);
-	}
 	pcc->fflags = fflags;
 	pcc->server_dev = pcsd;
 	pcc->server = pcs;
@@ -1553,10 +1546,12 @@ cuse_client_open(struct cdev *dev, int fflags, int devtype, struct thread *td)
 	}
 	cuse_server_unlock(pcs);
 
-	if (error) {
-		devfs_clear_cdevpriv();	/* XXX bugfix */
+	if (error != 0)
 		return (error);
-	}
+
+	if ((error = devfs_set_cdevpriv(pcc, &cuse_client_free)) != 0)
+		return (error);
+
 	pccmd = &pcc->cmds[CUSE_CMD_OPEN];
 
 	cuse_cmd_lock(pccmd);
@@ -1575,9 +1570,6 @@ cuse_client_open(struct cdev *dev, int fflags, int devtype, struct thread *td)
 
 	cuse_cmd_unlock(pccmd);
 
-	if (error)
-		devfs_clear_cdevpriv();	/* XXX bugfix */
-
 	return (error);
 }