Skip to content

Commit b9dd212

Browse files
committed
ASoC: topology: Fix route memory corruption
Merge series from Amadeusz Sławiński <[email protected]>: Originally reported here: thesofproject/avs-topology-xml#22 (comment) There is various level of failure there, first of all when topology loads routes, it points directly into FW file, but it may be freed after topology load. After fixing the above, when avs driver parses topology it should allocate its own memory, as target strings can be shorter than needed. Also clean up soc_tplg_dapm_graph_elems_load() a bit.
2 parents e3209a1 + e0e7bc2 commit b9dd212

File tree

2 files changed

+37
-23
lines changed

2 files changed

+37
-23
lines changed

sound/soc/intel/avs/topology.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,8 +1545,8 @@ static int avs_route_load(struct snd_soc_component *comp, int index,
15451545
{
15461546
struct snd_soc_acpi_mach *mach = dev_get_platdata(comp->card->dev);
15471547
size_t len = SNDRV_CTL_ELEM_ID_NAME_MAXLEN;
1548-
char buf[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
15491548
int ssp_port, tdm_slot;
1549+
char *buf;
15501550

15511551
/* See parse_link_formatted_string() for dynamic naming when(s). */
15521552
if (!avs_mach_singular_ssp(mach))
@@ -1557,13 +1557,24 @@ static int avs_route_load(struct snd_soc_component *comp, int index,
15571557
return 0;
15581558
tdm_slot = avs_mach_ssp_tdm(mach, ssp_port);
15591559

1560+
buf = devm_kzalloc(comp->card->dev, len, GFP_KERNEL);
1561+
if (!buf)
1562+
return -ENOMEM;
15601563
avs_ssp_sprint(buf, len, route->source, ssp_port, tdm_slot);
1561-
strscpy((char *)route->source, buf, len);
1564+
route->source = buf;
1565+
1566+
buf = devm_kzalloc(comp->card->dev, len, GFP_KERNEL);
1567+
if (!buf)
1568+
return -ENOMEM;
15621569
avs_ssp_sprint(buf, len, route->sink, ssp_port, tdm_slot);
1563-
strscpy((char *)route->sink, buf, len);
1570+
route->sink = buf;
1571+
15641572
if (route->control) {
1573+
buf = devm_kzalloc(comp->card->dev, len, GFP_KERNEL);
1574+
if (!buf)
1575+
return -ENOMEM;
15651576
avs_ssp_sprint(buf, len, route->control, ssp_port, tdm_slot);
1566-
strscpy((char *)route->control, buf, len);
1577+
route->control = buf;
15671578
}
15681579

15691580
return 0;

sound/soc/soc-topology.c

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,6 +1021,7 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg,
10211021
struct snd_soc_tplg_hdr *hdr)
10221022
{
10231023
struct snd_soc_dapm_context *dapm = &tplg->comp->dapm;
1024+
const size_t maxlen = SNDRV_CTL_ELEM_ID_NAME_MAXLEN;
10241025
struct snd_soc_tplg_dapm_graph_elem *elem;
10251026
struct snd_soc_dapm_route *route;
10261027
int count, i;
@@ -1044,31 +1045,33 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg,
10441045
tplg->pos += sizeof(struct snd_soc_tplg_dapm_graph_elem);
10451046

10461047
/* validate routes */
1047-
if (strnlen(elem->source, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
1048-
SNDRV_CTL_ELEM_ID_NAME_MAXLEN) {
1048+
if ((strnlen(elem->source, maxlen) == maxlen) ||
1049+
(strnlen(elem->sink, maxlen) == maxlen) ||
1050+
(strnlen(elem->control, maxlen) == maxlen)) {
10491051
ret = -EINVAL;
10501052
break;
10511053
}
1052-
if (strnlen(elem->sink, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
1053-
SNDRV_CTL_ELEM_ID_NAME_MAXLEN) {
1054-
ret = -EINVAL;
1055-
break;
1056-
}
1057-
if (strnlen(elem->control, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
1058-
SNDRV_CTL_ELEM_ID_NAME_MAXLEN) {
1059-
ret = -EINVAL;
1054+
1055+
route->source = devm_kmemdup(tplg->dev, elem->source,
1056+
min(strlen(elem->source), maxlen),
1057+
GFP_KERNEL);
1058+
route->sink = devm_kmemdup(tplg->dev, elem->sink,
1059+
min(strlen(elem->sink), maxlen),
1060+
GFP_KERNEL);
1061+
if (!route->source || !route->sink) {
1062+
ret = -ENOMEM;
10601063
break;
10611064
}
10621065

1063-
route->source = elem->source;
1064-
route->sink = elem->sink;
1065-
1066-
/* set to NULL atm for tplg users */
1067-
route->connected = NULL;
1068-
if (strnlen(elem->control, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 0)
1069-
route->control = NULL;
1070-
else
1071-
route->control = elem->control;
1066+
if (strnlen(elem->control, maxlen) != 0) {
1067+
route->control = devm_kmemdup(tplg->dev, elem->control,
1068+
min(strlen(elem->control), maxlen),
1069+
GFP_KERNEL);
1070+
if (!route->control) {
1071+
ret = -ENOMEM;
1072+
break;
1073+
}
1074+
}
10721075

10731076
/* add route dobj to dobj_list */
10741077
route->dobj.type = SND_SOC_DOBJ_GRAPH;

0 commit comments

Comments
 (0)