[PATCH] ALSA: Use del_timer_sync() before freeing timer
From: "Steven Rostedt (Google)" rostedt@goodmis.org
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.
Cc: stable@vger.kernel.org Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Steven Rostedt (Google) rostedt@goodmis.org --- sound/synth/emux/emux.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c index 5ed8e36d2e04..a2ee78809cfb 100644 --- a/sound/synth/emux/emux.c +++ b/sound/synth/emux/emux.c @@ -131,10 +131,7 @@ int snd_emux_free(struct snd_emux *emu) 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);
On 10/26/22 20:12, Steven Rostedt wrote:
From: "Steven Rostedt (Google)" rostedt@goodmis.org
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.
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
sound/synth/emux/emux.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c index 5ed8e36d2e04..a2ee78809cfb 100644 --- a/sound/synth/emux/emux.c +++ b/sound/synth/emux/emux.c @@ -131,10 +131,7 @@ int snd_emux_free(struct snd_emux *emu) 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);
Hi Steven,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on tiwai-sound/for-next] [also build test WARNING on linux/master linus/master v6.1-rc2 next-20221027] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Steven-Rostedt/ALSA-Use-del_t... base: https://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git for-next patch link: https://lore.kernel.org/r/20221026231236.6834b551%40gandalf.local.home patch subject: [PATCH] ALSA: Use del_timer_sync() before freeing timer config: x86_64-allyesconfig compiler: gcc-11 (Debian 11.3.0-8) 11.3.0 reproduce (this is a W=1 build): # https://github.com/intel-lab-lkp/linux/commit/998e4b5d9793fb6deb720110f9038e... git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Steven-Rostedt/ALSA-Use-del_timer_sync-before-freeing-timer/20221027-111423 git checkout 998e4b5d9793fb6deb720110f9038ed04e822603 # save the config file mkdir build_dir && cp config build_dir/.config make W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash sound/synth/
If you fix the issue, kindly add following tag where applicable | Reported-by: kernel test robot lkp@intel.com
All warnings (new ones prefixed by >>):
sound/synth/emux/emux.c: In function 'snd_emux_free':
sound/synth/emux/emux.c:129:23: warning: unused variable 'flags' [-Wunused-variable]
129 | unsigned long flags; | ^~~~~
vim +/flags +129 sound/synth/emux/emux.c
^1da177e4c3f41 Linus Torvalds 2005-04-16 124 ^1da177e4c3f41 Linus Torvalds 2005-04-16 125 /* ^1da177e4c3f41 Linus Torvalds 2005-04-16 126 */ 03da312ac080b4 Takashi Iwai 2005-11-17 127 int snd_emux_free(struct snd_emux *emu) ^1da177e4c3f41 Linus Torvalds 2005-04-16 128 { ^1da177e4c3f41 Linus Torvalds 2005-04-16 @129 unsigned long flags; ^1da177e4c3f41 Linus Torvalds 2005-04-16 130 ^1da177e4c3f41 Linus Torvalds 2005-04-16 131 if (! emu) ^1da177e4c3f41 Linus Torvalds 2005-04-16 132 return -EINVAL; ^1da177e4c3f41 Linus Torvalds 2005-04-16 133 998e4b5d9793fb Steven Rostedt (Google 2022-10-26 134) del_timer_sync(&emu->tlist); ^1da177e4c3f41 Linus Torvalds 2005-04-16 135 ^1da177e4c3f41 Linus Torvalds 2005-04-16 136 snd_emux_proc_free(emu); ^1da177e4c3f41 Linus Torvalds 2005-04-16 137 snd_emux_delete_virmidi(emu); 3d774d5ef06697 Takashi Iwai 2017-06-09 138 #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) ^1da177e4c3f41 Linus Torvalds 2005-04-16 139 snd_emux_detach_seq_oss(emu); ^1da177e4c3f41 Linus Torvalds 2005-04-16 140 #endif ^1da177e4c3f41 Linus Torvalds 2005-04-16 141 snd_emux_detach_seq(emu); ^1da177e4c3f41 Linus Torvalds 2005-04-16 142 snd_emux_delete_hwdep(emu); ^1da177e4c3f41 Linus Torvalds 2005-04-16 143 snd_sf_free(emu->sflist); ^1da177e4c3f41 Linus Torvalds 2005-04-16 144 kfree(emu->voices); ^1da177e4c3f41 Linus Torvalds 2005-04-16 145 kfree(emu->name); ^1da177e4c3f41 Linus Torvalds 2005-04-16 146 kfree(emu); ^1da177e4c3f41 Linus Torvalds 2005-04-16 147 return 0; ^1da177e4c3f41 Linus Torvalds 2005-04-16 148 } ^1da177e4c3f41 Linus Torvalds 2005-04-16 149
On Thu, 27 Oct 2022 05:12:36 +0200, Steven Rostedt wrote:
From: "Steven Rostedt (Google)" rostedt@goodmis.org
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.
Cc: stable@vger.kernel.org Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Steven Rostedt (Google) rostedt@goodmis.org
Applied now with the fix of unused variable warning.
Thanks!
Takashi
sound/synth/emux/emux.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c index 5ed8e36d2e04..a2ee78809cfb 100644 --- a/sound/synth/emux/emux.c +++ b/sound/synth/emux/emux.c @@ -131,10 +131,7 @@ int snd_emux_free(struct snd_emux *emu) 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);
-- 2.35.1
On Thu, 27 Oct 2022 08:43:32 +0200 Takashi Iwai tiwai@suse.de wrote:
Applied now with the fix of unused variable warning.
Thanks Takashi!
-- Steve
participants (4)
-
Guenter Roeck
-
kernel test robot
-
Steven Rostedt
-
Takashi Iwai