git: b760fa5bf0e9 - stable/14 - snd_dummy: Make callout stopping more robust

From: Christos Margiolis <christos_at_FreeBSD.org>
Date: Thu, 29 May 2025 22:10:09 UTC
The branch stable/14 has been updated by christos:

URL: https://cgit.FreeBSD.org/src/commit/?id=b760fa5bf0e965210f8df05cef9ff46c68377d2a

commit b760fa5bf0e965210f8df05cef9ff46c68377d2a
Author:     Christos Margiolis <christos@FreeBSD.org>
AuthorDate: 2025-05-29 10:24:28 +0000
Commit:     Christos Margiolis <christos@FreeBSD.org>
CommitDate: 2025-05-29 22:09:40 +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
    
    (cherry picked from commit 0432b2183f25ddba7e13a33adf1dd6f9563b0bd1)
---
 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 89e22a5ceb44..eeb6bd4ad4ad 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);