summary refs log tree commit diff
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/soc-core.c3
-rw-r--r--sound/soc/soc-topology.c34
-rw-r--r--sound/soc/soc-utils.c13
3 files changed, 43 insertions, 7 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 94f1548b8a32..dcf6be4c4aaa 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -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);
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c
index 7a4559ddf903..557e22c5254c 100644
--- a/sound/soc/soc-topology.c
+++ b/sound/soc/soc-topology.c
@@ -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;
diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c
index 299b5d6ebfd1..a4efe7e52a8b 100644
--- a/sound/soc/soc-utils.c
+++ b/sound/soc/soc-utils.c
@@ -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)