diff options
author | Wilson Sung <wilsonsung@google.com> | 2019-07-12 12:10:57 +0800 |
---|---|---|
committer | Wilson Sung <wilsonsung@google.com> | 2019-07-12 12:11:18 +0800 |
commit | 7a6d2aabd186bd97fc634533856955152d338dc9 (patch) | |
tree | 3057c3ffd80c018faa80c24a78ef3139850f277b | |
parent | 02ab6f9b4fa78f67e4d1b75f4614308e4303dc5c (diff) | |
parent | 3d24c5213d6d9ec48e932a6b61f3178d567c253c (diff) | |
download | msm-extra-android-msm-crosshatch-4.9-q-preview-6.tar.gz |
Merge branch 'android-msm-pixel-4.9-qt-security-next' into android-msm-pixel-4.9-qtandroid-q-preview-6_r0.6android-q-preview-6_r0.4android-10.0.0_r0.4android-10.0.0_r0.3android-10.0.0_r0.20android-10.0.0_r0.19android-10.0.0_r0.12android-10.0.0_r0.10android-msm-crosshatch-4.9-q-preview-6android-msm-crosshatch-4.9-android10-releaseandroid-msm-bonito-4.9-q-preview-6android-msm-bonito-4.9-android10-release
SEP 2019.1
Bug: 136171028
Bug: 136170907
Change-Id: Ib93b92ee9ed7c61c4b9a3e70ec0e810624e6a4e0
Signed-off-by: Wilson Sung <wilsonsung@google.com>
-rw-r--r-- | asoc/msm-lsm-client.c | 45 | ||||
-rw-r--r-- | dsp/q6asm.c | 278 | ||||
-rw-r--r-- | dsp/q6lsm.c | 18 | ||||
-rw-r--r-- | include/dsp/q6lsm.h | 4 |
4 files changed, 241 insertions, 104 deletions
diff --git a/asoc/msm-lsm-client.c b/asoc/msm-lsm-client.c index 72bdeaa2..4133e297 100644 --- a/asoc/msm-lsm-client.c +++ b/asoc/msm-lsm-client.c @@ -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 @@ -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, - uint32_t *payload, void *priv) + uint32_t *payload, uint16_t client_size, + void *priv) { unsigned long flags; struct lsm_priv *prtd = priv; @@ -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; @@ -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; @@ -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]; @@ -322,12 +341,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, diff --git a/dsp/q6asm.c b/dsp/q6asm.c index eadf1670..c7581f96 100644 --- a/dsp/q6asm.c +++ b/dsp/q6asm.c @@ -1696,14 +1696,14 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv) return 0; } - if (data->payload_size > sizeof(int)) { + if (data->payload_size >= 2 * sizeof(uint32_t)) { pr_debug("%s:ptr0[0x%x]ptr1[0x%x]opcode[0x%x] token[0x%x]payload_s[%d] src[%d] dest[%d]sid[%d]dir[%d]\n", __func__, payload[0], payload[1], data->opcode, data->token, data->payload_size, data->src_port, data->dest_port, asm_token._token.session_id, dir); pr_debug("%s:Payload = [0x%x] status[0x%x]\n", __func__, payload[0], payload[1]); - } else if (data->payload_size == sizeof(int)) { + } else if (data->payload_size == sizeof(uint32_t)) { pr_debug("%s:ptr0[0x%x]opcode[0x%x] token[0x%x]payload_s[%d] src[%d] dest[%d]sid[%d]dir[%d]\n", __func__, payload[0], data->opcode, data->token, data->payload_size, data->src_port, @@ -1717,7 +1717,8 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv) case ASM_CMD_SHARED_MEM_MAP_REGIONS: case ASM_CMD_SHARED_MEM_UNMAP_REGIONS: case ASM_CMD_ADD_TOPOLOGIES: - if (payload[1] != 0) { + if (data->payload_size >= 2 * sizeof(uint32_t) && + payload[1] != 0) { pr_err("%s: cmd = 0x%x returned error = 0x%x sid:%d\n", __func__, payload[0], payload[1], asm_token._token.session_id); @@ -1735,8 +1736,12 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv) if (atomic_cmpxchg(&ac->mem_state, -1, 0) == -1) wake_up(&ac->mem_wait); - dev_vdbg(ac->dev, "%s: Payload = [0x%x] status[0x%x]\n", + if (data->payload_size >= 2 * sizeof(uint32_t)) + dev_vdbg(ac->dev, "%s: Payload = [0x%x] status[0x%x]\n", __func__, payload[0], payload[1]); + else + dev_vdbg(ac->dev, "%s: Payload size of %d is less than expected.\n", + __func__, data->payload_size); break; default: pr_debug("%s: command[0x%x] not expecting rsp\n", @@ -1765,8 +1770,14 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv) break; } case ASM_CMD_SHARED_MEM_UNMAP_REGIONS:{ - pr_debug("%s: PL#0[0x%x]PL#1 [0x%x]\n", - __func__, payload[0], payload[1]); + if (data->payload_size >= 2 * sizeof(uint32_t)) + pr_debug("%s: PL#0[0x%x]PL#1 [0x%x]\n", + __func__, payload[0], + payload[1]); + else + pr_debug("%s: Payload size of %d is less than expected.\n", + __func__, data->payload_size); + spin_lock_irqsave(&port->dsp_lock, dsp_flags); if (atomic_cmpxchg(&ac->mem_state, -1, 0) == -1) wake_up(&ac->mem_wait); @@ -1775,8 +1786,12 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv) break; } default: - pr_debug("%s: command[0x%x]success [0x%x]\n", - __func__, payload[0], payload[1]); + if (data->payload_size >= 2 * sizeof(uint32_t)) + pr_debug("%s: command[0x%x]success [0x%x]\n", + __func__, payload[0], payload[1]); + else + pr_debug("%s: Payload size of %d is less than expected.\n", + __func__, data->payload_size); } if (ac->cb) ac->cb(data->opcode, data->token, @@ -1928,8 +1943,12 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) &(session[session_id].session_lock), flags); return -EINVAL; } - dev_vdbg(ac->dev, "%s: Payload = [0x%x] status[0x%x] opcode 0x%x\n", - __func__, payload[0], payload[1], data->opcode); + if (data->payload_size >= 2 * sizeof(uint32_t)) + dev_vdbg(ac->dev, "%s: Payload = [0x%x] status[0x%x] opcode 0x%x\n", + __func__, payload[0], payload[1], data->opcode); + else + dev_vdbg(ac->dev, "%s: Payload size of %d is less than expected.\n", + __func__, data->payload_size); } if (data->opcode == APR_BASIC_RSP_RESULT) { switch (payload[0]) { @@ -1973,29 +1992,41 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) case ASM_DATA_CMD_REMOVE_TRAILING_SILENCE: case ASM_SESSION_CMD_REGISTER_FOR_RX_UNDERFLOW_EVENTS: case ASM_STREAM_CMD_OPEN_WRITE_COMPRESSED: - pr_debug("%s: session %d opcode 0x%x token 0x%x Payload = [0x%x] stat 0x%x src %d dest %d\n", - __func__, ac->session, - data->opcode, data->token, - payload[0], payload[1], - data->src_port, data->dest_port); - if (payload[1] != 0) { - pr_err("%s: cmd = 0x%x returned error = 0x%x\n", - __func__, payload[0], payload[1]); - if (wakeup_flag) { - if ((is_adsp_reg_event(payload[0]) >= 0) - || (payload[0] == - ASM_STREAM_CMD_SET_PP_PARAMS_V2)) - atomic_set(&ac->cmd_state_pp, + if (data->payload_size >= 2 * sizeof(uint32_t)) { + pr_debug("%s: session %d opcode 0x%x token 0x%x Payload = [0x%x] stat 0x%x src %d dest %d\n", + __func__, ac->session, + data->opcode, data->token, + payload[0], payload[1], + data->src_port, data->dest_port); + if (payload[1] != 0) { + pr_err("%s: cmd = 0x%x returned error = 0x%x\n", + __func__, payload[0], + payload[1]); + if (wakeup_flag) { + if ( + (is_adsp_reg_event(payload[0]) + >=0) || + (payload[0] == + ASM_STREAM_CMD_SET_PP_PARAMS_V2 + ) + ) + atomic_set( + &ac->cmd_state_pp, payload[1]); - else - atomic_set(&ac->cmd_state, + else + atomic_set( + &ac->cmd_state, payload[1]); - wake_up(&ac->cmd_wait); + wake_up(&ac->cmd_wait); + } + spin_unlock_irqrestore( + &(session[session_id].session_lock), + flags); + return 0; } - spin_unlock_irqrestore( - &(session[session_id].session_lock), - flags); - return 0; + } else { + pr_err("%s: payload size of %x is less than expected.\n", + __func__, data->payload_size); } if ((is_adsp_reg_event(payload[0]) >= 0) || (payload[0] == ASM_STREAM_CMD_SET_PP_PARAMS_V2)) { @@ -2016,19 +2047,27 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) (uint32_t *)data->payload, ac->priv); break; case ASM_CMD_ADD_TOPOLOGIES: - pr_debug("%s:Payload = [0x%x]stat[0x%x]\n", - __func__, payload[0], payload[1]); - if (payload[1] != 0) { - pr_err("%s: cmd = 0x%x returned error = 0x%x\n", - __func__, payload[0], payload[1]); - if (wakeup_flag) { - atomic_set(&ac->mem_state, payload[1]); - wake_up(&ac->mem_wait); + if (data->payload_size >= 2 * sizeof(uint32_t)) { + pr_debug("%s:Payload = [0x%x]stat[0x%x]\n", + __func__, payload[0], + payload[1]); + if (payload[1] != 0) { + pr_err("%s: cmd = 0x%x returned error = 0x%x\n", + __func__, payload[0], + payload[1]); + if (wakeup_flag) { + atomic_set(&ac->mem_state, + payload[1]); + wake_up(&ac->mem_wait); + } + spin_unlock_irqrestore( + &(session[session_id].session_lock), + flags); + return 0; } - spin_unlock_irqrestore( - &(session[session_id].session_lock), - flags); - return 0; + } else { + pr_err("%s: payload size of %x is less than expected.\n", + __func__, data->payload_size); } if (atomic_read(&ac->mem_state) && wakeup_flag) { atomic_set(&ac->mem_state, 0); @@ -2039,8 +2078,12 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) (uint32_t *)data->payload, ac->priv); break; case ASM_DATA_EVENT_WATERMARK: { - pr_debug("%s: Watermark opcode[0x%x] status[0x%x]", - __func__, payload[0], payload[1]); + if (data->payload_size >= 2 * sizeof(uint32_t)) + pr_debug("%s: Watermark opcode[0x%x] status[0x%x]", + __func__, payload[0], payload[1]); + else + pr_err("%s: payload size of %x is less than expected.\n", + __func__, data->payload_size); break; } case ASM_STREAM_CMD_GET_PP_PARAMS_V2: @@ -2052,11 +2095,17 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) /* error or malformed APR packet. Otherwise */ /* response will be returned as */ /* ASM_STREAM_CMDRSP_GET_PP_PARAMS_V2 */ - if (payload[1] != 0) { - pr_err("%s: ASM get param error = %d, resuming\n", - __func__, payload[1]); - rtac_make_asm_callback(ac->session, payload, + if (data->payload_size >= 2 * sizeof(uint32_t)) { + if (payload[1] != 0) { + pr_err("%s: ASM get param error = %d, resuming\n", + __func__, payload[1]); + rtac_make_asm_callback( + ac->session, payload, data->payload_size); + } + } else { + pr_err("%s: payload size of %x is less than expected.\n", + __func__, data->payload_size); } break; case ASM_STREAM_CMD_REGISTER_PP_EVENTS: @@ -2064,11 +2113,16 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) __func__, ac->session, data->opcode, data->token, data->src_port, data->dest_port); - if (payload[1] != 0) - pr_err("%s: ASM get param error = %d, resuming\n", - __func__, payload[1]); - atomic_set(&ac->cmd_state_pp, payload[1]); - wake_up(&ac->cmd_wait); + if (data->payload_size >= 2 * sizeof(uint32_t)) { + if (payload[1] != 0) + pr_err("%s: ASM get param error = %d, resuming\n", + __func__, payload[1]); + atomic_set(&ac->cmd_state_pp, payload[1]); + wake_up(&ac->cmd_wait); + } else { + pr_err("%s: payload size of %x is less than expected.\n", + __func__, data->payload_size); + } break; default: pr_debug("%s: command[0x%x] not expecting rsp\n", @@ -2084,10 +2138,13 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) switch (data->opcode) { case ASM_DATA_EVENT_WRITE_DONE_V2:{ struct audio_port_data *port = &ac->port[IN]; - - dev_vdbg(ac->dev, "%s: Rxed opcode[0x%x] status[0x%x] token[%d]", - __func__, payload[0], payload[1], - data->token); + if (data->payload_size >= 2 * sizeof(uint32_t)) + dev_vdbg(ac->dev, "%s: Rxed opcode[0x%x] status[0x%x] token[%d]", + __func__, payload[0], payload[1], + data->token); + else + dev_err(ac->dev, "%s: payload size of %x is less than expected.\n", + __func__, data->payload_size); if (ac->io_mode & SYNC_IO_MODE) { if (port->buf == NULL) { pr_err("%s: Unexpected Write Done\n", @@ -2103,22 +2160,24 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) pr_debug("%s: Invalid buffer index %u\n", __func__, buf_index); spin_unlock_irqrestore(&port->dsp_lock, - dsp_flags); + dsp_flags); spin_unlock_irqrestore( &(session[session_id].session_lock), flags); return -EINVAL; } - if (lower_32_bits(port->buf[buf_index].phys) != - payload[0] || - msm_audio_populate_upper_32_bits( - port->buf[buf_index].phys) != payload[1]) { + if (data->payload_size >= 2 * sizeof(uint32_t) && + (lower_32_bits(port->buf[buf_index].phys) != + payload[0] || + msm_audio_populate_upper_32_bits( + port->buf[buf_index].phys) + != payload[1])) { pr_debug("%s: Expected addr %pK\n", - __func__, &port->buf[buf_index].phys); + __func__, &port->buf[buf_index].phys); pr_err("%s: rxedl[0x%x] rxedu [0x%x]\n", __func__, payload[0], payload[1]); spin_unlock_irqrestore(&port->dsp_lock, - dsp_flags); + dsp_flags); spin_unlock_irqrestore( &(session[session_id].session_lock), flags); @@ -2147,14 +2206,30 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) } else if (generic_get_data) { generic_get_data->valid = 1; if (generic_get_data->is_inband) { - pr_debug("%s: payload[1] = 0x%x, payload[2]=0x%x, payload[3]=0x%x\n", - __func__, payload[1], payload[2], payload[3]); - generic_get_data->size_in_ints = payload[3]>>2; - for (i = 0; i < payload[3]>>2; i++) { - generic_get_data->ints[i] = - payload[4+i]; - pr_debug("%s: ASM callback val %i = %i\n", - __func__, i, payload[4+i]); + if (data->payload_size >= 4 * sizeof(uint32_t)) + pr_debug("%s: payload[1] = 0x%x, payload[2]=0x%x, payload[3]=0x%x\n", + __func__, payload[1], + payload[2], payload[3]); + else + pr_err("%s: payload size of %x is less than expected.\n", + __func__, + data->payload_size); + + if (data->payload_size >= + (4 + (payload[3]>>2)) * sizeof(uint32_t) + ) + {generic_get_data->size_in_ints = + payload[3]>>2; + for (i = 0; i < payload[3]>>2; i++) { + generic_get_data->ints[i] = + payload[4+i]; + pr_debug("%s: ASM callback val %i = %i\n", + __func__, i, + payload[4+i]); + } + } else { + pr_err("%s: payload size of %x is less than expected.\n", + __func__, data->payload_size); } pr_debug("%s: callback size in ints = %i\n", __func__, @@ -2251,11 +2326,17 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) data->src_port, data->dest_port); break; case ASM_SESSION_CMDRSP_GET_SESSIONTIME_V3: - dev_vdbg(ac->dev, "%s: ASM_SESSION_CMDRSP_GET_SESSIONTIME_V3, payload[0] = %d, payload[1] = %d, payload[2] = %d\n", - __func__, - payload[0], payload[1], payload[2]); - ac->time_stamp = (uint64_t)(((uint64_t)payload[2] << 32) | - payload[1]); + if (data->payload_size >= 3 * sizeof(uint32_t)) { + dev_vdbg(ac->dev, "%s: ASM_SESSION_CMDRSP_GET_SESSIONTIME_V3, payload[0] = %d, payload[1] = %d, payload[2] = %d\n", + __func__, + payload[0], payload[1], payload[2]); + ac->time_stamp = (uint64_t)(( + (uint64_t)payload[2] << 32) | + payload[1]); + } else { + dev_err(ac->dev, "%s: payload size of %x is less than expected.n", + __func__, data->payload_size); + } if (atomic_cmpxchg(&ac->time_flag, 1, 0)) wake_up(&ac->time_wait); break; @@ -2265,10 +2346,14 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) __func__, ac->session, data->opcode, data->token, data->src_port, data->dest_port); - pr_debug("%s: ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY, payload[0] = %d, payload[1] = %d, payload[2] = %d, payload[3] = %d\n", - __func__, - payload[0], payload[1], payload[2], - payload[3]); + if (data->payload_size >= 4 * sizeof(uint32_t)) + pr_debug("%s: ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY, payload[0] = %d, payload[1] = %d, payload[2] = %d, payload[3] = %d\n", + __func__, + payload[0], payload[1], payload[2], + payload[3]); + else + pr_debug("%s: payload size of %x is less than expected.\n", + __func__, data->payload_size); break; case ASM_SESSION_CMDRSP_GET_MTMX_STRTR_PARAMS_V2: q6asm_process_mtmx_get_param_rsp(ac, (void *) payload); @@ -2276,8 +2361,12 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) case ASM_STREAM_PP_EVENT: case ASM_STREAM_CMD_ENCDEC_EVENTS: case ASM_STREAM_CMD_REGISTER_IEC_61937_FMT_UPDATE: - pr_debug("%s: ASM_STREAM_EVENT payload[0][0x%x] payload[1][0x%x]", - __func__, payload[0], payload[1]); + if (data->payload_size >= 2 * sizeof(uint32_t)) + pr_debug("%s: ASM_STREAM_EVENT payload[0][0x%x] payload[1][0x%x]", + __func__, payload[0], payload[1]); + else + pr_debug("%s: payload size of %x is less than expected.\n", + __func__, data->payload_size); i = is_adsp_raise_event(data->opcode); if (i < 0) { spin_unlock_irqrestore( @@ -2318,16 +2407,25 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) &(session[session_id].session_lock), flags); return 0; case ASM_SESSION_CMDRSP_ADJUST_SESSION_CLOCK_V2: - pr_debug("%s: ASM_SESSION_CMDRSP_ADJUST_SESSION_CLOCK_V2 sesion %d status 0x%x msw %u lsw %u\n", - __func__, ac->session, payload[0], payload[2], - payload[1]); + if (data->payload_size >= 3 * sizeof(uint32_t)) + pr_debug("%s: ASM_SESSION_CMDRSP_ADJUST_SESSION_CLOCK_V2 sesion %d status 0x%x msw %u lsw %u\n", + __func__, ac->session, payload[0], payload[2], + payload[1]); + else + pr_err("%s: payload size of %x is less than expected.\n", + __func__, data->payload_size); wake_up(&ac->cmd_wait); break; case ASM_SESSION_CMDRSP_GET_PATH_DELAY_V2: - pr_debug("%s: ASM_SESSION_CMDRSP_GET_PATH_DELAY_V2 session %d status 0x%x msw %u lsw %u\n", - __func__, ac->session, payload[0], payload[2], - payload[1]); - if (payload[0] == 0) { + if (data->payload_size >= 3 * sizeof(uint32_t)) + pr_debug("%s: ASM_SESSION_CMDRSP_GET_PATH_DELAY_V2 session %d status 0x%x msw %u lsw %u\n", + __func__, ac->session, payload[0], + payload[2],payload[1]); + else + pr_err("%s: payload size of %x is less than expected.\n", + __func__, data->payload_size); + if (payload[0] == 0 && + data->payload_size >= 2 * sizeof(uint32_t)) { atomic_set(&ac->cmd_state, 0); /* ignore msw, as a delay that large shouldn't happen */ ac->path_delay = payload[1]; diff --git a/dsp/q6lsm.c b/dsp/q6lsm.c index cf3e81ca..9c153b11 100644 --- a/dsp/q6lsm.c +++ b/dsp/q6lsm.c @@ -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 @@ -175,7 +175,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)); @@ -193,6 +194,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) { @@ -218,6 +220,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", @@ -238,7 +245,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; } @@ -1358,6 +1365,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); @@ -1423,7 +1432,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; } diff --git a/include/dsp/q6lsm.h b/include/dsp/q6lsm.h index efce3a6d..be0e9988 100644 --- a/include/dsp/q6lsm.h +++ b/include/dsp/q6lsm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017, 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 @@ -26,7 +26,7 @@ #define LSM_MAX_NUM_CHANNELS 8 typedef void (*lsm_app_cb)(uint32_t opcode, uint32_t token, - uint32_t *payload, void *priv); + uint32_t *payload, uint16_t client_size, void *priv); struct lsm_sound_model { dma_addr_t phys; |