⬢ DragonFlyBSD Kernel Audit
DF-4156 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/sound/pci/maestro.c
+++ b/sys/dev/sound/pci/maestro.c
@@ -1920,8 +1920,17 @@
 	return 0;
 
  bad:
-	if (codec != NULL)
+	if (codec != NULL) {
+		/*
+		 * If mixer_init() succeeded, the 0666 /dev/mixerN cdev it
+		 * created still holds this codec as its devinfo.  Tear the
+		 * mixer down (destroy_dev + free snd_mixer) before freeing
+		 * the codec, mirroring the pcm_unregister() unwind order.
+		 */
+		if (ess->codec == codec)
+			mixer_uninit(dev);
 		ac97_destroy(codec);
+	}
 	if (ih != NULL)
 		bus_teardown_intr(dev, irq, ih);
 	if (irq != NULL)
@@ -1966,6 +1975,10 @@
 		return r;
 	}
 
+	/* pcm_unregister() already ran mixer_uninit(); the codec is ours. */
+	if (ess->codec != NULL)
+		ac97_destroy(ess->codec);
+
 	agg_lock(ess);
 	agg_power(ess, PCI_POWERSTATE_D3);
 	agg_unlock(ess);