mirror of
https://git.proxmox.com/git/mirror_ubuntu-kernels.git
synced 2025-11-25 16:33:36 +00:00
ASoC: topology: Fix route memory corruption
Merge series from Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>: Originally reported here: https://github.com/thesofproject/avs-topology-xml/issues/22#issuecomment-2127892605 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.
This commit is contained in:
commit
b9dd212b14
@ -1545,8 +1545,8 @@ static int avs_route_load(struct snd_soc_component *comp, int index,
|
||||
{
|
||||
struct snd_soc_acpi_mach *mach = dev_get_platdata(comp->card->dev);
|
||||
size_t len = SNDRV_CTL_ELEM_ID_NAME_MAXLEN;
|
||||
char buf[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
int ssp_port, tdm_slot;
|
||||
char *buf;
|
||||
|
||||
/* See parse_link_formatted_string() for dynamic naming when(s). */
|
||||
if (!avs_mach_singular_ssp(mach))
|
||||
@ -1557,13 +1557,24 @@ static int avs_route_load(struct snd_soc_component *comp, int index,
|
||||
return 0;
|
||||
tdm_slot = avs_mach_ssp_tdm(mach, ssp_port);
|
||||
|
||||
buf = devm_kzalloc(comp->card->dev, len, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
avs_ssp_sprint(buf, len, route->source, ssp_port, tdm_slot);
|
||||
strscpy((char *)route->source, buf, len);
|
||||
route->source = buf;
|
||||
|
||||
buf = devm_kzalloc(comp->card->dev, len, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
avs_ssp_sprint(buf, len, route->sink, ssp_port, tdm_slot);
|
||||
strscpy((char *)route->sink, buf, len);
|
||||
route->sink = buf;
|
||||
|
||||
if (route->control) {
|
||||
buf = devm_kzalloc(comp->card->dev, len, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
avs_ssp_sprint(buf, len, route->control, ssp_port, tdm_slot);
|
||||
strscpy((char *)route->control, buf, len);
|
||||
route->control = buf;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@ -1021,6 +1021,7 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg,
|
||||
struct snd_soc_tplg_hdr *hdr)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = &tplg->comp->dapm;
|
||||
const size_t maxlen = SNDRV_CTL_ELEM_ID_NAME_MAXLEN;
|
||||
struct snd_soc_tplg_dapm_graph_elem *elem;
|
||||
struct snd_soc_dapm_route *route;
|
||||
int count, i;
|
||||
@ -1044,31 +1045,33 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg,
|
||||
tplg->pos += sizeof(struct snd_soc_tplg_dapm_graph_elem);
|
||||
|
||||
/* validate routes */
|
||||
if (strnlen(elem->source, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
|
||||
SNDRV_CTL_ELEM_ID_NAME_MAXLEN) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
if (strnlen(elem->sink, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
|
||||
SNDRV_CTL_ELEM_ID_NAME_MAXLEN) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
if (strnlen(elem->control, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
|
||||
SNDRV_CTL_ELEM_ID_NAME_MAXLEN) {
|
||||
if ((strnlen(elem->source, maxlen) == maxlen) ||
|
||||
(strnlen(elem->sink, maxlen) == maxlen) ||
|
||||
(strnlen(elem->control, maxlen) == maxlen)) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
route->source = elem->source;
|
||||
route->sink = elem->sink;
|
||||
route->source = devm_kmemdup(tplg->dev, elem->source,
|
||||
min(strlen(elem->source), maxlen),
|
||||
GFP_KERNEL);
|
||||
route->sink = devm_kmemdup(tplg->dev, elem->sink,
|
||||
min(strlen(elem->sink), maxlen),
|
||||
GFP_KERNEL);
|
||||
if (!route->source || !route->sink) {
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
/* set to NULL atm for tplg users */
|
||||
route->connected = NULL;
|
||||
if (strnlen(elem->control, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 0)
|
||||
route->control = NULL;
|
||||
else
|
||||
route->control = elem->control;
|
||||
if (strnlen(elem->control, maxlen) != 0) {
|
||||
route->control = devm_kmemdup(tplg->dev, elem->control,
|
||||
min(strlen(elem->control), maxlen),
|
||||
GFP_KERNEL);
|
||||
if (!route->control) {
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* add route dobj to dobj_list */
|
||||
route->dobj.type = SND_SOC_DOBJ_GRAPH;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user