⬢ DragonFlyBSD Kernel Audit
DF-3228 / fix.diff
← back to finding ↓ download raw
--- a/sys/vfs/fuse/fuse_device.c
+++ b/sys/vfs/fuse/fuse_device.c
@@ -40,8 +40,16 @@
 {
 	struct fuse_mount *fmp = data;
 
-	if (!fuse_cdevpriv_close(fmp))
+	if (fmp->devvp) {
+		/* mounted: kill it if still alive and drop the open ref */
+		fuse_cdevpriv_close(fmp);
 		fuse_mount_free(fmp);
+	} else {
+		/* never mounted: refcnt==1, no locks, no cred -- just free
+		 * (the old code leaked this object: fuse_cdevpriv_close()
+		 * returned ENODEV and skipped fuse_mount_free()). */
+		kfree(fmp, M_TEMP);
+	}
 }
 
 static int
@@ -49,12 +57,17 @@
 {
 	struct fuse_mount *fmp;
 	struct file *fp = ap->a_fpp ? *ap->a_fpp : NULL;
+	int error;
 
 	fmp = kmalloc(sizeof(*fmp), M_TEMP, M_WAITOK | M_ZERO);
 	KKASSERT(fmp);
 
 	refcount_init(&fmp->refcnt, 1);
-	devfs_set_cdevpriv(fp, fmp, fuse_cdevpriv_dtor);
+	error = devfs_set_cdevpriv(fp, fmp, fuse_cdevpriv_dtor);
+	if (error) {
+		kfree(fmp, M_TEMP);
+		return error;
+	}
 	fuse_dbg("open %s\n", ap->a_head.a_dev->si_name);
 
 	return 0;