summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCássio Gabriel <cassiogabrielcontato@gmail.com>2026-06-04 00:10:58 -0300
committerMark Brown <broonie@kernel.org>2026-06-11 20:47:42 +0100
commitb7e44d1986d6671342c19b82192189ca5db5dab7 (patch)
tree4a11d31c113633b88dbd26d87d52c114a8ffb05d
parent890b61d3a8c980ec46d88b9ab1b35e3ddd4f1593 (diff)
ASoC: topology: Check PCM and DAI name strings before use
Topology objects store several PCM and DAI names in fixed-size UAPI arrays. Other topology parser paths validate these fields with bounded strnlen() checks before using them as C strings, but the PCM and DAI paths still pass some fixed-size arrays directly to strlen(), devm_kstrdup(), DAI lookup, and diagnostic prints. A malformed topology blob with a non-NUL-terminated PCM, DAI, or stream capability name can therefore make the parser read past the end of the fixed-size field. Reject unterminated PCM and DAI name fields before consuming them as C strings. Fixes: 64527e8a3529 ("ASoC: topology: Add FE DAIs dynamically") Fixes: acfc7d46cddc ("ASoC: topology: Add FE DAI links dynamically") Fixes: 0038be9a84dc ("ASoC: topology: Add support for configuring existing BE DAIs") Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com> Link: https://patch.msgid.link/20260604-asoc-topology-check-pcm-dai-names-v1-1-e1b0f6f7c2ce@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/soc-topology.c37
1 files changed, 34 insertions, 3 deletions
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c
index 85679c8e0229..35cbe29d2275 100644
--- a/sound/soc/soc-topology.c
+++ b/sound/soc/soc-topology.c
@@ -1326,9 +1326,24 @@ static int soc_tplg_dapm_complete(struct soc_tplg *tplg)
return ret;
}
+static int soc_tplg_check_name(const char *name)
+{
+ if (strnlen(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
+ SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
+ return -EINVAL;
+
+ return 0;
+}
+
static int set_stream_info(struct soc_tplg *tplg, struct snd_soc_pcm_stream *stream,
struct snd_soc_tplg_stream_caps *caps)
{
+ int ret;
+
+ ret = soc_tplg_check_name(caps->name);
+ if (ret)
+ return ret;
+
stream->stream_name = devm_kstrdup(tplg->dev, caps->name, GFP_KERNEL);
if (!stream->stream_name)
return -ENOMEM;
@@ -1380,7 +1395,11 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg,
if (dai_drv == NULL)
return -ENOMEM;
- if (strlen(pcm->dai_name)) {
+ ret = soc_tplg_check_name(pcm->dai_name);
+ if (ret)
+ goto err;
+
+ if (pcm->dai_name[0]) {
dai_drv->name = devm_kstrdup(tplg->dev, pcm->dai_name, GFP_KERNEL);
if (!dai_drv->name) {
ret = -ENOMEM;
@@ -1486,7 +1505,11 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg,
if (tplg->ops)
link->dobj.unload = tplg->ops->link_unload;
- if (strlen(pcm->pcm_name)) {
+ ret = soc_tplg_check_name(pcm->pcm_name);
+ if (ret)
+ goto err;
+
+ if (pcm->pcm_name[0]) {
link->name = devm_kstrdup(tplg->dev, pcm->pcm_name, GFP_KERNEL);
link->stream_name = devm_kstrdup(tplg->dev, pcm->pcm_name, GFP_KERNEL);
if (!link->name || !link->stream_name) {
@@ -1496,7 +1519,11 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg,
}
link->id = le32_to_cpu(pcm->pcm_id);
- if (strlen(pcm->dai_name)) {
+ ret = soc_tplg_check_name(pcm->dai_name);
+ if (ret)
+ goto err;
+
+ if (pcm->dai_name[0]) {
link->cpus->dai_name = devm_kstrdup(tplg->dev, pcm->dai_name, GFP_KERNEL);
if (!link->cpus->dai_name) {
ret = -ENOMEM;
@@ -1848,6 +1875,10 @@ static int soc_tplg_dai_config(struct soc_tplg *tplg,
memset(&dai_component, 0, sizeof(dai_component));
+ ret = soc_tplg_check_name(d->dai_name);
+ if (ret)
+ return ret;
+
dai_component.dai_name = d->dai_name;
dai = snd_soc_find_dai(&dai_component);
if (!dai) {