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:
Amadeusz Sławiński 2020-03-27 16:47:24 -04:00 committed by Mark Brown
parent ccfc531695
commit abc3caac24
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0

View File

@ -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 */