Skip to content
This repository has been archived by the owner on Dec 28, 2020. It is now read-only.

Commit

Permalink
techpack: audio: Merge tag 'LA.UM.7.3.r1-07800-sdm845.0' into neutrin…
Browse files Browse the repository at this point in the history
…o-msm-fajita-4.9

"LA.UM.7.3.r1-07800-sdm845.0"

* tag 'LA.UM.7.3.r1-07800-sdm845.0':
  dsp: adm: validate ADSP payload size before access
  dsp: q6voice: Check size of shared memory buffer before access
  dsp: q6usm: Check size of payload before access
  dsp: afe: check for payload size before payload access
  dsp: q6usm: Check size of payload before access
  dsp: q6core: validate payload size before memory copy
  lsm: check payload size validity before using it as array index
  dsp: q6voice: Check size of payload before access

Signed-off-by: Adam W. Willis <return.of.octobot@gmail.com>
  • Loading branch information
0ctobot committed May 30, 2019
2 parents 5af9c4f + 0e72333 commit 50dba0f
Show file tree
Hide file tree
Showing 8 changed files with 190 additions and 48 deletions.
45 changes: 37 additions & 8 deletions techpack/audio/asoc/msm-lsm-client.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
* Copyright (c) 2013-2019, 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
Expand Down Expand Up @@ -195,7 +195,8 @@ static int lsm_lab_buffer_sanity(struct lsm_priv *prtd,
}

static void lsm_event_handler(uint32_t opcode, uint32_t token,
void *payload, void *priv)
void *payload, uint16_t client_size,
void *priv)
{
unsigned long flags;
struct lsm_priv *prtd = priv;
Expand Down Expand Up @@ -265,6 +266,12 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
}

case LSM_SESSION_EVENT_DETECTION_STATUS:
if (client_size < 3 * sizeof(uint8_t)) {
dev_err(rtd->dev,
"%s: client_size has invalid size[%d]\n",
__func__, client_size);
return;
}
status = (uint16_t)((uint8_t *)payload)[0];
payload_size = (uint16_t)((uint8_t *)payload)[2];
index = 4;
Expand All @@ -274,6 +281,12 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
break;

case LSM_SESSION_EVENT_DETECTION_STATUS_V2:
if (client_size < 2 * sizeof(uint8_t)) {
dev_err(rtd->dev,
"%s: client_size has invalid size[%d]\n",
__func__, client_size);
return;
}
status = (uint16_t)((uint8_t *)payload)[0];
payload_size = (uint16_t)((uint8_t *)payload)[1];
index = 2;
Expand All @@ -283,6 +296,12 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
break;

case LSM_SESSION_EVENT_DETECTION_STATUS_V3:
if (client_size < 2 * (sizeof(uint32_t) + sizeof(uint8_t))) {
dev_err(rtd->dev,
"%s: client_size has invalid size[%d]\n",
__func__, client_size);
return;
}
event_ts_lsw = ((uint32_t *)payload)[0];
event_ts_msw = ((uint32_t *)payload)[1];
status = (uint16_t)((uint8_t *)payload)[8];
Expand Down Expand Up @@ -321,12 +340,22 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
prtd->event_status->payload_size = payload_size;

if (likely(prtd->event_status)) {
memcpy(prtd->event_status->payload,
&((uint8_t *)payload)[index],
payload_size);
prtd->event_avail = 1;
spin_unlock_irqrestore(&prtd->event_lock, flags);
wake_up(&prtd->event_wait);
if (client_size >= (payload_size + index)) {
memcpy(prtd->event_status->payload,
&((uint8_t *)payload)[index],
payload_size);
prtd->event_avail = 1;
spin_unlock_irqrestore(&prtd->event_lock,
flags);
wake_up(&prtd->event_wait);
} else {
spin_unlock_irqrestore(&prtd->event_lock,
flags);
dev_err(rtd->dev,
"%s: Failed to copy memory with invalid size = %d\n",
__func__, payload_size);
return;
}
} else {
spin_unlock_irqrestore(&prtd->event_lock, flags);
dev_err(rtd->dev,
Expand Down
66 changes: 44 additions & 22 deletions techpack/audio/dsp/q6adm.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2019, 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
Expand Down Expand Up @@ -1381,7 +1381,7 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv)
}

