Browse Source

asoc: codec: add range check to avoid overflow

Add range check for ucontrol value to avoid array
overflow.

Change-Id: I7b699519bec6f605e5ca5ece8f67badbefc7a094
Signed-off-by: Vatsal Bucha <[email protected]>
Vatsal Bucha 4 years ago
parent
commit
77ac79f6c7
3 changed files with 47 additions and 19 deletions
  1. 6 2
      asoc/codecs/swr-dmic.c
  2. 34 13
      asoc/codecs/wcd937x/wcd937x.c
  3. 7 4
      asoc/codecs/wcd938x/wcd938x.c

+ 6 - 2
asoc/codecs/swr-dmic.c

@@ -160,7 +160,7 @@ static int swr_dmic_tx_master_port_put(struct snd_kcontrol *kcontrol,
 				snd_soc_kcontrol_component(kcontrol);
 	struct swr_dmic_priv *swr_dmic = snd_soc_component_get_drvdata(component);
 	int ret = 0;
-	int slave_port_idx;
+	unsigned int slave_port_idx = SWR_DMIC_MAX_PORTS, idx = 0;
 
 	ret  = swr_dmic_tx_get_slave_port_type_idx(kcontrol->id.name,
 							&slave_port_idx);
@@ -169,8 +169,12 @@ static int swr_dmic_tx_master_port_put(struct snd_kcontrol *kcontrol,
 		return ret;
 	}
 
+	idx = ucontrol->value.enumerated.item[0];
+	if (idx < 0 || idx >= ARRAY_SIZE(swr_master_channel_map))
+		return -EINVAL;
+
 	swr_dmic->tx_master_port_map[slave_port_idx] =
-		swr_master_channel_map[ucontrol->value.enumerated.item[0]];
+			swr_master_channel_map[idx];
 	dev_dbg(component->dev, "%s: slv port id: %d, master_port_type: %d\n",
 		__func__, slave_port_idx,
 		swr_dmic->tx_master_port_map[slave_port_idx]);

+ 34 - 13
asoc/codecs/wcd937x/wcd937x.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/module.h>
@@ -2120,15 +2120,24 @@ static int wcd937x_tx_master_ch_get(struct snd_kcontrol *kcontrol,
 {
 	struct snd_soc_component *component =
 				snd_soc_kcontrol_component(kcontrol);
-	struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component);
-	int slave_ch_idx;
+	struct wcd937x_priv *wcd937x = NULL;
+	int slave_ch_idx = -EINVAL;
+
+	if (component == NULL)
+		return -EINVAL;
+
+	wcd937x = snd_soc_component_get_drvdata(component);
+	if (wcd937x == NULL)
+		return -EINVAL;
 
 	wcd937x_tx_get_slave_ch_type_idx(kcontrol->id.name, &slave_ch_idx);
 
-	if (slave_ch_idx != -EINVAL)
-		ucontrol->value.integer.value[0] =
-				wcd937x_slave_get_master_ch_val(
-				wcd937x->tx_master_ch_map[slave_ch_idx]);
+	if (slave_ch_idx < 0 || slave_ch_idx >= WCD937X_MAX_SLAVE_CH_TYPES)
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] =
+			wcd937x_slave_get_master_ch_val(
+			wcd937x->tx_master_ch_map[slave_ch_idx]);
 
 	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
 			__func__, ucontrol->value.integer.value[0]);
@@ -2140,19 +2149,31 @@ static int wcd937x_tx_master_ch_put(struct snd_kcontrol *kcontrol,
 {
 	struct snd_soc_component *component =
 				snd_soc_kcontrol_component(kcontrol);
-	struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component);
-	int slave_ch_idx;
+	struct wcd937x_priv *wcd937x;
+	int slave_ch_idx = -EINVAL, idx = 0;
+
+	if (component == NULL)
+		return -EINVAL;
+
+	wcd937x = snd_soc_component_get_drvdata(component);
+	if (wcd937x == NULL)
+		return -EINVAL;
 
 	wcd937x_tx_get_slave_ch_type_idx(kcontrol->id.name, &slave_ch_idx);
 
+	if (slave_ch_idx < 0 || slave_ch_idx >= WCD937X_MAX_SLAVE_CH_TYPES)
+		return -EINVAL;
+
 	dev_dbg(component->dev, "%s: slave_ch_idx: %d", __func__, slave_ch_idx);
 	dev_dbg(component->dev, "%s: ucontrol->value.enumerated.item[0] = %ld\n",
 			__func__, ucontrol->value.enumerated.item[0]);
 
-	if (slave_ch_idx != -EINVAL)
-		wcd937x->tx_master_ch_map[slave_ch_idx] =
-				wcd937x_slave_get_master_ch(
-					ucontrol->value.enumerated.item[0]);
+	idx = ucontrol->value.enumerated.item[0];
+	if (idx < 0 || idx >= ARRAY_SIZE(wcd937x_swr_master_ch_map))
+		return -EINVAL;
+
+	wcd937x->tx_master_ch_map[slave_ch_idx] =
+			wcd937x_slave_get_master_ch(idx);
 
 	return 0;
 }

+ 7 - 4
asoc/codecs/wcd938x/wcd938x.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/module.h>
@@ -2942,7 +2942,7 @@ static int wcd938x_tx_master_ch_put(struct snd_kcontrol *kcontrol,
 	struct snd_soc_component *component =
 				snd_soc_kcontrol_component(kcontrol);
 	struct wcd938x_priv *wcd938x = NULL;
-	int slave_ch_idx = -EINVAL;
+	int slave_ch_idx = -EINVAL, idx = 0;
 
 	if (component == NULL)
 		return -EINVAL;
@@ -2960,8 +2960,11 @@ static int wcd938x_tx_master_ch_put(struct snd_kcontrol *kcontrol,
 	dev_dbg(component->dev, "%s: ucontrol->value.enumerated.item[0] = %ld\n",
 			__func__, ucontrol->value.enumerated.item[0]);
 
-	wcd938x->tx_master_ch_map[slave_ch_idx] = wcd938x_slave_get_master_ch(
-				ucontrol->value.enumerated.item[0]);
+	idx = ucontrol->value.enumerated.item[0];
+	if (idx < 0 || idx >= ARRAY_SIZE(swr_master_ch_map))
+		return -EINVAL;
+
+	wcd938x->tx_master_ch_map[slave_ch_idx] = wcd938x_slave_get_master_ch(idx);
 	return 0;
 }