⬢ DragonFlyBSD Kernel Audit
DF-4773 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/apple/smc/smc.c
+++ b/sys/dev/apple/smc/smc.c
@@ -503,6 +503,24 @@
 apple_smc_detach(device_t dev)
 {
 	struct apple_smc_softc *sc = device_get_softc(dev);
+	struct sysctl_ctx_list *sysctlctx;
+
+	/*
+	 * Tear down the sysctl tree BEFORE freeing anything its handlers
+	 * dereference (sensor key arrays in smc_sysctl.c:179/219/224/229/234,
+	 * the softc, the backend resources).  The device sysctl context is
+	 * otherwise only destroyed by newbus at device_delete time -- long
+	 * after this function returns -- leaving every registered oid
+	 * pointing at freed state for the whole detach..delete window.
+	 *
+	 * sysctl_ctx_free() on an already-drained context is a no-op, so
+	 * the later device_sysctl_fini() call stays harmless.  This must
+	 * run in detach context (no sysctl lock held); a handler-side
+	 * removal would self-deadlock on the sysctllock.
+	 */
+	sysctlctx = device_get_sysctl_ctx(dev);
+	if (sysctlctx != NULL)
+		sysctl_ctx_free(sysctlctx);
 
 	apple_smc_free_sensors(sc->sc_temp_sensors,    sc->sc_temp_count);
 	apple_smc_free_sensors(sc->sc_dts_sensors,     sc->sc_dts_count);