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

Takashi Iwai tiwai at suse.de
Tue May 23 20:14:07 CEST 2017


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?

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.


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
@@ -2047,6 +2047,8 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour)
 EXPORT_SYMBOL_GPL(snd_soc_set_dmi_name);
 #endif /* CONFIG_DMI */
 
+static void soc_cleanup_card_resources(struct snd_card *scard);
+
 static int snd_soc_instantiate_card(struct snd_soc_card *card)
 {
 	struct snd_soc_codec *codec;
@@ -2228,6 +2230,8 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
 	}
 
 	card->instantiated = 1;
+	card->snd_card->private_data = card;
+	card->snd_card->private_free = soc_cleanup_card_resources;
 	snd_soc_dapm_sync(&card->dapm);
 	mutex_unlock(&card->mutex);
 	mutex_unlock(&client_mutex);
@@ -2278,8 +2282,9 @@ static int soc_probe(struct platform_device *pdev)
 	return snd_soc_register_card(card);
 }
 
-static int soc_cleanup_card_resources(struct snd_soc_card *card)
+static void soc_cleanup_card_resources(struct snd_card *scard)
 {
+	struct snd_soc_card *card = scard->private_data;
 	struct snd_soc_pcm_runtime *rtd;
 
 	/* make sure any delayed work runs */
@@ -2299,10 +2304,6 @@ static int soc_cleanup_card_resources(struct snd_soc_card *card)
 	/* remove the card */
 	if (card->remove)
 		card->remove(card);
-
-	snd_card_free(card->snd_card);
-	return 0;
-
 }
 
 /* removes a socdev */
@@ -2887,7 +2888,7 @@ int snd_soc_unregister_card(struct snd_soc_card *card)
 	if (card->instantiated) {
 		card->instantiated = false;
 		snd_soc_dapm_shutdown(card);
-		soc_cleanup_card_resources(card);
+		snd_card_free(card->snd_card);
 		dev_dbg(card->dev, "ASoC: Unregistered card '%s'\n", card->name);
 	}
 


More information about the Alsa-devel mailing list