adm_callback_debug_print(data);
if (data->payload_size) {
if (data->payload_size >= sizeof(uint32_t)) {
copp_idx = (data->token) & 0XFF;
port_idx = ((data->token) >> 16) & 0xFF;
client_id = ((data->token) >> 8) & 0xFF;
Expand All @@ -1403,6 +1403,15 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv)
if (data->opcode == APR_BASIC_RSP_RESULT) {
pr_debug("%s: APR_BASIC_RSP_RESULT id 0x%x\n",
__func__, payload[0]);
if (!((client_id != ADM_CLIENT_ID_SOURCE_TRACKING) &&
(payload[0] == ADM_CMD_SET_PP_PARAMS_V5))) {
if (data->payload_size <
(2 * sizeof(uint32_t))) {
pr_err("%s: Invalid payload size %d\n",
__func__, data->payload_size);
return 0;
}
}
if (payload[1] != 0) {
pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
__func__, payload[0], payload[1]);
Expand Down Expand Up @@ -1521,9 +1530,16 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv)
switch (data->opcode) {
case ADM_CMDRSP_DEVICE_OPEN_V5:
case ADM_CMDRSP_DEVICE_OPEN_V6: {
struct adm_cmd_rsp_device_open_v5 *open =
(struct adm_cmd_rsp_device_open_v5 *)data->payload;
struct adm_cmd_rsp_device_open_v5 *open = NULL;

if (data->payload_size <
sizeof(struct adm_cmd_rsp_device_open_v5)) {
pr_err("%s: Invalid payload size %d\n",
__func__, data->payload_size);
return 0;
}
open =
(struct adm_cmd_rsp_device_open_v5 *)data->payload;
if (open->copp_id == INVALID_COPP_ID) {
pr_err("%s: invalid coppid rxed %d\n",
__func__, open->copp_id);
Expand Down Expand Up @@ -1596,25 +1612,31 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv)
pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST",
__func__);
pr_err(":err = 0x%x\n", payload[0]);
} else if (payload[1] >
((ADM_GET_TOPO_MODULE_LIST_LENGTH /
sizeof(uint32_t)) - 1)) {
pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST",
__func__);
pr_err(":size = %d\n", payload[1]);
} else {
idx = ADM_GET_TOPO_MODULE_LIST_LENGTH *
copp_idx;
pr_debug("%s:Num modules payload[1] %d\n",
__func__, payload[1]);
adm_module_topo_list[idx] = payload[1];
for (i = 1; i <= payload[1]; i++) {
adm_module_topo_list[idx+i] =
payload[1+i];
pr_debug("%s:payload[%d] = %x\n",
__func__, (i+1), payload[1+i]);
} else if (data->payload_size >=
(2 * sizeof(uint32_t))) {
if (payload[1] >
((ADM_GET_TOPO_MODULE_LIST_LENGTH /
sizeof(uint32_t)) - 1)) {
pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST",
__func__);
pr_err(":size = %d\n", payload[1]);
} else {
idx = ADM_GET_TOPO_MODULE_LIST_LENGTH *
copp_idx;
pr_debug("%s:Num modules payload[1] %d\n",
__func__, payload[1]);
adm_module_topo_list[idx] = payload[1];
for (i = 1; i <= payload[1]; i++) {
adm_module_topo_list[idx+i] =
payload[1+i];
pr_debug("%s:payload[%d] = %x\n",
__func__, (i+1),
payload[1+i]);
}
}
}
} else
pr_err("%s: Invalid payload size %d\n",
__func__, data->payload_size);
atomic_set(&this_adm.copp.stat
[port_idx][copp_idx], payload[0]);
wake_up(&this_adm.copp.wait[port_idx][copp_idx]);
Expand Down
19 changes: 15 additions & 4 deletions techpack/audio/dsp/q6afe.c
Original file line number Diff line number Diff line change
Expand Up @@ -391,14 +391,20 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv)
return -EINVAL;
}

