⬢ DragonFlyBSD Kernel Audit
DF-4986 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/raid/mfi/mfi_pci.c
+++ b/sys/dev/raid/mfi/mfi_pci.c
@@ -226,10 +226,17 @@ mfi_pci_attach(device_t dev)
 	u_int irq_flags;
 
 	sc = device_get_softc(dev);
 	bzero(sc, sizeof(*sc));
 	sc->mfi_dev = dev;
+
+	/*
+	 * Initialize the watchdog callout before anything can fail:
+	 * every failure unwind below (including the DMA-tag failure that
+	 * runs before mfi_attach()) goes through mfi_free(), which does
+	 * callout_terminate(&sc->mfi_watchdog_callout).  Terminating a
+	 * never-initialized (bzero'd) callout trips
+	 * KKASSERT(cc->flags & CALLOUT_DID_INIT) in kern_timeout.c and
+	 * panics INVARIANTS kernels (stock X86_64_GENERIC).
+	 */
+	callout_init_mp(&sc->mfi_watchdog_callout);
+
 	m = mfi_find_ident(dev);
 	sc->mfi_flags = m->flags;
 
 	/* Verify that the adapter can be set up in PCI space */
--- a/sys/dev/raid/mfi/mfi.c
+++ b/sys/dev/raid/mfi/mfi.c
@@ -738,8 +738,7 @@ mfi_attach(struct mfi_softc *sc)
 	bus_generic_attach(sc->mfi_dev);
 
 	/* Start the timeout watchdog */
-	callout_init_mp(&sc->mfi_watchdog_callout);
-	callout_reset(&sc->mfi_watchdog_callout, mfi_cmd_timeout * hz,
+	callout_reset(&sc->mfi_watchdog_callout, mfi_cmd_timeout * hz,
 	    mfi_timeout, sc);
 
 	return (0);