git: 0432b2183f25 - main - snd_dummy: Make callout stopping more robust
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 29 May 2025 10:25:27 UTC
The branch main has been updated by christos: URL: https://cgit.FreeBSD.org/src/commit/?id=0432b2183f25ddba7e13a33adf1dd6f9563b0bd1 commit 0432b2183f25ddba7e13a33adf1dd6f9563b0bd1 Author: Christos Margiolis <christos@FreeBSD.org> AuthorDate: 2025-05-29 10:24:28 +0000 Commit: Christos Margiolis <christos@FreeBSD.org> CommitDate: 2025-05-29 10:25:18 +0000 snd_dummy: Make callout stopping more robust If the callout gets rescheduled during detach, we might access freed pcm_channel resources in dummy_chan_io(), which will cause a panic similar to this: panic: ASan: Invalid access, 8-byte read at 0xfffffe00479f65d8, UMAUseAfterFree(fd) cpuid = 1 time = 1747433047 KDB: stack backtrace: db_trace_self_wrapper() at db_trace_self_wrapper+0xa5/frame 0xfffffe0046a8d730 kdb_backtrace() at kdb_backtrace+0xc6/frame 0xfffffe0046a8d890 vpanic() at vpanic+0x226/frame 0xfffffe0046a8da30 panic() at panic+0xb5/frame 0xfffffe0046a8db00 kasan_code_name() at kasan_code_name/frame 0xfffffe0046a8dbd0 __mtx_lock_flags() at __mtx_lock_flags+0xd3/frame 0xfffffe0046a8dcc0 chn_intr() at chn_intr+0x3d/frame 0xfffffe0046a8dce0 dummy_chan_io() at dummy_chan_io+0x9c/frame 0xfffffe0046a8dd10 softclock_call_cc() at softclock_call_cc+0x2bb/frame 0xfffffe0046a8de80 softclock_thread() at softclock_thread+0x162/frame 0xfffffe0046a8def0 fork_exit() at fork_exit+0xa3/frame 0xfffffe0046a8df30 fork_trampoline() at fork_trampoline+0xe/frame 0xfffffe0046a8df30 Reviewed by: adrian Differential Revision: https://reviews.freebsd.org/D50386 --- sys/dev/sound/dummy.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/sys/dev/sound/dummy.c b/sys/dev/sound/dummy.c index ae2af6fa61ed..1e2a81f40103 100644 --- a/sys/dev/sound/dummy.c +++ b/sys/dev/sound/dummy.c @@ -65,6 +65,7 @@ struct dummy_softc { struct dummy_chan chans[DUMMY_NCHAN]; struct callout callout; struct mtx *lock; + bool stopped; }; static bool @@ -92,6 +93,9 @@ dummy_chan_io(void *arg) struct dummy_chan *ch; int i = 0; + if (sc->stopped) + return; + /* Do not reschedule if no channel is running. */ if (!dummy_active(sc)) return; @@ -108,7 +112,8 @@ dummy_chan_io(void *arg) chn_intr(ch->chan); snd_mtxlock(sc->lock); } - callout_schedule(&sc->callout, 1); + if (!sc->stopped) + callout_schedule(&sc->callout, 1); } static int @@ -195,6 +200,11 @@ dummy_chan_trigger(kobj_t obj, void *data, int go) snd_mtxlock(sc->lock); + if (sc->stopped) { + snd_mtxunlock(sc->lock); + return (0); + } + switch (go) { case PCMTRIG_START: ch->ptr = 0; @@ -345,8 +355,11 @@ dummy_detach(device_t dev) struct dummy_softc *sc = device_get_softc(dev); int err; - err = pcm_unregister(dev); + snd_mtxlock(sc->lock); + sc->stopped = true; + snd_mtxunlock(sc->lock); callout_drain(&sc->callout); + err = pcm_unregister(dev); snd_mtxfree(sc->lock); return (err);