Merge series "ASoC: Sanity checks and soc-topology updates" from Cezary Rojewski <cezary.rojewski@intel.com>:

Couple of soc-topology related changes and a use-after-free fix. Said fix
and two sanity checks for soc-topology lead the way. While the
use-after-free is quite obvious, the sanity checks are here to cover for
cases where user malformed the topology file -or- access to filesystem
somehow got interrupted during copy operation. We shouldn't be reading
outside the file boundary.

Afterward a change to soc_tplg_add_kcontrol(): device being passed to
soc_tplg_add_dcontrol() from comp->dev to tplg->dev which corrects
dev_xxx() invoked later on.
Also, device used for topology memory allocations from component->dev to
component->card->dev so memory gets freed each time card device (usually
platform device) is removed rather than the component device what may
happen less frequently.

Dummy component gets smarter and no longer overrides hw_params if
there are other components accociated with related struct
snd_soc_pcm_runtime instance.

Amadeusz Sławiński (5):
  ASoC: core: Remove invalid snd_soc_component_set_jack call
  ASoC: topology: Check for dapm widget completeness
  ASoC: topology: Use correct device for prints
  ASoC: topology: Change topology device to card device
  ASoC: Stop dummy from overriding hwparams

Cezary Rojewski (1):
  ASoC: topology: Add header payload_size verification

 sound/soc/soc-core.c     |  3 ---
 sound/soc/soc-topology.c | 34 ++++++++++++++++++++++++++++++----
 sound/soc/soc-utils.c    | 13 +++++++++++++
 3 files changed, 43 insertions(+), 7 deletions(-)

--
2.25.1
This commit is contained in:
Mark Brown 2021-10-29 21:53:39 +01:00
commit 956ac4f1f5
No known key found for this signature in database
GPG key ID: 24D68B725D5487D0
3 changed files with 43 additions and 7 deletions

View file

@ -1342,9 +1342,6 @@ static void soc_remove_component(struct snd_soc_component *component,
if (probed)
snd_soc_component_remove(component);
/* For framework level robustness */
snd_soc_component_set_jack(component, NULL, NULL);
list_del_init(&component->card_list);
snd_soc_dapm_free(snd_soc_component_get_dapm(component));
soc_cleanup_component_debugfs(component);

View file

@ -351,7 +351,7 @@ static int soc_tplg_add_kcontrol(struct soc_tplg *tplg,
struct snd_soc_component *comp = tplg->comp;
return soc_tplg_add_dcontrol(comp->card->snd_card,
comp->dev, k, comp->name_prefix, comp, kcontrol);
tplg->dev, k, comp->name_prefix, comp, kcontrol);
}
/* remove a mixer kcontrol */
@ -1591,11 +1591,28 @@ static int soc_tplg_dapm_widget_elems_load(struct soc_tplg *tplg,
struct snd_soc_tplg_dapm_widget *widget = (struct snd_soc_tplg_dapm_widget *) tplg->pos;
int ret;
/*
* check if widget itself fits within topology file
* use sizeof instead of widget->size, as we can't be sure
* it is set properly yet (file may end before it is present)
*/
if (soc_tplg_get_offset(tplg) + sizeof(*widget) >= tplg->fw->size) {
dev_err(tplg->dev, "ASoC: invalid widget data size\n");
return -EINVAL;
}
/* check if widget has proper size */
if (le32_to_cpu(widget->size) != sizeof(*widget)) {
dev_err(tplg->dev, "ASoC: invalid widget size\n");
return -EINVAL;
}
/* check if widget private data fits within topology file */
if (soc_tplg_get_offset(tplg) + le32_to_cpu(widget->priv.size) >= tplg->fw->size) {
dev_err(tplg->dev, "ASoC: invalid widget private data size\n");
return -EINVAL;
}
ret = soc_tplg_dapm_widget_create(tplg, widget);
if (ret < 0) {
dev_err(tplg->dev, "ASoC: failed to load widget %s\n",
@ -2438,6 +2455,7 @@ static int soc_tplg_manifest_load(struct soc_tplg *tplg,
_manifest = manifest;
} else {
abi_match = false;
ret = manifest_new_ver(tplg, manifest, &_manifest);
if (ret < 0)
return ret;
@ -2468,6 +2486,14 @@ static int soc_valid_header(struct soc_tplg *tplg,
return -EINVAL;
}
if (soc_tplg_get_hdr_offset(tplg) + hdr->payload_size >= tplg->fw->size) {
dev_err(tplg->dev,
"ASoC: invalid header of type %d at offset %ld payload_size %d\n",
le32_to_cpu(hdr->type), soc_tplg_get_hdr_offset(tplg),
hdr->payload_size);
return -EINVAL;
}
/* big endian firmware objects not supported atm */
if (le32_to_cpu(hdr->magic) == SOC_TPLG_MAGIC_BIG_ENDIAN) {
dev_err(tplg->dev,
@ -2642,17 +2668,17 @@ int snd_soc_tplg_component_load(struct snd_soc_component *comp,
/*
* check if we have sane parameters:
* comp - needs to exist to keep and reference data while parsing
* comp->dev - used for resource management and prints
* comp->card - used for setting card related parameters
* comp->card->dev - used for resource management and prints
* fw - we need it, as it is the very thing we parse
*/
if (!comp || !comp->dev || !comp->card || !fw)
if (!comp || !comp->card || !comp->card->dev || !fw)
return -EINVAL;
/* setup parsing context */
memset(&tplg, 0, sizeof(tplg));
tplg.fw = fw;
tplg.dev = comp->dev;
tplg.dev = comp->card->dev;
tplg.comp = comp;
if (ops) {
tplg.ops = ops;

View file

@ -63,10 +63,23 @@ static const struct snd_pcm_hardware dummy_dma_hardware = {
.periods_max = 128,
};
static const struct snd_soc_component_driver dummy_platform;
static int dummy_dma_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
int i;
/*
* If there are other components associated with rtd, we shouldn't
* override their hwparams
*/
for_each_rtd_components(rtd, i, component) {
if (component->driver == &dummy_platform)
return 0;
}
/* BE's dont need dummy params */
if (!rtd->dai_link->no_pcm)