⬢ DragonFlyBSD Kernel Audit
DF-4227 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/smbus/cyapa/cyapa.c
+++ b/sys/dev/smbus/cyapa/cyapa.c
@@ -547,6 +547,19 @@
 {
 	struct cyapa_softc *sc = (struct cyapa_softc *)device_get_softc(dev);
 
+	/*
+	 * DF-4227: refuse to detach while userland holds the device open.
+	 * Otherwise the cdev entry points keep operating on a softc that
+	 * vanishes with devclass teardown (devclass_get_softc() returns
+	 * NULL) and, after kldunload, on module ops memory that has been
+	 * freed.
+	 */
+	if (sc->count != 0)
+		return (EBUSY);
+
+	/* Wake any readers blocked in cyaparead(). */
+	wakeup(&sc->blocked);
+
 #if 0
 	/*
 	 * Cleanup input event tracking
@@ -620,6 +633,9 @@
 	int didread;
 	size_t n;
 
+	if (sc == NULL)
+		return (ENXIO);
+
 	/*
 	 * If buffer is empty, load a new event if it is ready
 	 */
@@ -793,6 +809,9 @@
 	size_t n;
 	uint8_t c0;
 
+	if (sc == NULL)
+		return (ENXIO);
+
 again:
 	/*
 	 * Copy data from userland.  This will also cross-over the end
@@ -1070,6 +1089,11 @@
 	struct knote *kn = ap->a_kn;
 	struct klist *klist;
 
+	if (sc == NULL) {
+		ap->a_result = ENXIO;
+		return (0);
+	}
+
 	switch(kn->kn_filter) {
 	case EVFILT_READ:
 		kn->kn_fop = &cyapa_filtops;