Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 253895d2 authored by Aravind Kumar's avatar Aravind Kumar
Browse files

ASoC: wcd9xxx: Add check for NULL pointer and buffer overflow



Current code has possible scenarios where NULL pointer
could be dereferenced or an out-of-bound index of array
could be accessed. The change checks the pointer for NULL
before they are dereferenced and checks for buffer overflows
to ensure out of bound indexes of arrays are not
accessed.

CRs-Fixed: 628865 628869 628873 628874 628875
Change-Id: I3002d1831eb852445619dabeb0f26285ab420953
Signed-off-by: default avatarAravind Kumar <akumark@codeaurora.org>
parent b5c75c4d
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -1827,7 +1827,6 @@ static int wcd9xxx_slim_device_down(struct slim_device *sldev)
{
	struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);

	dev_info(wcd9xxx->dev, "%s: device down\n", __func__);
	if (!wcd9xxx) {
		pr_err("%s: wcd9xxx is NULL\n", __func__);
		return -EINVAL;
+12 −0
Original line number Diff line number Diff line
@@ -618,6 +618,10 @@ static int phyirq_to_virq(struct wcd9xxx_core_resource *wcd9xxx_res, int offset)
static int virq_to_phyirq(struct wcd9xxx_core_resource *wcd9xxx_res, int virq)
{
	struct irq_data *irq_data = irq_get_irq_data(virq);
	if (unlikely(!irq_data)) {
		pr_err("%s: irq_data is NULL", __func__);
		return -EINVAL;
	}
	return irq_data->hwirq;
}

@@ -667,6 +671,10 @@ static int wcd9xxx_irq_probe(struct platform_device *pdev)
	} else {
		dev_dbg(&pdev->dev, "%s: virq = %d\n", __func__, irq);
		domain = irq_find_host(pdev->dev.of_node);
		if (unlikely(!domain)) {
			pr_err("%s: domain is NULL", __func__);
			return -EINVAL;
		}
		data = (struct wcd9xxx_irq_drv_data *)domain->host_data;
		data->irq = irq;
		wmb();
@@ -682,6 +690,10 @@ static int wcd9xxx_irq_remove(struct platform_device *pdev)
	struct wcd9xxx_irq_drv_data *data;

	domain = irq_find_host(pdev->dev.of_node);
	if (unlikely(!domain)) {
		pr_err("%s: domain is NULL", __func__);
		return -EINVAL;
	}
	data = (struct wcd9xxx_irq_drv_data *)domain->host_data;
	data->irq = 0;
	wmb();
+30 −10
Original line number Diff line number Diff line
@@ -1509,6 +1509,7 @@ static int wcd9306_put_dec_enum(struct snd_kcontrol *kcontrol,
	u16 tx_mux_ctl_reg;
	u8 adc_dmic_sel = 0x0;
	int ret = 0;
	char *srch = NULL;

	if (ucontrol->value.enumerated.item[0] > e->max - 1)
		return -EINVAL;
@@ -1527,8 +1528,12 @@ static int wcd9306_put_dec_enum(struct snd_kcontrol *kcontrol,
		ret =  -EINVAL;
		goto out;
	}

	ret = kstrtouint(strpbrk(dec_name, "1234"), 10, &decimator);
	srch = strpbrk(dec_name, "1234");
	if (srch == NULL) {
		pr_err("%s: Invalid decimator name %s\n", __func__, dec_name);
		return -EINVAL;
	}
	ret = kstrtouint(srch, 10, &decimator);
	if (ret < 0) {
		pr_err("%s: Invalid decimator = %s\n", __func__, dec_name);
		ret =  -EINVAL;
@@ -2043,8 +2048,15 @@ static int tapan_codec_enable_dmic(struct snd_soc_dapm_widget *w,
	s32 *dmic_clk_cnt;
	unsigned int dmic;
	int ret;
	char *srch = NULL;

	ret = kstrtouint(strpbrk(w->name, "1234"), 10, &dmic);
	srch = strpbrk(w->name, "1234");
	if (srch == NULL) {
		pr_err("%s: Invalid widget name %s\n", __func__, w->name);
		return -EINVAL;
	}

	ret = kstrtouint(srch, 10, &dmic);
	if (ret < 0) {
		pr_err("%s: Invalid DMIC line on the codec\n", __func__);
		return -EINVAL;
@@ -2376,6 +2388,7 @@ static int tapan_codec_enable_dec(struct snd_soc_dapm_widget *w,
	u16 dec_reset_reg, tx_vol_ctl_reg, tx_mux_ctl_reg;
	u8 dec_hpf_cut_of_freq;
	int offset;
	char *srch = NULL;

	dev_dbg(codec->dev, "%s %d\n", __func__, event);

@@ -2391,8 +2404,12 @@ static int tapan_codec_enable_dec(struct snd_soc_dapm_widget *w,
		ret =  -EINVAL;
		goto out;
	}

	ret = kstrtouint(strpbrk(dec_name, "123456789"), 10, &decimator);
	srch = strpbrk(dec_name, "123456789");
	if (srch == NULL) {
		pr_err("%s: Invalid decimator name %s\n", __func__, dec_name);
		return -EINVAL;
	}
	ret = kstrtouint(srch, 10, &decimator);
	if (ret < 0) {
		pr_err("%s: Invalid decimator = %s\n", __func__, dec_name);
		ret =  -EINVAL;
@@ -3353,7 +3370,7 @@ static void tapan_shutdown(struct snd_pcm_substream *substream,
	dev_dbg(dai->codec->dev, "%s(): substream = %s  stream = %d\n",
		 __func__, substream->name, substream->stream);

	if (dai->id <= NUM_CODEC_DAIS) {
	if (dai->id < NUM_CODEC_DAIS) {
		if (tapan->dai[dai->id].ch_mask) {
			active = 1;
			dev_dbg(dai->codec->dev, "%s(): Codec DAI: chmask[%d] = 0x%lx\n",
@@ -3472,7 +3489,7 @@ static int tapan_set_channel_map(struct snd_soc_dai *dai,
{
	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(dai->codec);
	struct wcd9xxx *core = dev_get_drvdata(dai->codec->dev->parent);
	if (!tx_slot && !rx_slot) {
	if (!tx_slot || !rx_slot) {
		pr_err("%s: Invalid\n", __func__);
		return -EINVAL;
	}
@@ -4869,9 +4886,9 @@ static int tapan_handle_pdata(struct tapan_priv *tapan)
	struct snd_soc_codec *codec = tapan->codec;
	struct wcd9xxx_pdata *pdata = tapan->resmgr.pdata;
	int k1, k2, k3, rc = 0;
	u8 txfe_bypass = pdata->amic_settings.txfe_enable;
	u8 txfe_buff = pdata->amic_settings.txfe_buff;
	u8 flag = pdata->amic_settings.use_pdata;
	u8 txfe_bypass;
	u8 txfe_buff;
	u8 flag;
	u8 i = 0, j = 0;
	u8 val_txfe = 0, value = 0;
	u8 dmic_sample_rate_value = 0;
@@ -4883,6 +4900,9 @@ static int tapan_handle_pdata(struct tapan_priv *tapan)
		rc = -ENODEV;
		goto done;
	}
	txfe_bypass = pdata->amic_settings.txfe_enable;
	txfe_buff = pdata->amic_settings.txfe_buff;
	flag = pdata->amic_settings.use_pdata;

	/* Make sure settings are correct */
	if ((pdata->micbias.ldoh_v > WCD9XXX_LDOH_3P0_V) ||
+9 −3
Original line number Diff line number Diff line
/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -552,7 +552,13 @@ static int get_impedance_index(u32 imped)
				__func__);
		goto ret;
	}
	for (i = 0; i < ARRAY_SIZE(imped_index); i++) {
	if (imped >= imped_index[ARRAY_SIZE(imped_index) - 1].imped_val) {
		pr_debug("%s, detected impedance is greater than 32164 Ohm\n",
				__func__);
		i = ARRAY_SIZE(imped_index) - 1;
		goto ret;
	}
	for (i = 0; i < ARRAY_SIZE(imped_index) - 1; i++) {
		if (imped >= imped_index[i].imped_val &&
			imped < imped_index[i + 1].imped_val)
			break;
@@ -569,7 +575,7 @@ void wcd9xxx_clsh_imped_config(struct snd_soc_codec *codec,
	int i  = 0;
	int index = 0;
	index = get_impedance_index(imped);
	if (index > ARRAY_SIZE(imped_index)) {
	if (index >= ARRAY_SIZE(imped_index)) {
		pr_err("%s, invalid imped = %d\n", __func__, imped);
		return;
	}
+1 −1
Original line number Diff line number Diff line
@@ -1626,7 +1626,7 @@ wcd9xxx_find_plug_type(struct wcd9xxx_mbhc *mbhc,
			continue;
		}

		if ((i > 0) && (d->_type != dprev->_type)) {
		if ((i > 0) && (dprev != NULL) && (d->_type != dprev->_type)) {
			pr_debug("%s: Invalid, inconsistent types\n", __func__);
			type = PLUG_TYPE_INVALID;
			goto exit;