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

Commit 73bfc22a authored by Shiv Maliyappanahalli's avatar Shiv Maliyappanahalli
Browse files

ASoC: msm: qdsp6v2: Fix buffer overflow in voice driver



Userspace registers calibration data with acdb driver
through ioctls. Voice driver registers the calibration
data with CVD by querying acdb data from acdb driver and
copies the calibration data in apr message.

The size of the calibration data can be controlled by userspace
and can result in buffer overflow if the calibration size is
greater than the destination buffer size.

Reject acdb data if the size is greater than the size of
destination buffer.

CRs-Fixed: 548872
Change-Id: I4cd23a38c90b745226ddbc28656c82ff7c10432b
Signed-off-by: default avatarShiv Maliyappanahalli <smaliyap@codeaurora.org>
parent 3e2b941d
Loading
Loading
Loading
Loading
+6 −3
Original line number Original line Diff line number Diff line
@@ -1519,7 +1519,8 @@ static int voice_send_cvs_register_cal_cmd(struct voice_data *v)


	/* get the cvs cal data */
	/* get the cvs cal data */
	get_all_vocstrm_cal(&cal_block);
	get_all_vocstrm_cal(&cal_block);
	if (cal_block.cal_size == 0)
	if (cal_block.cal_size == 0 ||
	    cal_block.cal_size > CVS_CAL_SIZE)
		goto fail;
		goto fail;


	if (v == NULL) {
	if (v == NULL) {
@@ -1928,7 +1929,8 @@ static int voice_send_cvp_register_cal_cmd(struct voice_data *v)


      /* get the cvp cal data */
      /* get the cvp cal data */
	get_all_vocproc_cal(&cal_block);
	get_all_vocproc_cal(&cal_block);
	if (cal_block.cal_size == 0)
	if (cal_block.cal_size == 0 ||
	    cal_block.cal_size > CVP_CAL_SIZE)
		goto fail;
		goto fail;


	if (v == NULL) {
	if (v == NULL) {
@@ -2063,7 +2065,8 @@ static int voice_send_cvp_register_vol_cal_table_cmd(struct voice_data *v)
	get_all_vocvol_cal(&vol_block);
	get_all_vocvol_cal(&vol_block);
	get_all_vocproc_cal(&voc_block);
	get_all_vocproc_cal(&voc_block);


	if (vol_block.cal_size == 0)
	if (vol_block.cal_size == 0 ||
	    vol_block.cal_size > CVP_CAL_SIZE)
		goto fail;
		goto fail;


	if (v == NULL) {
	if (v == NULL) {
+44 −9
Original line number Original line Diff line number Diff line
@@ -1955,20 +1955,22 @@ static int voice_send_cvs_register_cal_cmd(struct voice_data *v)
	if (!common.apr_q6_cvs) {
	if (!common.apr_q6_cvs) {
		pr_err("%s: apr_cvs is NULL\n", __func__);
		pr_err("%s: apr_cvs is NULL\n", __func__);


		ret = -EPERM;
		ret = -EINVAL;
		goto done;
		goto done;
	}
	}


	if (!common.cal_mem_handle) {
	if (!common.cal_mem_handle) {
		pr_err("%s: Cal mem handle is NULL\n", __func__);
		pr_err("%s: Cal mem handle is NULL\n", __func__);
		ret = -EPERM;

		ret = -EINVAL;
		goto done;
		goto done;
	}
	}


	get_vocstrm_cal(&cal_block);
	get_vocstrm_cal(&cal_block);
	if (cal_block.cal_size == 0) {
	if (cal_block.cal_size == 0) {
		pr_err("%s: CVS cal size is 0\n", __func__);
		pr_err("%s: CVS cal size is 0\n", __func__);
		ret = -EPERM;

		ret = -EINVAL;
		goto done;
		goto done;
	}
	}


@@ -1989,6 +1991,15 @@ static int voice_send_cvs_register_cal_cmd(struct voice_data *v)


	/* Get the column info corresponding to CVS cal from ACDB. */
	/* Get the column info corresponding to CVS cal from ACDB. */
	get_voice_col_data(VOCSTRM_CAL, &cal_block);
	get_voice_col_data(VOCSTRM_CAL, &cal_block);
	if (cal_block.cal_size == 0 ||
	    cal_block.cal_size >
	    sizeof(cvs_reg_cal_cmd.cvs_cal_data.column_info)) {
		pr_err("%s: Invalid VOCSTRM_CAL size %d\n",
		       __func__, cal_block.cal_size);

		ret = -EINVAL;
		goto done;
	}
	memcpy(&cvs_reg_cal_cmd.cvs_cal_data.column_info[0],
	memcpy(&cvs_reg_cal_cmd.cvs_cal_data.column_info[0],
	       (void *) cal_block.cal_kvaddr,
	       (void *) cal_block.cal_kvaddr,
	       cal_block.cal_size);
	       cal_block.cal_size);
@@ -2227,20 +2238,22 @@ static int voice_send_cvp_register_cal_cmd(struct voice_data *v)
	if (!common.apr_q6_cvp) {
	if (!common.apr_q6_cvp) {
		pr_err("%s: apr_cvp is NULL\n", __func__);
		pr_err("%s: apr_cvp is NULL\n", __func__);


		ret = -EPERM;
		ret = -EINVAL;
		goto done;
		goto done;
	}
	}


	if (!common.cal_mem_handle) {
	if (!common.cal_mem_handle) {
		pr_err("%s: Cal mem handle is NULL\n", __func__);
		pr_err("%s: Cal mem handle is NULL\n", __func__);
		ret = -EPERM;

		ret = -EINVAL;
		goto done;
		goto done;
	}
	}


	get_vocproc_cal(&cal_block);
	get_vocproc_cal(&cal_block);
	if (cal_block.cal_size == 0) {
	if (cal_block.cal_size == 0) {
		pr_err("%s: CVP cal size is 0\n", __func__);
		pr_err("%s: CVP cal size is 0\n", __func__);
		ret = -EPERM;

		ret = -EINVAL;
		goto done;
		goto done;
	}
	}


@@ -2261,6 +2274,16 @@ static int voice_send_cvp_register_cal_cmd(struct voice_data *v)


	/* Get the column info corresponding to CVP cal from ACDB. */
	/* Get the column info corresponding to CVP cal from ACDB. */
	get_voice_col_data(VOCPROC_CAL, &cal_block);
	get_voice_col_data(VOCPROC_CAL, &cal_block);
	if (cal_block.cal_size == 0 ||
	    cal_block.cal_size >
	    sizeof(cvp_reg_cal_cmd.cvp_cal_data.column_info)) {
		pr_err("%s: Invalid VOCPROC_CAL size %d\n",
		       __func__, cal_block.cal_size);

		ret = -EINVAL;
		goto done;
	}

	memcpy(&cvp_reg_cal_cmd.cvp_cal_data.column_info[0],
	memcpy(&cvp_reg_cal_cmd.cvp_cal_data.column_info[0],
	       (void *) cal_block.cal_kvaddr,
	       (void *) cal_block.cal_kvaddr,
	       cal_block.cal_size);
	       cal_block.cal_size);
@@ -2363,20 +2386,22 @@ static int voice_send_cvp_register_vol_cal_cmd(struct voice_data *v)
	if (!common.apr_q6_cvp) {
	if (!common.apr_q6_cvp) {
		pr_err("%s: apr_cvp is NULL\n", __func__);
		pr_err("%s: apr_cvp is NULL\n", __func__);


		ret = -EPERM;
		ret = -EINVAL;
		goto done;
		goto done;
	}
	}


	if (!common.cal_mem_handle) {
	if (!common.cal_mem_handle) {
		pr_err("%s: Cal mem handle is NULL\n", __func__);
		pr_err("%s: Cal mem handle is NULL\n", __func__);
		ret = -EPERM;

		ret = -EINVAL;
		goto done;
		goto done;
	}
	}


	get_vocvol_cal(&cal_block);
	get_vocvol_cal(&cal_block);
	if (cal_block.cal_size == 0) {
	if (cal_block.cal_size == 0) {
		pr_err("%s: CVP vol cal size is 0\n", __func__);
		pr_err("%s: CVP vol cal size is 0\n", __func__);
		ret = -EPERM;

		ret = -EINVAL;
		goto done;
		goto done;
	}
	}


@@ -2399,6 +2424,16 @@ static int voice_send_cvp_register_vol_cal_cmd(struct voice_data *v)


	/* Get the column info corresponding to CVP volume cal from ACDB. */
	/* Get the column info corresponding to CVP volume cal from ACDB. */
	get_voice_col_data(VOCVOL_CAL, &cal_block);
	get_voice_col_data(VOCVOL_CAL, &cal_block);
	if (cal_block.cal_size == 0 ||
	    cal_block.cal_size >
	    sizeof(cvp_reg_vol_cal_cmd.cvp_vol_cal_data.column_info)) {
		pr_err("%s: Invalid VOCVOL_CAL size %d\n",
		       __func__, cal_block.cal_size);

		ret = -EINVAL;
		goto done;
	}

	memcpy(&cvp_reg_vol_cal_cmd.cvp_vol_cal_data.column_info[0],
	memcpy(&cvp_reg_vol_cal_cmd.cvp_vol_cal_data.column_info[0],
	       (void *) cal_block.cal_kvaddr,
	       (void *) cal_block.cal_kvaddr,
	       cal_block.cal_size);
	       cal_block.cal_size);