⬢ DragonFlyBSD Kernel Audit
DF-5103 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/apple/fw/apple_fw.h
+++ b/sys/dev/apple/fw/apple_fw.h
@@ -64,6 +64,7 @@ struct apple_fw_softc {
 	device_t		sc_dev;
 	struct lock		sc_lock;
+	struct sysctl_ctx_list	sc_sctx;
 
 	/* OSDW state: 1 = macOS detected, 0 = other OS */
 	int			sc_osdw;
@@ -82,6 +83,6 @@ struct apple_fw_softc {
 
 /* apple_fw_dsm.c */
 void	apple_fw_discover_dsm_devices(device_t dev);
 
 /* apple_fw_sysctl.c */
-void	apple_fw_sysctl_init(device_t dev);
+void	apple_fw_sysctl_init(device_t dev, struct sysctl_ctx_list *ctx);
--- a/sys/dev/apple/fw/apple_fw.c
+++ b/sys/dev/apple/fw/apple_fw.c
@@ -122,9 +122,11 @@ apple_fw_attach(device_t dev)
 	sc->sc_dev = dev;
 	lockinit(&sc->sc_lock, "apple_fw", 0, LK_CANRECURSE);
+	sysctl_ctx_init(&sc->sc_sctx);
 
 	/* Enumerate Apple-specific SSDTs */
 	apple_fw_enumerate_ssdts(dev);
@@ -141,12 +143,17 @@ apple_fw_attach(device_t dev)
 	apple_fw_discover_dsm_devices(dev);
 
 	/* Register sysctl tree */
-	apple_fw_sysctl_init(dev);
+	apple_fw_sysctl_init(dev, &sc->sc_sctx);
 
 	return (0);
 }
 
 static int
 apple_fw_detach(device_t dev)
 {
 	struct apple_fw_softc *sc = device_get_softc(dev);
 
+	/*
+	 * Tear down the softc-backed sysctls BEFORE returning: newbus frees
+	 * the softc in device_set_driver() before it runs device_sysctl_fini(),
+	 * leaving a window where live oids point at freed memory.
+	 */
+	sysctl_ctx_free(&sc->sc_sctx);
 	lockuninit(&sc->sc_lock);
 	return (0);
 }
--- a/sys/dev/apple/fw/apple_fw_sysctl.c
+++ b/sys/dev/apple/fw/apple_fw_sysctl.c
@@ -14,6 +14,7 @@
 
 void
-apple_fw_sysctl_init(device_t dev)
+apple_fw_sysctl_init(device_t dev, struct sysctl_ctx_list *ctx)
 {
 	struct apple_fw_softc *sc = device_get_softc(dev);
@@ -25,8 +26,6 @@ apple_fw_sysctl_init(device_t dev)
 	char numbuf[8];
 	int i, j;
 
-	ctx = device_get_sysctl_ctx(dev);
 	tree = device_get_sysctl_tree(dev);
*** NOTE: with the driver-owned ctx, the oids should hang off the device
*** tree node obtained via device_get_sysctl_tree(dev) as before; only the
*** ctx that owns their lifetime changes.