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
This commit is contained in:
Christos Margiolis
2025-11-13 13:11:06 +01:00
parent e4b31985b5
commit 634e578ac7
+5 -13
View File
@@ -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);
}