⬢ DragonFlyBSD Kernel Audit
DF-5106 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/sound/pci/emu10kx-midi.c
+++ b/sys/dev/sound/pci/emu10kx-midi.c
@@ -222,12 +222,27 @@ static int
 emu_midi_detach(device_t dev)
 {
 	struct emu_midi_softc *scp;
+	int rv;
 
 	scp = device_get_softc(dev);
-	mpu401_uninit(scp->mpu);
+	/*
+	 * mpu401_uninit() fails (ENXIO) when the MIDI cdev created by
+	 * midi_init() is still open: in that case it does NOT free the
+	 * mpu401, the snd_midi and the /dev/midiN.M cdev.  Returning
+	 * success here lets newbus kfree() our softc while those objects
+	 * still reference it (m->cookie, m->si, the mpu401 callout), which
+	 * leaves a use-after-free reachable through the still-open cdev and
+	 * panics the kernel when the module is unloaded (stale m->si).
+	 * Propagate the failure so detach is aborted instead.
+	 */
+	rv = mpu401_uninit(scp->mpu);
+	if (rv != 0)
+		return (rv);
 	emu_intr_unregister(scp->card, scp->ihandle);
 	lockuninit(&scp->lock);
 	return (0);
 }