From ac9477fbb8ce907734ea34aa33e0c2ad7bf39913 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Mon, 31 May 2021 20:33:43 +0000 Subject: [PATCH] audio(4): Insert mixers and audioctls into sc_files on open too. This is necessary so that on detach we set file->dying before any operations, particularly audioclose, try to acquire a psref by the time the audio softc is gone. Candidate fix for PR kern/56164. --- sys/dev/audio/audio.c | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/sys/dev/audio/audio.c b/sys/dev/audio/audio.c index d09ed4ad663b..4a61c5344e79 100644 --- a/sys/dev/audio/audio.c +++ b/sys/dev/audio/audio.c @@ -1373,7 +1373,8 @@ audiodetach(device_t self, int flags) * Here, we no longer need any locks to traverse sc_files. */ while ((file = SLIST_FIRST(&sc->sc_files)) != NULL) { - audio_unlink(sc, file); + if (file->ptrack || file->rtrack) + audio_unlink(sc, file); } pmf_event_deregister(self, PMFE_AUDIO_VOLUME_DOWN, @@ -1788,6 +1789,11 @@ audioclose(struct file *fp) sc = audio_sc_acquire_fromfile(file, &sc_ref); SDT_PROBE2(audio, file, close, start, file, sc); if (sc) { + mutex_enter(sc->sc_lock); + mutex_enter(sc->sc_intr_lock); + SLIST_REMOVE(&sc->sc_files, file, audio_file, entry); + mutex_exit(sc->sc_intr_lock); + mutex_exit(sc->sc_lock); switch (AUDIODEV(dev)) { case SOUND_DEVICE: case AUDIO_DEVICE: @@ -2712,10 +2718,6 @@ audio_unlink(struct audio_softc *sc, audio_file_t *file) device_active(sc->sc_dev, DVA_SYSTEM); - mutex_enter(sc->sc_intr_lock); - SLIST_REMOVE(&sc->sc_files, file, audio_file, entry); - mutex_exit(sc->sc_intr_lock); - if (file->ptrack) { TRACET(3, file->ptrack, "dropframes=%" PRIu64, file->ptrack->dropframes); @@ -3633,7 +3635,17 @@ audioctl_open(dev_t dev, struct audio_softc *sc, int flags, int ifmt, af->sc = sc; af->dev = dev; - /* Not necessary to insert sc_files. */ + mutex_enter(sc->sc_lock); + if (sc->sc_dying) { + mutex_exit(sc->sc_lock); + kmem_free(af, sizeof(*af)); + fd_abort(curproc, fp, fd); + return ENXIO; + } + mutex_enter(sc->sc_intr_lock); + SLIST_INSERT_HEAD(&sc->sc_files, af, entry); + mutex_exit(sc->sc_intr_lock); + mutex_exit(sc->sc_lock); error = fd_clone(fp, fd, flags, &audio_fileops, af); KASSERTMSG(error == EMOVEFD, "error=%d", error); @@ -8281,6 +8293,18 @@ mixer_open(dev_t dev, struct audio_softc *sc, int flags, int ifmt, af->sc = sc; af->dev = dev; + mutex_enter(sc->sc_lock); + if (sc->sc_dying) { + mutex_exit(sc->sc_lock); + kmem_free(af, sizeof(*af)); + fd_abort(curproc, fp, fd); + return ENXIO; + } + mutex_enter(sc->sc_intr_lock); + SLIST_INSERT_HEAD(&sc->sc_files, af, entry); + mutex_exit(sc->sc_intr_lock); + mutex_exit(sc->sc_lock); + error = fd_clone(fp, fd, flags, &audio_fileops, af); KASSERT(error == EMOVEFD);