⬢ DragonFlyBSD Kernel Audit
DF-2399 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/agp/agp.c
+++ b/sys/dev/agp/agp.c
@@ -778,8 +778,8 @@
 	device_t dev = kdev->si_drv1;
 	struct agp_softc *sc = device_get_softc(dev);
 
-	if (!sc->as_isopen) {
-		sc->as_isopen = 1;
+	sc->as_isopen++;	/* refcount, one device_busy per open fd (DF-2399) */
+	if (sc->as_isopen == 1) {
 		device_busy(dev);
 	}
 
@@ -797,17 +797,17 @@
 	/*
 	 * Clear the GATT and force release on last close
 	 */
-	while ((mem = TAILQ_FIRST(&sc->as_memory)) != NULL) {
-		if (mem->am_is_bound)
-			AGP_UNBIND_MEMORY(dev, mem);
-		AGP_FREE_MEMORY(dev, mem);
-	}
-	if (sc->as_state == AGP_ACQUIRE_USER)
-		agp_release_helper(dev, AGP_ACQUIRE_USER);
-	if (sc->as_isopen) {
-		sc->as_isopen = 0;
+	if (sc->as_isopen == 1) {
+		while ((mem = TAILQ_FIRST(&sc->as_memory)) != NULL) {
+			if (mem->am_is_bound)
+				AGP_UNBIND_MEMORY(dev, mem);
+			AGP_FREE_MEMORY(dev, mem);
+		}
+		if (sc->as_state == AGP_ACQUIRE_USER)
+			agp_release_helper(dev, AGP_ACQUIRE_USER);
+	}
+	if (sc->as_isopen > 0 && --sc->as_isopen == 0)
 		device_unbusy(dev);
-	}
 
 	return 0;
 }