Merge "msm: adm: validate ADSP payload size before access"

This commit is contained in:
Linux Build Service Account 2019-05-24 10:20:00 -07:00 committed by Gerrit - the friendly Code Review server
commit 10da01940d

View file

@ -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 * 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 * 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) { switch (opcode) {
case ADM_CMDRSP_GET_PP_PARAMS_V5: case ADM_CMDRSP_GET_PP_PARAMS_V5:
struct_size = sizeof(struct adm_cmd_rsp_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; v5_rsp = (struct adm_cmd_rsp_get_pp_params_v5 *) payload;
data_size = v5_rsp->param_hdr.param_size; data_size = v5_rsp->param_hdr.param_size;
param_data = v5_rsp->param_data; param_data = v5_rsp->param_data;
break; break;
case ADM_CMDRSP_GET_PP_PARAMS_V6: case ADM_CMDRSP_GET_PP_PARAMS_V6:
struct_size = sizeof(struct adm_cmd_rsp_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; v6_rsp = (struct adm_cmd_rsp_get_pp_params_v6 *) payload;
data_size = v6_rsp->param_hdr.param_size; data_size = v6_rsp->param_hdr.param_size;
param_data = v6_rsp->param_data; 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); adm_callback_debug_print(data);
if (data->payload_size) { if (data->payload_size >= sizeof(uint32_t)) {
copp_idx = (data->token) & 0XFF; copp_idx = (data->token) & 0XFF;
port_idx = ((data->token) >> 16) & 0xFF; port_idx = ((data->token) >> 16) & 0xFF;
client_id = ((data->token) >> 8) & 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) { if (data->opcode == APR_BASIC_RSP_RESULT) {
pr_debug("%s: APR_BASIC_RSP_RESULT id 0x%x\n", pr_debug("%s: APR_BASIC_RSP_RESULT id 0x%x\n",
__func__, payload[0]); __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) { if (payload[1] != 0) {
pr_err("%s: cmd = 0x%x returned error = 0x%x\n", pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
__func__, payload[0], payload[1]); __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_V5:
case ADM_CMDRSP_DEVICE_OPEN_V6: case ADM_CMDRSP_DEVICE_OPEN_V6:
case ADM_CMDRSP_DEVICE_OPEN_V8: { case ADM_CMDRSP_DEVICE_OPEN_V8: {
struct adm_cmd_rsp_device_open_v5 *open = struct adm_cmd_rsp_device_open_v5 *open = NULL;
(struct adm_cmd_rsp_device_open_v5 *)data->payload;
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) { if (open->copp_id == INVALID_COPP_ID) {
pr_err("%s: invalid coppid rxed %d\n", pr_err("%s: invalid coppid rxed %d\n",
__func__, open->copp_id); __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: case ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST_V2:
pr_debug("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST\n", pr_debug("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST\n",
__func__); __func__);
num_modules = payload[1]; if (data->payload_size >= (2 * sizeof(uint32_t))) {
pr_debug("%s: Num modules %d\n", __func__, num_modules); num_modules = payload[1];
if (payload[0]) { pr_debug("%s: Num modules %d\n", __func__,
pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST, error = %d\n", num_modules);
__func__, payload[0]); if (payload[0]) {
} else if (num_modules > MAX_MODULES_IN_TOPO) { pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST, error = %d\n",
pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST invalid num modules received, num modules = %d\n", __func__, payload[0]);
__func__, num_modules); } 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 { } else {
ret = adm_process_get_topo_list_response( pr_err("%s: Invalid payload size %d\n",
data->opcode, copp_idx, num_modules, __func__, data->payload_size);
payload, data->payload_size);
if (ret)
pr_err("%s: Failed to process get topo modules list response, error %d\n",
__func__, ret);
} }
atomic_set(&this_adm.copp.stat[port_idx][copp_idx], atomic_set(&this_adm.copp.stat[port_idx][copp_idx],
payload[0]); payload[0]);