aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristos Margiolis <christos@FreeBSD.org>2025-11-13 12:11:06 +0000
committerChristos Margiolis <christos@FreeBSD.org>2025-11-13 12:11:06 +0000
commit634e578ac7b0a03ae25427c723c0da27e894a340 (patch)
tree0aa4db1bee7a8c542ee23ce351ddfc3f8457cfcf
parente4b31985b54b626b2bbf486a82dd789f3dd381db (diff)
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
-rw-r--r--sys/fs/cuse/cuse.c18
1 files 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);
}