[alsa-devel] BUG: double free of PCM structure upon module removal

Takashi Iwai tiwai at suse.de
Wed May 24 08:39:28 CEST 2017


On Wed, 24 May 2017 08:31:39 +0200,
Robert Jarzmik wrote:
> 
> Takashi Iwai <tiwai at suse.de> writes:
> 
> > On Tue, 23 May 2017 19:14:05 +0200,
> > Mark Brown wrote:
> >> 
> >> On Tue, May 23, 2017 at 06:46:58PM +0200, Robert Jarzmik wrote:
> >> 
> >> > Did you notice the same behavior on other platforms, and if not would you have a
> >> > hint why it happens to me ?
> >> 
> >> This is the only report I've seen, sorry.  It's not ringing any bells
> >> immediately either - I'll have a think.
> >
> > What's the problem?  soc_free_pcm_runtime() just calls kfree() of rtd,
> > but it's not called in snd_pcm_free(), isn't it?
> You're right, it's not called, but it's dereferenced.
> The way I see it, what happens is :
>  - soc_free_pcm_runtime() calls kfree(rtd)
>    - ... guess ...
>    - some other call does a kmalloc() which gets the same bucket as rtd
>    - this other call puts data in the previous rtd
>      => in my backtrace, this data is 35343848, which looks like the string
>      "548H"
>  - snd_pcm_free() calls soc_pcm_free()
>  - soc_pcm_free() uses in the for_each loop rtd->card->component_dev_list, and
>    triggers the BUG.

I see, so my patch should cure such a case.

> > In anyway the calls there look in a wrong order.  Basically we should
> > start with snd_card_free() to sync with the whole operation finishes,
> > then release everything.  Below is an untested patch to do that.
> With you patch, the bug is gone in my first 3 tries.

I think the patch below is simpler and has the same effect.
If this works for you, I'll submit the proper patch.


thanks,

Takashi

---
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -2286,6 +2286,8 @@ static int soc_cleanup_card_resources(struct snd_soc_card *card)
 	list_for_each_entry(rtd, &card->rtd_list, list)
 		flush_delayed_work(&rtd->delayed_work);
 
+	snd_card_free(card->snd_card);
+
 	/* remove and free each DAI */
 	soc_remove_dai_links(card);
 	soc_remove_pcm_runtimes(card);
@@ -2300,7 +2302,6 @@ static int soc_cleanup_card_resources(struct snd_soc_card *card)
 	if (card->remove)
 		card->remove(card);
 
-	snd_card_free(card->snd_card);
 	return 0;
 
 }


More information about the Alsa-devel mailing list