ASoC: topology: Add missing memory checks
kstrdup is an allocation function and it can fail, so its return value should be checked and handled appropriately. In order to check all cases, we need to modify set_stream_info to return a value, so check that everything went correctly when doing kstrdup(). Later add proper checks and error handlers. Signed-off-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com> Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Link: https://lore.kernel.org/r/20200327204729.397-2-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
ccfc531695
commit
abc3caac24
|
@ -1766,10 +1766,13 @@ static int soc_tplg_dapm_complete(struct soc_tplg *tplg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void set_stream_info(struct snd_soc_pcm_stream *stream,
|
||||
static int set_stream_info(struct snd_soc_pcm_stream *stream,
|
||||
struct snd_soc_tplg_stream_caps *caps)
|
||||
{
|
||||
stream->stream_name = kstrdup(caps->name, GFP_KERNEL);
|
||||
if (!stream->stream_name)
|
||||
return -ENOMEM;
|
||||
|
||||
stream->channels_min = le32_to_cpu(caps->channels_min);
|
||||
stream->channels_max = le32_to_cpu(caps->channels_max);
|
||||
stream->rates = le32_to_cpu(caps->rates);
|
||||
|
@ -1777,6 +1780,8 @@ static void set_stream_info(struct snd_soc_pcm_stream *stream,
|
|||
stream->rate_max = le32_to_cpu(caps->rate_max);
|
||||
stream->formats = le64_to_cpu(caps->formats);
|
||||
stream->sig_bits = le32_to_cpu(caps->sig_bits);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_dai_flags(struct snd_soc_dai_driver *dai_drv,
|
||||
|
@ -1812,20 +1817,29 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg,
|
|||
if (dai_drv == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
if (strlen(pcm->dai_name))
|
||||
if (strlen(pcm->dai_name)) {
|
||||
dai_drv->name = kstrdup(pcm->dai_name, GFP_KERNEL);
|
||||
if (!dai_drv->name) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
dai_drv->id = le32_to_cpu(pcm->dai_id);
|
||||
|
||||
if (pcm->playback) {
|
||||
stream = &dai_drv->playback;
|
||||
caps = &pcm->caps[SND_SOC_TPLG_STREAM_PLAYBACK];
|
||||
set_stream_info(stream, caps);
|
||||
ret = set_stream_info(stream, caps);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (pcm->capture) {
|
||||
stream = &dai_drv->capture;
|
||||
caps = &pcm->caps[SND_SOC_TPLG_STREAM_CAPTURE];
|
||||
set_stream_info(stream, caps);
|
||||
ret = set_stream_info(stream, caps);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (pcm->compress)
|
||||
|
@ -1835,11 +1849,7 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg,
|
|||
ret = soc_tplg_dai_load(tplg, dai_drv, pcm, NULL);
|
||||
if (ret < 0) {
|
||||
dev_err(tplg->comp->dev, "ASoC: DAI loading failed\n");
|
||||
kfree(dai_drv->playback.stream_name);
|
||||
kfree(dai_drv->capture.stream_name);
|
||||
kfree(dai_drv->name);
|
||||
kfree(dai_drv);
|
||||
return ret;
|
||||
goto err;
|
||||
}
|
||||
|
||||
dai_drv->dobj.index = tplg->index;
|
||||
|
@ -1860,6 +1870,14 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg,
|
|||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
kfree(dai_drv->playback.stream_name);
|
||||
kfree(dai_drv->capture.stream_name);
|
||||
kfree(dai_drv->name);
|
||||
kfree(dai_drv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1916,11 +1934,20 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg,
|
|||
if (strlen(pcm->pcm_name)) {
|
||||
link->name = kstrdup(pcm->pcm_name, GFP_KERNEL);
|
||||
link->stream_name = kstrdup(pcm->pcm_name, GFP_KERNEL);
|
||||
if (!link->name || !link->stream_name) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
link->id = le32_to_cpu(pcm->pcm_id);
|
||||
|
||||
if (strlen(pcm->dai_name))
|
||||
if (strlen(pcm->dai_name)) {
|
||||
link->cpus->dai_name = kstrdup(pcm->dai_name, GFP_KERNEL);
|
||||
if (!link->cpus->dai_name) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
link->codecs->name = "snd-soc-dummy";
|
||||
link->codecs->dai_name = "snd-soc-dummy-dai";
|
||||
|
@ -2436,13 +2463,17 @@ static int soc_tplg_dai_config(struct soc_tplg *tplg,
|
|||
if (d->playback) {
|
||||
stream = &dai_drv->playback;
|
||||
caps = &d->caps[SND_SOC_TPLG_STREAM_PLAYBACK];
|
||||
set_stream_info(stream, caps);
|
||||
ret = set_stream_info(stream, caps);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (d->capture) {
|
||||
stream = &dai_drv->capture;
|
||||
caps = &d->caps[SND_SOC_TPLG_STREAM_CAPTURE];
|
||||
set_stream_info(stream, caps);
|
||||
ret = set_stream_info(stream, caps);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (d->flag_mask)
|
||||
|
@ -2454,10 +2485,15 @@ static int soc_tplg_dai_config(struct soc_tplg *tplg,
|
|||
ret = soc_tplg_dai_load(tplg, dai_drv, NULL, dai);
|
||||
if (ret < 0) {
|
||||
dev_err(tplg->comp->dev, "ASoC: DAI loading failed\n");
|
||||
return ret;
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
kfree(dai_drv->playback.stream_name);
|
||||
kfree(dai_drv->capture.stream_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* load physical DAI elements */
|
||||
|
|
Loading…
Reference in New Issue