]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ASoC: topology: Check PCM and DAI name strings before use
authorCássio Gabriel <cassiogabrielcontato@gmail.com>
Thu, 4 Jun 2026 03:10:58 +0000 (00:10 -0300)
committerMark Brown <broonie@kernel.org>
Thu, 11 Jun 2026 19:47:42 +0000 (20:47 +0100)
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>
sound/soc/soc-topology.c

index 85679c8e022999a9a710422fd4bcdf20d60724e5..35cbe29d227589fcee5fa178dfa463af9c078495 100644 (file)
@@ -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) {