summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2021-11-05 10:15:17 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-11-26 11:58:34 +0100
commit9082aa14e202f452618f4513876f0bf086525d8e (patch)
treeb57a5340a36da9d3d0eb610131a8f8736775de63 /sound
parentff7aa915782a4989a1c3aee5d879e78c2e99a624 (diff)
downloadlinux-stable-9082aa14e202f452618f4513876f0bf086525d8e.tar.gz
linux-stable-9082aa14e202f452618f4513876f0bf086525d8e.tar.bz2
linux-stable-9082aa14e202f452618f4513876f0bf086525d8e.zip
ALSA: timer: Unconditionally unlink slave instances, too
commit ffdd98277f0a1d15a67a74ae09bee713df4c0dbc upstream. 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'sound')
-rw-r--r--sound/core/timer.c13
1 files changed, 6 insertions, 7 deletions
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 41f4b33b18b9..90ad22e24a71 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -566,23 +566,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;
}
/*