ALSA: Use del_timer_sync() before freeing timer
commit f0a868788fcbf63cdab51f5adcf73b271ede8164 upstream. The current code for freeing the emux timer is extremely dangerous: CPU0 CPU1 ---- ---- snd_emux_timer_callback() snd_emux_free() spin_lock(&emu->voice_lock) del_timer(&emu->tlist); <-- returns immediately spin_unlock(&emu->voice_lock); [..] kfree(emu); spin_lock(&emu->voice_lock); [BOOM!] Instead just use del_timer_sync() which will wait for the timer to finish before continuing. No need to check if the timer is active or not when doing so. This doesn't fix the race of a possible re-arming of the timer, but at least it won't use the data that has just been freed. [ Fixed unused variable warning by tiwai ] Cc: stable@vger.kernel.org Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Link: https://lore.kernel.org/r/20221026231236.6834b551@gandalf.local.home Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
819f7dfd04
commit
af52f24032
@ -138,15 +138,10 @@ EXPORT_SYMBOL(snd_emux_register);
|
||||
*/
|
||||
int snd_emux_free(struct snd_emux *emu)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (! emu)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&emu->voice_lock, flags);
|
||||
if (emu->timer_active)
|
||||
del_timer(&emu->tlist);
|
||||
spin_unlock_irqrestore(&emu->voice_lock, flags);
|
||||
del_timer_sync(&emu->tlist);
|
||||
|
||||
snd_emux_proc_free(emu);
|
||||
snd_emux_delete_virmidi(emu);
|
||||
|
Loading…
x
Reference in New Issue
Block a user