⬢ DragonFlyBSD Kernel Audit
DF-2477 / fix.diff
← back to finding ↓ download raw
--- /home/maxx/dfbsd/dfbsd/sys/dev/disk/md/md.c	2026-06-29 12:51:18.000000000 +0000
+++ /tmp/opencode/fixtree/sys/dev/disk/md/md.c	2026-10-24 09:24:22.917124000 +0000
@@ -132,7 +132,9 @@
 
 	sc = dev->si_drv1;
 	lwkt_gettoken(&sc->tok);
-	if (sc->unit + 1 == mdunits)
+	/* cap the auto-create-on-open convenience; explicit creation
+	 * via the ioctls remains unlimited for root */
+	if (sc->unit + 1 == mdunits && mdunits < 256)
 		mdcreate_malloc();
 	atomic_add_int(&refcnt, 1);
 	lwkt_reltoken(&sc->tok);
@@ -478,6 +480,20 @@
 	 * itself.
 	 */
 	TAILQ_FOREACH_MUTABLE(sc, &mdlist, link, sc_temp) {
+		/*
+		 * Drain the device FIRST: destroy_dev() blocks until racing
+		 * mdopen/mdclose have completed and prevents any new open.
+		 * Only then re-check refcnt before freeing -- an mdopen that
+		 * slipped past the unlocked check above either completes
+		 * before the drain (refcnt!=0 -> EBUSY, nothing freed) or is
+		 * rejected by the destroyed cdev.
+		 */
+		if (sc->dev != NULL) {
+			destroy_dev(sc->dev);
+			sc->dev = NULL;
+		}
+		if (atomic_fetchadd_int(&refcnt, 0) != 0)
+			return EBUSY;
 		for (secno = 0; secno < sc->nsecp; secno++) {
 			if ((u_int)(uintptr_t)sc->secp[secno] > 255)
 				kfree(sc->secp[secno], M_MDSECT);