From a935cbe4375cde0027646c6e838b98243be84e22 Mon Sep 17 00:00:00 2001 From: Vignesh Kulothungan Date: Thu, 28 Feb 2019 15:38:00 -0800 Subject: [PATCH] msm: adm: validate ADSP payload size before access Check the size of ADSP payload before accessing it. CRs-Fixed: 2380694 Change-Id: Icdc19a85b39a397ba6d7177f42ece4626b901832 Signed-off-by: Vignesh Kulothungan --- sound/soc/msm/qdsp6v2/q6adm.c | 70 ++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 18 deletions(-) diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c index c6f3b5ba96ba..8569f5d2243a 100644 --- a/sound/soc/msm/qdsp6v2/q6adm.c +++ b/sound/soc/msm/qdsp6v2/q6adm.c @@ -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 @@ -1230,12 +1230,22 @@ static int adm_process_get_param_response(u32 opcode, u32 idx, u32 *payload, switch (opcode) { case ADM_CMDRSP_GET_PP_PARAMS_V5: struct_size = sizeof(struct adm_cmd_rsp_get_pp_params_v5); + if (payload_size < struct_size) { + pr_err("%s: payload size %d < expected size %d\n", + __func__, payload_size, struct_size); + break; + } v5_rsp = (struct adm_cmd_rsp_get_pp_params_v5 *) payload; data_size = v5_rsp->param_hdr.param_size; param_data = v5_rsp->param_data; break; case ADM_CMDRSP_GET_PP_PARAMS_V6: struct_size = sizeof(struct adm_cmd_rsp_get_pp_params_v6); + if (payload_size < struct_size) { + pr_err("%s: payload size %d < expected size %d\n", + __func__, payload_size, struct_size); + break; + } v6_rsp = (struct adm_cmd_rsp_get_pp_params_v6 *) payload; data_size = v6_rsp->param_hdr.param_size; param_data = v6_rsp->param_data; @@ -1399,7 +1409,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; @@ -1421,6 +1431,16 @@ 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) || + (payload[0] == ADM_CMD_SET_PP_PARAMS_V6)))) { + 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]); @@ -1545,9 +1565,16 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv) case ADM_CMDRSP_DEVICE_OPEN_V5: case ADM_CMDRSP_DEVICE_OPEN_V6: case ADM_CMDRSP_DEVICE_OPEN_V8: { - 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); @@ -1603,21 +1630,28 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv) case ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST_V2: pr_debug("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST\n", __func__); - num_modules = payload[1]; - pr_debug("%s: Num modules %d\n", __func__, num_modules); - if (payload[0]) { - pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST, error = %d\n", - __func__, payload[0]); - } else if (num_modules > MAX_MODULES_IN_TOPO) { - pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST invalid num modules received, num modules = %d\n", - __func__, num_modules); + if (data->payload_size >= (2 * sizeof(uint32_t))) { + num_modules = payload[1]; + pr_debug("%s: Num modules %d\n", __func__, + num_modules); + if (payload[0]) { + pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST, error = %d\n", + __func__, payload[0]); + } else if (num_modules > MAX_MODULES_IN_TOPO) { + pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST invalid num modules received, num modules = %d\n", + __func__, num_modules); + } else { + ret = adm_process_get_topo_list_response + (data->opcode, copp_idx, + num_modules, payload, + data->payload_size); + if (ret) + pr_err("%s: Failed to process get topo modules list response, error %d\n", + __func__, ret); + } } else { - ret = adm_process_get_topo_list_response( - data->opcode, copp_idx, num_modules, - payload, data->payload_size); - if (ret) - pr_err("%s: Failed to process get topo modules list response, error %d\n", - __func__, ret); + pr_err("%s: Invalid payload size %d\n", + __func__, data->payload_size); } atomic_set(&this_adm.copp.stat[port_idx][copp_idx], payload[0]);