⬢ DragonFlyBSD Kernel Audit
DF-4752 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/misc/gpio/gpio.c
+++ b/sys/dev/misc/gpio/gpio.c
@@ -70,6 +70,7 @@
 struct gpio_driver {
 	char	*name;
 	struct devfs_bitmap	unit_bitmap;
+	int	refs;
 	LIST_ENTRY(gpio_driver)	link;
 };
 
@@ -554,6 +555,7 @@
 			continue;
 
 		master_unit = devfs_clone_bitmap_get(&gpd->unit_bitmap, 0);
+		gpd->refs++;
 		break;
 	}
 	if (master_unit == -1) {
@@ -561,6 +563,7 @@
 		    M_TEMP, M_WAITOK | M_ZERO);
 		gpd->name = kstrdup(gp->driver_name, M_TEMP);
 		devfs_clone_bitmap_init(&gpd->unit_bitmap);
+		gpd->refs = 1;
 		master_unit = devfs_clone_bitmap_get(&gpd->unit_bitmap, 0);
 		LIST_INSERT_HEAD(&gpio_driverlist, gpd, link);
 	}
@@ -600,6 +603,8 @@
 	}
 
 	destroy_dev(gp->master_dev);
+	devfs_clone_bitmap_put(&DEVFS_CLONE_BITMAP(gpio),
+	    minor(gp->master_dev));
 
 	lockmgr(&gpio_lock, LK_EXCLUSIVE);
 	LIST_FOREACH(gpd, &gpio_driverlist, link) {
@@ -607,7 +612,11 @@
 			continue;
 
 		devfs_clone_bitmap_put(&gpd->unit_bitmap, gp->driver_unit);
-		LIST_REMOVE(gpd, link);
+		if (--gpd->refs == 0) {
+			LIST_REMOVE(gpd, link);
+			kfree(gpd->name, M_TEMP);
+			kfree(gpd, M_TEMP);
+		}
 		break;
 	}
 	lockmgr(&gpio_lock, LK_RELEASE);