Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6add7233 authored by Laxminath Kasam's avatar Laxminath Kasam
Browse files

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: default avatarLaxminath Kasam <lkasam@codeaurora.org>
parent beb1eeec
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -150,6 +150,8 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask,
	
	if (snd_BUG_ON(!card || !id))
		return;
	if (card->shutdown)
		return;
	read_lock(&card->ctl_files_rwlock);
#if IS_ENABLED(CONFIG_SND_MIXER_OSS)
	card->mixer_oss_change_count++;
+18 −12
Original line number Diff line number Diff line
@@ -813,6 +813,22 @@ int snd_pcm_new_internal(struct snd_card *card, const char *id, int device,
}
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)
{
	struct snd_pcm_substream *substream, *substream_next;
@@ -835,6 +851,7 @@ static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
		kfree(setup);
	}
#endif
	free_pcm_kctl(pstr);
}

static int snd_pcm_free(struct snd_pcm *pcm)
@@ -1149,18 +1166,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
			break;
		}
		snd_unregister_device(devtype, pcm->card, pcm->device);
		if (pcm->streams[cidx].chmap_kctl) {
			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;
		}
		free_pcm_kctl(&pcm->streams[cidx]);
	}
	mutex_unlock(&pcm->open_mutex);
 unlock: