--- 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;