if (rtac_make_afe_callback(data->payload,
data->payload_size))
return 0;

if (data->payload_size < 3 * sizeof(uint32_t)) {
pr_err("%s: Error: size %d is less than expected\n",
__func__, data->payload_size);
return -EINVAL;
}

if (payload[2] == AFE_PARAM_ID_DEV_TIMING_STATS) {
av_dev_drift_afe_cb_handler(data->payload,
data->payload_size);
} else {
if (rtac_make_afe_callback(data->payload,
data->payload_size))
return 0;

if (sp_make_afe_callback(data->payload,
data->payload_size))
return -EINVAL;
Expand All @@ -413,6 +419,11 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv)

payload = data->payload;
if (data->opcode == APR_BASIC_RSP_RESULT) {
if (data->payload_size < (2 * sizeof(uint32_t))) {
pr_err("%s: Error: size %d is less than expected\n",
__func__, data->payload_size);
return -EINVAL;
}
pr_debug("%s:opcode = 0x%x cmd = 0x%x status = 0x%x token=%d\n",
__func__, data->opcode,
payload[0], payload[1], data->token);
Expand Down
38 changes: 35 additions & 3 deletions techpack/audio/dsp/q6core.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2019, 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
Expand Down Expand Up @@ -184,7 +184,7 @@ int q6core_send_uevent(struct audio_uevent_data *uevent_data, char *event)
}
EXPORT_SYMBOL(q6core_send_uevent);

