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