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

Commit ee259c6c authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Revert "ASoC: dpcm: prevent snd_soc_dpcm use after free"



This reverts commit 71dc356a which is
commit a9764869779081e8bf24da07ac040e8f3efcf13a upstream.  It is needed
for Android but in this format, it breaks the ABI.  An ABI-stable
version will be added back to the tree in a later change.

Fixes: 71dc356a ("ASoC: dpcm: prevent snd_soc_dpcm use after free")
Cc: Will McVicker <willmcvicker@google.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
Change-Id: I11e394d57418cd35de0801e34ba479ffce3eb81d
parent 464464ac
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -1161,8 +1161,6 @@ struct snd_soc_card {
	u32 pop_time;

	void *drvdata;

	spinlock_t dpcm_lock;
};

/* SoC machine DAI configuration, glues a codec and cpu DAI together */
+0 −1
Original line number Diff line number Diff line
@@ -2786,7 +2786,6 @@ int snd_soc_register_card(struct snd_soc_card *card)
	mutex_init(&card->mutex);
	mutex_init(&card->dapm_mutex);
	mutex_init(&card->dapm_power_mutex);
	spin_lock_init(&card->dpcm_lock);

	ret = snd_soc_instantiate_card(card);
	if (ret != 0)
+7 −33
Original line number Diff line number Diff line
@@ -1282,7 +1282,6 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe,
		struct snd_soc_pcm_runtime *be, int stream)
{
	struct snd_soc_dpcm *dpcm;
	unsigned long flags;

	/* only add new dpcms */
	list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
@@ -1298,10 +1297,8 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe,
	dpcm->fe = fe;
	be->dpcm[stream].runtime = fe->dpcm[stream].runtime;
	dpcm->state = SND_SOC_DPCM_LINK_STATE_NEW;
	spin_lock_irqsave(&fe->card->dpcm_lock, flags);
	list_add(&dpcm->list_be, &fe->dpcm[stream].be_clients);
	list_add(&dpcm->list_fe, &be->dpcm[stream].fe_clients);
	spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);

	dev_dbg(fe->dev, "connected new DPCM %s path %s %s %s\n",
			stream ? "capture" : "playback",  fe->dai_link->name,
@@ -1347,7 +1344,6 @@ static void dpcm_be_reparent(struct snd_soc_pcm_runtime *fe,
void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream)
{
	struct snd_soc_dpcm *dpcm, *d;
	unsigned long flags;

	list_for_each_entry_safe(dpcm, d, &fe->dpcm[stream].be_clients, list_be) {
		dev_dbg(fe->dev, "ASoC: BE %s disconnect check for %s\n",
@@ -1367,10 +1363,8 @@ void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream)
#ifdef CONFIG_DEBUG_FS
		debugfs_remove(dpcm->debugfs_state);
#endif
		spin_lock_irqsave(&fe->card->dpcm_lock, flags);
		list_del(&dpcm->list_be);
		list_del(&dpcm->list_fe);
		spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
		kfree(dpcm);
	}
}
@@ -1624,13 +1618,10 @@ int dpcm_process_paths(struct snd_soc_pcm_runtime *fe,
void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream)
{
	struct snd_soc_dpcm *dpcm;
	unsigned long flags;

	spin_lock_irqsave(&fe->card->dpcm_lock, flags);
	list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
		dpcm->be->dpcm[stream].runtime_update =
						SND_SOC_DPCM_UPDATE_NO;
	spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
}

static void dpcm_be_dai_startup_unwind(struct snd_soc_pcm_runtime *fe,
@@ -2696,7 +2687,6 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
	struct snd_soc_dpcm *dpcm;
	enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
	int ret;
	unsigned long flags;

	dev_dbg(fe->dev, "ASoC: runtime %s open on FE %s\n",
			stream ? "capture" : "playback", fe->dai_link->name);
@@ -2766,13 +2756,11 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
	dpcm_be_dai_shutdown(fe, stream);
disconnect:
	/* disconnect any non started BEs */
	spin_lock_irqsave(&fe->card->dpcm_lock, flags);
	list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
		struct snd_soc_pcm_runtime *be = dpcm->be;
		if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START)
				dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
	}
	spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);

	return ret;
}
@@ -3368,10 +3356,7 @@ int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe,
{
	struct snd_soc_dpcm *dpcm;
	int state;
	int ret = 1;
	unsigned long flags;

	spin_lock_irqsave(&fe->card->dpcm_lock, flags);
	list_for_each_entry(dpcm, &be->dpcm[stream].fe_clients, list_fe) {

		if (dpcm->fe == fe)
@@ -3380,15 +3365,12 @@ int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe,
		state = dpcm->fe->dpcm[stream].state;
		if (state == SND_SOC_DPCM_STATE_START ||
			state == SND_SOC_DPCM_STATE_PAUSED ||
			state == SND_SOC_DPCM_STATE_SUSPEND) {
			ret = 0;
			break;
		}
			state == SND_SOC_DPCM_STATE_SUSPEND)
			return 0;
	}
	spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);

	/* it's safe to free/stop this BE DAI */
	return ret;
	return 1;
}
EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_free_stop);

@@ -3401,10 +3383,7 @@ int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
{
	struct snd_soc_dpcm *dpcm;
	int state;
	int ret = 1;
	unsigned long flags;

	spin_lock_irqsave(&fe->card->dpcm_lock, flags);
	list_for_each_entry(dpcm, &be->dpcm[stream].fe_clients, list_fe) {

		if (dpcm->fe == fe)
@@ -3414,15 +3393,12 @@ int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
		if (state == SND_SOC_DPCM_STATE_START ||
			state == SND_SOC_DPCM_STATE_PAUSED ||
			state == SND_SOC_DPCM_STATE_SUSPEND ||
			state == SND_SOC_DPCM_STATE_PREPARE) {
			ret = 0;
			break;
		}
			state == SND_SOC_DPCM_STATE_PREPARE)
			return 0;
	}
	spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);

	/* it's safe to change hw_params */
	return ret;
	return 1;
}
EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params);

@@ -3461,7 +3437,6 @@ static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe,
	struct snd_pcm_hw_params *params = &fe->dpcm[stream].hw_params;
	struct snd_soc_dpcm *dpcm;
	ssize_t offset = 0;
	unsigned long flags;

	/* FE state */
	offset += scnprintf(buf + offset, size - offset,
@@ -3489,7 +3464,6 @@ static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe,
		goto out;
	}

	spin_lock_irqsave(&fe->card->dpcm_lock, flags);
	list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
		struct snd_soc_pcm_runtime *be = dpcm->be;
		params = &dpcm->hw_params;
@@ -3510,7 +3484,7 @@ static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe,
				params_channels(params),
				params_rate(params));
	}
	spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);

out:
	return offset;
}