ASoC: Fix freed memory access of pcm stream kctl
Consider sound card instantiate fails due to audrx init failure. In such case, all dais/ctls are de-registered and freed. But as part of it, access to unregistered ctls for pcm_chmap and similar controls result in crash. Ctls are freed at disconnection but the disconnect is called only when it was registered. CRs-Fixed: 1038054 Change-Id: Ief8817b4ec000c058d46aa021977b7c6003c0011 Signed-off-by: Laxminath Kasam <lkasam@codeaurora.org>
This commit is contained in:
parent
293a2b36f2
commit
482c8b19a8
2 changed files with 20 additions and 12 deletions
|
@ -160,6 +160,8 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask,
|
||||||
|
|
||||||
if (snd_BUG_ON(!card || !id))
|
if (snd_BUG_ON(!card || !id))
|
||||||
return;
|
return;
|
||||||
|
if (card->shutdown)
|
||||||
|
return;
|
||||||
read_lock(&card->ctl_files_rwlock);
|
read_lock(&card->ctl_files_rwlock);
|
||||||
#if IS_ENABLED(CONFIG_SND_MIXER_OSS)
|
#if IS_ENABLED(CONFIG_SND_MIXER_OSS)
|
||||||
card->mixer_oss_change_count++;
|
card->mixer_oss_change_count++;
|
||||||
|
|
|
@ -849,6 +849,22 @@ int snd_pcm_new_internal(struct snd_card *card, const char *id, int device,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(snd_pcm_new_internal);
|
EXPORT_SYMBOL(snd_pcm_new_internal);
|
||||||
|
|
||||||
|
static void free_pcm_kctl(struct snd_pcm_str *pstr)
|
||||||
|
{
|
||||||
|
if (pstr->chmap_kctl) {
|
||||||
|
snd_ctl_remove(pstr->pcm->card, pstr->chmap_kctl);
|
||||||
|
pstr->chmap_kctl = NULL;
|
||||||
|
}
|
||||||
|
if (pstr->vol_kctl) {
|
||||||
|
snd_ctl_remove(pstr->pcm->card, pstr->vol_kctl);
|
||||||
|
pstr->vol_kctl = NULL;
|
||||||
|
}
|
||||||
|
if (pstr->usr_kctl) {
|
||||||
|
snd_ctl_remove(pstr->pcm->card, pstr->usr_kctl);
|
||||||
|
pstr->usr_kctl = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
|
static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
|
||||||
{
|
{
|
||||||
struct snd_pcm_substream *substream, *substream_next;
|
struct snd_pcm_substream *substream, *substream_next;
|
||||||
|
@ -871,6 +887,7 @@ static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
|
||||||
kfree(setup);
|
kfree(setup);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
free_pcm_kctl(pstr);
|
||||||
if (pstr->substream_count)
|
if (pstr->substream_count)
|
||||||
put_device(&pstr->dev);
|
put_device(&pstr->dev);
|
||||||
}
|
}
|
||||||
|
@ -1135,18 +1152,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
|
||||||
for (cidx = 0; cidx < 2; cidx++) {
|
for (cidx = 0; cidx < 2; cidx++) {
|
||||||
if (!pcm->internal)
|
if (!pcm->internal)
|
||||||
snd_unregister_device(&pcm->streams[cidx].dev);
|
snd_unregister_device(&pcm->streams[cidx].dev);
|
||||||
if (pcm->streams[cidx].chmap_kctl) {
|
free_pcm_kctl(&pcm->streams[cidx]);
|
||||||
snd_ctl_remove(pcm->card, pcm->streams[cidx].chmap_kctl);
|
|
||||||
pcm->streams[cidx].chmap_kctl = NULL;
|
|
||||||
}
|
|
||||||
if (pcm->streams[cidx].vol_kctl) {
|
|
||||||
snd_ctl_remove(pcm->card, pcm->streams[cidx].vol_kctl);
|
|
||||||
pcm->streams[cidx].vol_kctl = NULL;
|
|
||||||
}
|
|
||||||
if (pcm->streams[cidx].usr_kctl) {
|
|
||||||
snd_ctl_remove(pcm->card, pcm->streams[cidx].usr_kctl);
|
|
||||||
pcm->streams[cidx].usr_kctl = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
mutex_unlock(&pcm->open_mutex);
|
mutex_unlock(&pcm->open_mutex);
|
||||||
mutex_unlock(®ister_mutex);
|
mutex_unlock(®ister_mutex);
|
||||||
|
|
Loading…
Add table
Reference in a new issue