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

Commit 0961951b authored by Lior Barenboim's avatar Lior Barenboim
Browse files

msm: ultrasound: fix KASan out of bounds error



APR header size is included twice which causes memory out of bounds. This
fix removes extra header size.

BUG: KASan: out of bounds on stack in smd_memcpy_to_fifo+0x74/0xd4 at addr ffffffc0895579f8
Read of size 8 by task mediaserver/507
page:ffffffbac69d5660 count:0 mapcount:0 mapping:          (null) index:0x0
flags: 0x0()
page dumped because: kasan: bad access detected
Call trace:
[<ffffffc000089e38>] dump_backtrace+0x0/0x1c4
[<ffffffc00008a00c>] show_stack+0x10/0x1c
[<ffffffc001188404>] dump_stack+0x74/0xc8
[<ffffffc00020d664>] kasan_report_error+0x2b0/0x408
[<ffffffc00020d898>] kasan_report+0x34/0x40
[<ffffffc00020c82c>] __asan_load8+0x84/0x90
[<ffffffc0005cbb9c>] smd_memcpy_to_fifo+0x70/0xd4
[<ffffffc0005cf824>] smd_stream_write+0x1c8/0x2f0
[<ffffffc0005cfccc>] smd_packet_write+0x180/0x20c
[<ffffffc0005ceefc>] smd_write+0x74/0x88
[<ffffffc0006068dc>] __apr_tal_write+0x70/0xe0
[<ffffffc000606988>] apr_tal_write+0x3c/0x94
[<ffffffc000605168>] apr_send_pkt+0x1c8/0x224
[<ffffffc000e8d840>] q6core_dereg_all_custom_topologies+0x100/0x21c
[<ffffffc000e8f0e4>] q6core_set_cal+0x1f4/0x47c
[<ffffffc000e4d8c8>] audio_cal_shared_ioctl.isra.0+0x60c/0x92c
[<ffffffc000e4dc70>] audio_cal_compat_ioctl+0x88/0x98
[<ffffffc00027d2dc>] compat_SyS_ioctl+0x1ac/0x1a18
Memory state around the buggy address:
 ffffffc089557880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 ffffffc089557900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>ffffffc089557980: 00 00 00 00 00 00 f1 f1 f1 f1 00 00 00 00 00 f4
                                                                ^
 ffffffc089557a00: f4 f4 f2 f2 f2 f2 00 00 00 00 00 f4 f4 f4 f3 f3
 ffffffc089557a80: f3 f3 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1

Change-Id: I397cb57060032806fa63e25e0a3a5a4abbda982e
Signed-off-by: default avatarLior Barenboim <liorb@codeaurora.org>
parent ef0d0e07
Loading
Loading
Loading
Loading
+10 −14
Original line number Diff line number Diff line
/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2015, 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
@@ -753,7 +753,7 @@ static void q6usm_add_hdr(struct us_client *usc, struct apr_hdr *hdr,
		hdr->token = usc->session;
		atomic_set(&usc->cmd_state, 1);
	}
	hdr->pkt_size  = APR_PKT_SIZE(APR_HDR_SIZE, pkt_size);
	hdr->pkt_size  = pkt_size;
	mutex_unlock(&usc->cmd_lock);
	return;
}
@@ -874,7 +874,7 @@ int q6usm_enc_cfg_blk(struct us_client *usc, struct us_encdec_cfg *us_cfg)
	} else
		round_params_size = 0;

	q6usm_add_hdr(usc, &enc_cfg->hdr, total_cfg_size - APR_HDR_SIZE, true);
	q6usm_add_hdr(usc, &enc_cfg->hdr, total_cfg_size, true);

	enc_cfg->hdr.opcode = USM_STREAM_CMD_SET_ENC_PARAM;
	enc_cfg->param_id = USM_PARAM_ID_ENCDEC_ENC_CFG_BLK;
@@ -988,7 +988,7 @@ int q6usm_dec_cfg_blk(struct us_client *usc, struct us_encdec_cfg *us_cfg)
		round_params_size = 0;
	}

	q6usm_add_hdr(usc, &dec_cfg->hdr, total_cfg_size - APR_HDR_SIZE, true);
	q6usm_add_hdr(usc, &dec_cfg->hdr, total_cfg_size, true);

	dec_cfg->hdr.opcode = USM_DATA_CMD_MEDIA_FORMAT_UPDATE;
	dec_cfg->format_id = int_format;
@@ -1148,7 +1148,7 @@ int q6usm_read(struct us_client *usc, uint32_t read_ind)
		read_counter = (port->buf_cnt - port->cpu_buf) + read_ind;
	}

	q6usm_add_hdr(usc, &read.hdr, (sizeof(read) - APR_HDR_SIZE), false);
	q6usm_add_hdr(usc, &read.hdr, sizeof(read), false);

	read.hdr.opcode = USM_DATA_CMD_READ;
	read.buf_size = port->buf_size;
@@ -1224,8 +1224,7 @@ int q6usm_write(struct us_client *usc, uint32_t write_ind)
		}
	}

	q6usm_add_hdr(usc, &cmd_write.hdr,
		      (sizeof(cmd_write) - APR_HDR_SIZE), false);
	q6usm_add_hdr(usc, &cmd_write.hdr, sizeof(cmd_write), false);

	cmd_write.hdr.opcode = USM_DATA_CMD_WRITE;
	cmd_write.buf_size = port->buf_size;
@@ -1296,7 +1295,7 @@ int q6usm_cmd(struct us_client *usc, int cmd)
		pr_err("%s: APR handle NULL\n", __func__);
		return -EINVAL;
	}
	q6usm_add_hdr(usc, &hdr, (sizeof(hdr) - APR_HDR_SIZE), true);
	q6usm_add_hdr(usc, &hdr, sizeof(hdr), true);
	switch (cmd) {
	case CMD_CLOSE:
		hdr.opcode = USM_STREAM_CMD_CLOSE;
@@ -1342,8 +1341,7 @@ int q6usm_set_us_detection(struct us_client *usc,
		return -EINVAL;
	}

	q6usm_add_hdr(usc, &detect_info->hdr,
		      detect_info_size - APR_HDR_SIZE, true);
	q6usm_add_hdr(usc, &detect_info->hdr, detect_info_size, true);

	detect_info->hdr.opcode = USM_SESSION_CMD_SIGNAL_DETECT_MODE;

@@ -1378,8 +1376,7 @@ int q6usm_set_us_stream_param(int dir, struct us_client *usc,
	}
	port = &usc->port[dir];

	q6usm_add_hdr(usc, &cmd_set_param.hdr,
		(sizeof(cmd_set_param) - APR_HDR_SIZE), true);
	q6usm_add_hdr(usc, &cmd_set_param.hdr, sizeof(cmd_set_param), true);

	cmd_set_param.hdr.opcode = USM_STREAM_CMD_SET_PARAM;
	cmd_set_param.buf_size = buf_size;
@@ -1424,8 +1421,7 @@ int q6usm_get_us_stream_param(int dir, struct us_client *usc,
	}
	port = &usc->port[dir];

	q6usm_add_hdr(usc, &cmd_get_param.hdr,
			(sizeof(cmd_get_param) - APR_HDR_SIZE), true);
	q6usm_add_hdr(usc, &cmd_get_param.hdr, sizeof(cmd_get_param), true);

	cmd_get_param.hdr.opcode = USM_STREAM_CMD_GET_PARAM;
	cmd_get_param.buf_size = buf_size;