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

Commit 5b134f53 authored by Vignesh Kulothungan's avatar Vignesh Kulothungan Committed by Gerrit - the friendly Code Review server
Browse files

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: default avatarVignesh Kulothungan <vigneshk@codeaurora.org>
parent ecfba02e
Loading
Loading
Loading
Loading
+51 −17
Original line number Original line Diff line number Diff line
@@ -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,8 +1630,10 @@ 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__);
			if (data->payload_size >= (2 * sizeof(uint32_t))) {
				num_modules = payload[1];
				num_modules = payload[1];
			pr_debug("%s: Num modules %d\n", __func__, num_modules);
				pr_debug("%s: Num modules %d\n", __func__,
					 num_modules);
				if (payload[0]) {
				if (payload[0]) {
					pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST, error = %d\n",
					pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST, error = %d\n",
					       __func__, payload[0]);
					       __func__, payload[0]);
@@ -1612,13 +1641,18 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv)
					pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST invalid num modules received, num modules = %d\n",
					pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST invalid num modules received, num modules = %d\n",
					       __func__, num_modules);
					       __func__, num_modules);
				} else {
				} else {
				ret = adm_process_get_topo_list_response(
					ret = adm_process_get_topo_list_response
					data->opcode, copp_idx, num_modules,
						(data->opcode, copp_idx,
					payload, data->payload_size);
						num_modules, payload,
						data->payload_size);
					if (ret)
					if (ret)
						pr_err("%s: Failed to process get topo modules list response, error %d\n",
						pr_err("%s: Failed to process get topo modules list response, error %d\n",
						       __func__, ret);
						       __func__, ret);
				}
				}
			} else {
				pr_err("%s: Invalid payload size %d\n",
					__func__, data->payload_size);
			}
			atomic_set(&this_adm.copp.stat[port_idx][copp_idx],
			atomic_set(&this_adm.copp.stat[port_idx][copp_idx],
				   payload[0]);
				   payload[0]);
			wake_up(&this_adm.copp.wait[port_idx][copp_idx]);
			wake_up(&this_adm.copp.wait[port_idx][copp_idx]);