static int parse_fwk_version_info(uint32_t *payload)
static int parse_fwk_version_info(uint32_t *payload, uint16_t payload_size)
{
size_t ver_size;
int num_services;
Expand All @@ -197,6 +197,11 @@ static int parse_fwk_version_info(uint32_t *payload)
* Based on this info, we copy the payload into core
* avcs version info structure.
*/
if (payload_size < 5 * sizeof(uint32_t)) {
pr_err("%s: payload has invalid size %d\n",
__func__, payload_size);
return -EINVAL;
}
num_services = payload[4];
if (num_services > VSS_MAX_AVCS_NUM_SERVICES) {
pr_err("%s: num_services: %d greater than max services: %d\n",
Expand All @@ -211,6 +216,12 @@ static int parse_fwk_version_info(uint32_t *payload)
ver_size = sizeof(struct avcs_get_fwk_version) +
num_services * sizeof(struct avs_svc_api_info);

if (payload_size < ver_size) {
pr_err("%s: payload has invalid size %d, expected size %zu\n",
__func__, payload_size, ver_size);
return -EINVAL;
}

q6core_lcl.q6core_avcs_ver_info.ver_info =
kzalloc(ver_size, GFP_ATOMIC);
if (q6core_lcl.q6core_avcs_ver_info.ver_info == NULL)
Expand Down Expand Up @@ -247,6 +258,12 @@ static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv)

payload1 = data->payload;

if (data->payload_size < 2 * sizeof(uint32_t)) {
pr_err("%s: payload has invalid size %d\n",
__func__, data->payload_size);
return -EINVAL;
}

switch (payload1[0]) {

case AVCS_CMD_SHARED_MEM_UNMAP_REGIONS:
Expand Down Expand Up @@ -307,6 +324,11 @@ static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv)
break;
}
case AVCS_CMDRSP_SHARED_MEM_MAP_REGIONS:
if (data->payload_size < sizeof(uint32_t)) {
pr_err("%s: payload has invalid size %d\n",
__func__, data->payload_size);
return -EINVAL;
}
payload1 = data->payload;
pr_debug("%s: AVCS_CMDRSP_SHARED_MEM_MAP_REGIONS handle %d\n",
__func__, payload1[0]);
Expand All @@ -315,6 +337,11 @@ static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv)
wake_up(&q6core_lcl.bus_bw_req_wait);
break;
case AVCS_CMDRSP_ADSP_EVENT_GET_STATE:
if (data->payload_size < sizeof(uint32_t)) {
pr_err("%s: payload has invalid size %d\n",
__func__, data->payload_size);
return -EINVAL;
}
payload1 = data->payload;
q6core_lcl.param = payload1[0];
pr_debug("%s: Received ADSP get state response 0x%x\n",
Expand All @@ -325,6 +352,11 @@ static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv)
wake_up(&q6core_lcl.bus_bw_req_wait);
break;
case AVCS_CMDRSP_GET_LICENSE_VALIDATION_RESULT:
if (data->payload_size < sizeof(uint32_t)) {
pr_err("%s: payload has invalid size %d\n",
__func__, data->payload_size);
return -EINVAL;
}
payload1 = data->payload;
pr_debug("%s: cmd = LICENSE_VALIDATION_RESULT, result = 0x%x\n",
__func__, payload1[0]);
Expand All @@ -337,7 +369,7 @@ static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv)
pr_debug("%s: Received AVCS_CMDRSP_GET_FWK_VERSION\n",
__func__);
payload1 = data->payload;
ret = parse_fwk_version_info(payload1);
ret = parse_fwk_version_info(payload1, data->payload_size);
if (ret < 0) {
q6core_lcl.adsp_status = ret;
pr_err("%s: Failed to parse payload:%d\n",
Expand Down
18 changes: 14 additions & 4 deletions techpack/audio/dsp/q6lsm.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2017, Linux Foundation. All rights reserved.
* Copyright (c) 2013-2017, 2019 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
Expand Down Expand Up @@ -167,7 +167,8 @@ static int q6lsm_callback(struct apr_client_data *data, void *priv)
struct lsm_cmd_read_done read_done;

token = data->token;
if (data->payload_size > sizeof(read_done)) {
if (data->payload_size > sizeof(read_done) ||
data->payload_size < 6 * sizeof(payload[0])) {
pr_err("%s: read done error payload size %d expected size %zd\n",
__func__, data->payload_size,
sizeof(read_done));
Expand All @@ -185,6 +186,7 @@ static int q6lsm_callback(struct apr_client_data *data, void *priv)
if (client->cb)
client->cb(data->opcode, data->token,
(void *)&read_done,
sizeof(read_done),
client->priv);
return 0;
} else if (data->opcode == APR_BASIC_RSP_RESULT) {
Expand All @@ -210,6 +212,11 @@ static int q6lsm_callback(struct apr_client_data *data, void *priv)
__func__, token, client->session);
return -EINVAL;
}
if (data->payload_size < 2 * sizeof(payload[0])) {
pr_err("%s: payload has invalid size[%d]\n",
__func__, data->payload_size);
return -EINVAL;
}
client->cmd_err_code = payload[1];
if (client->cmd_err_code)
pr_err("%s: cmd 0x%x failed status %d\n",
Expand All @@ -230,7 +237,7 @@ static int q6lsm_callback(struct apr_client_data *data, void *priv)

if (client->cb)
client->cb(data->opcode, data->token, data->payload,
client->priv);
data->payload_size, client->priv);

return 0;
}
Expand Down Expand Up @@ -1350,6 +1357,8 @@ static int q6lsm_mmapcallback(struct apr_client_data *data, void *priv)
"proc 0x%x SID 0x%x\n", __func__, data->opcode,
data->reset_event, data->reset_proc, sid);

if (sid < LSM_MIN_SESSION_ID || sid > LSM_MAX_SESSION_ID)
pr_err("%s: Invalid session %d\n", __func__, sid);
apr_reset(lsm_common.apr);
lsm_common.apr = NULL;
atomic_set(&lsm_common.apr_users, 0);
Expand Down Expand Up @@ -1415,7 +1424,8 @@ static int q6lsm_mmapcallback(struct apr_client_data *data, void *priv)
}
if (client->cb)
client->cb(data->opcode, data->token,
data->payload, client->priv);
data->payload, data->payload_size,
client->priv);
return 0;
}

Expand Down
Loading

0 comments on commit 50dba0f

Please sign in to comment.