The branch main has been updated by markj:

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

commit 62c4afcb460457bae055d756b24d5b5e5535903c
Author:     Mark Johnston <[email protected]>
AuthorDate: 2026-08-24 15:20:32 +0000
Commit:     Mark Johnston <[email protected]>
CommitDate: 2026-08-25 15:46:24 +0000

    dsp: Fix a potential use-after-free in dsp_oss_syncstart()
    
    This function has a loop where it attempts to lock all channels in a
    group.  If doing so would block, it releases all locks, sleeps for a
    bit, and tries again.  However, once the syncgroup lock is dropped,
    nothing prevents the syncgroup structure from being freed.
    
    Fix the inner loop: after waking up, break out of it unconditionally and
    start everything again.  I think the old code was also buggy and not
    well-exercised: after waking up we'd continue to try and continue
    locking channels.  Then we'd try again from the beginning and fail to
    lock the channels we had already locked.
    
    Approved by:    so
    Security:       FreeBSD-SA-26:58.sound
    Security:       CVE-2026-58091
    Reported by:    Hazley Samsudin of GovTech CSG
    Reviewed by:    christos
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D58912
---
 sys/dev/sound/pcm/channel.h |  9 +++++----
 sys/dev/sound/pcm/dsp.c     | 17 ++++++-----------
 2 files changed, 11 insertions(+), 15 deletions(-)

diff --git a/sys/dev/sound/pcm/channel.h b/sys/dev/sound/pcm/channel.h
index aac6ab368625..2f71f0708c8e 100644
--- a/sys/dev/sound/pcm/channel.h
+++ b/sys/dev/sound/pcm/channel.h
@@ -57,10 +57,11 @@ struct pcmchan_syncmember;
 extern struct mtx snd_pcm_syncgroups_mtx;
 extern SLIST_HEAD(pcm_synclist, pcmchan_syncgroup) snd_pcm_syncgroups;
 
-#define PCM_SG_LOCK()      mtx_lock(&snd_pcm_syncgroups_mtx)
-#define PCM_SG_TRYLOCK()    mtx_trylock(&snd_pcm_syncgroups_mtx)
-#define PCM_SG_UNLOCK()            mtx_unlock(&snd_pcm_syncgroups_mtx)
-#define PCM_SG_LOCKASSERT(arg) mtx_assert(&snd_pcm_syncgroups_mtx, arg)
+#define PCM_SG_LOCKPTR()       (&snd_pcm_syncgroups_mtx)
+#define PCM_SG_LOCK()          mtx_lock(PCM_SG_LOCKPTR())
+#define PCM_SG_TRYLOCK()       mtx_trylock(PCM_SG_LOCKPTR())
+#define PCM_SG_UNLOCK()                mtx_unlock(PCM_SG_LOCKPTR())
+#define PCM_SG_LOCKASSERT(arg) mtx_assert(PCM_SG_LOCKPTR(), arg)
 
 /**
  * @brief Specifies an audio device sync group
diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c
index 18d679c81433..c92c55b02cff 100644
--- a/sys/dev/sound/pcm/dsp.c
+++ b/sys/dev/sound/pcm/dsp.c
@@ -2684,14 +2684,11 @@ dsp_oss_syncstart(int sg_id)
        struct pcmchan_syncmember *sm, *sm_tmp;
        struct pcmchan_syncgroup *sg;
        struct pcm_channel *c;
-       int ret, needlocks;
+       int ret;
 
-       /* Get the synclists lock */
        PCM_SG_LOCK();
-
        do {
                ret = 0;
-               needlocks = 0;
 
                /* Search for syncgroup by ID */
                SLIST_FOREACH(sg, &snd_pcm_syncgroups, link) {
@@ -2728,16 +2725,14 @@ dsp_oss_syncstart(int sg_id)
                                }
 
                                /** @todo Is PRIBIO correct/ */
-                               ret = msleep(sm, &snd_pcm_syncgroups_mtx,
+                               ret = msleep(sm, PCM_SG_LOCKPTR(),
                                    PRIBIO | PCATCH, "pcmsg", timo);
-                               if (ret == EINTR || ret == ERESTART)
-                                       break;
-
-                               needlocks = 1;
-                               ret = 0; /* Assumes ret == EAGAIN... */
+                               if (ret == EAGAIN)
+                                       ret = 0;
+                               break;
                        }
                }
-       } while (needlocks && ret == 0);
+       } while (ret == 0 && sm != NULL);
 
        /* Proceed only if no errors encountered. */
        if (ret == 0) {

Reply via email to