The branch main has been updated by christos:

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

commit 0432b2183f25ddba7e13a33adf1dd6f9563b0bd1
Author:     Christos Margiolis <chris...@freebsd.org>
AuthorDate: 2025-05-29 10:24:28 +0000
Commit:     Christos Margiolis <chris...@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);

Reply via email to