ALSA: timer: Unconditionally unlink slave instances, too
authorTakashi Iwai <tiwai@suse.de>
Fri, 5 Nov 2021 09:15:17 +0000 (10:15 +0100)
committerTakashi Iwai <tiwai@suse.de>
Fri, 5 Nov 2021 10:27:27 +0000 (11:27 +0100)
Like the previous fix (commit c0317c0e8709 "ALSA: timer: Fix
use-after-free problem"), we have to unlink slave timer instances
immediately at snd_timer_stop(), too.  Otherwise it may leave a stale
entry in the list if the slave instance is freed before actually
running.

Cc: <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/20211105091517.21733-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/core/timer.c

index 4f9bab93195154a24cf8b6ba6df66a4faf258f77..b3214baa89193ae83fabc040fcc4fe328c8a5fc4 100644 (file)
@@ -665,23 +665,22 @@ static int snd_timer_stop1(struct snd_timer_instance *timeri, bool stop)
 static int snd_timer_stop_slave(struct snd_timer_instance *timeri, bool stop)
 {
        unsigned long flags;
+       bool running;
 
        spin_lock_irqsave(&slave_active_lock, flags);
-       if (!(timeri->flags & SNDRV_TIMER_IFLG_RUNNING)) {
-               spin_unlock_irqrestore(&slave_active_lock, flags);
-               return -EBUSY;
-       }
+       running = timeri->flags & SNDRV_TIMER_IFLG_RUNNING;
        timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
        if (timeri->timer) {
                spin_lock(&timeri->timer->lock);
                list_del_init(&timeri->ack_list);
                list_del_init(&timeri->active_list);
-               snd_timer_notify1(timeri, stop ? SNDRV_TIMER_EVENT_STOP :
-                                 SNDRV_TIMER_EVENT_PAUSE);
+               if (running)
+                       snd_timer_notify1(timeri, stop ? SNDRV_TIMER_EVENT_STOP :
+                                         SNDRV_TIMER_EVENT_PAUSE);
                spin_unlock(&timeri->timer->lock);
        }
        spin_unlock_irqrestore(&slave_active_lock, flags);
-       return 0;
+       return running ? 0 : -EBUSY;
 }
 
 /*