⬢ DragonFlyBSD Kernel Audit
DF-5057 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/raid/mlx/mlx.c
+++ b/sys/dev/raid/mlx/mlx.c
@@ -783,6 +783,11 @@
 	    error = EBUSY;
 	    goto detach_out;
 	}
+
+	/* DF-5057: block new opens while we flush/delete; mlx_flush sleeps
+	 * (polled round-trip), so mlxd_open's MLX_STATE_SHUTDOWN gate must
+	 * be raised for the whole window, not just around the delete. */
+	sc->mlx_state |= MLX_STATE_SHUTDOWN;
 	
 	/* flush controller */
 	if (mlx_flush(sc)) {
@@ -796,6 +801,9 @@
 	dr->ms_disk = NULL;
 
     detach_out:
+	/* single-drive detach: the controller keeps running afterwards */
+	sc->mlx_state &= ~MLX_STATE_SHUTDOWN;
+
 	if (error) {
 	    kprintf("failed\n");
 	} else {
--- a/sys/dev/raid/mlx/mlx_disk.c
+++ b/sys/dev/raid/mlx/mlx_disk.c
@@ -40,6 +40,7 @@
 #include <sys/disk.h>
 #include <sys/dtype.h>
 #include <sys/rman.h>
+#include <sys/thread2.h>
 
 #include "mlx_compat.h"
 #include "mlxio.h"
@@ -294,6 +295,17 @@
 
     debug_called(1);
 
+    /* DF-5057: last-chance gate.  MLX_DETACH_DRIVE checks MLXD_OPEN and
+     * then sleeps in mlx_flush before device_delete_child; an open that
+     * lands in that window leaves si_drv1 dangling once the softc is
+     * freed.  (Complete fix: also drain in-flight bios before destroy.) */
+    crit_enter();
+    if (sc->mlxd_flags & MLXD_OPEN) {
+	crit_exit();
+	return (EBUSY);
+    }
+    crit_exit();
+
     devstat_remove_entry(&sc->mlxd_stats);
     disk_destroy(&sc->mlxd_disk);