⬢ DragonFlyBSD Kernel Audit
DF-3733 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/raid/ciss/ciss.c
+++ b/sys/dev/raid/ciss/ciss.c
@@ -425,9 +425,13 @@
 
     sc = device_get_softc(dev);
     sc->ciss_dev = dev;
     lockinit(&sc->ciss_lock, "cissmtx", 0, LK_CANRECURSE);
-    callout_init_mp(&sc->ciss_periodic);
+    /* Serialize the periodic callout with ciss_lock: with _lk the callout
+     * subsystem holds ciss_lock while running/stopping/re-arming the
+     * callout, so callout_stop() in ciss_free() cannot race the re-arm
+     * at the tail of ciss_periodic(). */
+    callout_init_lk(&sc->ciss_periodic, &sc->ciss_lock);
 
     /*
      * Do PCI-specific init.
      */
@@ -482,9 +482,11 @@
 
     /*
      * Start the heartbeat routine and event chain.
      */
-    ciss_periodic(sc);
+    lockmgr(&sc->ciss_lock, LK_EXCLUSIVE);
+    ciss_periodic(sc);
+    lockmgr(&sc->ciss_lock, LK_RELEASE);
 
     /*
      * Create the control device.
      */
@@ -3379,10 +3379,9 @@
     struct ciss_request	*cr = NULL;
     struct ciss_command	*cc = NULL;
     int			error = 0;
 
-    lockmgr(&sc->ciss_lock, LK_EXCLUSIVE);
-    debug_called(1);
+    debug_called(1);
 
     /*
      * Check the adapter heartbeat.
      */
@@ -3392,10 +3392,9 @@
 	      sc->ciss_heartbeat, sc->ciss_heart_attack);
 	if (sc->ciss_heart_attack == 3) {
 	    ciss_printf(sc, "ADAPTER HEARTBEAT FAILED\n");
 	    ciss_disable_adapter(sc);
-	    lockmgr(&sc->ciss_lock, LK_RELEASE);
-	    return;
+	    return;
 	}
     } else {
 	sc->ciss_heartbeat = sc->ciss_cfg->heartbeat;
 	sc->ciss_heart_attack = 0;
@@ -3427,9 +3427,8 @@
     if (!(sc->ciss_flags & CISS_FLAG_NOTIFY_OK)) {
 	debug(0, "(re)starting Event Notify chain");
 	ciss_notify_event(sc);
     }
-    lockmgr(&sc->ciss_lock, LK_RELEASE);
 
     /*
      * Reschedule.
      */