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

Commit e17e5abc authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: vidc: Avoid information leak while accessing the packet"

parents 7d10a626 7a3956a5
Loading
Loading
Loading
Loading
+86 −11
Original line number Diff line number Diff line
@@ -109,7 +109,7 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
		struct msm_vidc_cb_info *info)
{
	struct msm_vidc_cb_event event_notify = {0};
	int num_properties_changed;
	u32 num_properties_changed;
	struct hfi_frame_size *frame_sz;
	struct hfi_profile_level *profile_level;
	struct hfi_bit_depth *pixel_depth;
@@ -117,17 +117,23 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
	struct hfi_buffer_requirements *buf_req;
	struct hfi_index_extradata_input_crop_payload *crop_info;
	struct hfi_dpb_counts *dpb_counts;
	u32 entropy_mode = 0;
	u32 rem_size, entropy_mode = 0;
	u8 *data_ptr;
	int prop_id;
	int luma_bit_depth, chroma_bit_depth;
	struct hfi_colour_space *colour_info;

	if (sizeof(struct hfi_msg_event_notify_packet) > pkt->size) {
		dprintk(VIDC_ERR,
				"hal_process_session_init_done: bad_pkt_size\n");
#define VALIDATE_PKT_SIZE(__rem_size, __msg_size) ({ \
		if (__rem_size < __msg_size) { \
			dprintk(VIDC_ERR, \
			"hal_process_session_init_done: bad_pkt_size\n"); \
			false; \
		} \
		true; \
	})
	if (!VALIDATE_PKT_SIZE(pkt->size,
			       sizeof(struct hfi_msg_event_notify_packet)))
		return -E2BIG;
	}

	event_notify.device_id = device_id;
	event_notify.session_id = (void *)(uintptr_t)pkt->session_id;
@@ -148,10 +154,18 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,

	if (num_properties_changed) {
		data_ptr = (u8 *) &pkt->rg_ext_event_data[0];
		rem_size = pkt->size - sizeof(struct
				hfi_msg_event_notify_packet) + sizeof(u32);
		do {
			if (!VALIDATE_PKT_SIZE(rem_size, sizeof(u32)))
				return -E2BIG;
			prop_id = (int) *((u32 *)data_ptr);
			rem_size -= sizeof(u32);
			switch (prop_id) {
			case HFI_PROPERTY_PARAM_FRAME_SIZE:
				if (!VALIDATE_PKT_SIZE(rem_size, sizeof(struct
					hfi_frame_size)))
					return -E2BIG;
				data_ptr = data_ptr + sizeof(u32);
				frame_sz =
					(struct hfi_frame_size *) data_ptr;
@@ -161,8 +175,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
					frame_sz->height, frame_sz->width);
				data_ptr +=
					sizeof(struct hfi_frame_size);
				rem_size -= sizeof(struct hfi_frame_size);
				break;
			case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT:
				if (!VALIDATE_PKT_SIZE(rem_size, sizeof(struct
					hfi_profile_level)))
					return -E2BIG;
				data_ptr = data_ptr + sizeof(u32);
				profile_level =
					(struct hfi_profile_level *) data_ptr;
@@ -173,8 +191,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
					profile_level->level);
				data_ptr +=
					sizeof(struct hfi_profile_level);
				rem_size -= sizeof(struct hfi_profile_level);
				break;
			case HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH:
				if (!VALIDATE_PKT_SIZE(rem_size, sizeof(struct
					hfi_bit_depth)))
					return -E2BIG;
				data_ptr = data_ptr + sizeof(u32);
				pixel_depth = (struct hfi_bit_depth *) data_ptr;
				/*
@@ -205,8 +227,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
					event_notify.bit_depth, luma_bit_depth,
					chroma_bit_depth);
				data_ptr += sizeof(struct hfi_bit_depth);
				rem_size -= sizeof(struct hfi_bit_depth);
				break;
			case HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT:
				if (!VALIDATE_PKT_SIZE(rem_size, sizeof(struct
					hfi_pic_struct)))
					return -E2BIG;
				data_ptr = data_ptr + sizeof(u32);
				pic_struct = (struct hfi_pic_struct *) data_ptr;
				event_notify.pic_struct =
@@ -216,8 +242,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
						pic_struct->progressive_only);
				data_ptr +=
					sizeof(struct hfi_pic_struct);
				rem_size -= sizeof(struct hfi_pic_struct);
				break;
			case HFI_PROPERTY_PARAM_VDEC_DPB_COUNTS:
				if (!VALIDATE_PKT_SIZE(rem_size, sizeof(struct
					hfi_dpb_counts)))
					return -E2BIG;
				data_ptr = data_ptr + sizeof(u32);
				dpb_counts = (struct hfi_dpb_counts *) data_ptr;
				event_notify.max_dpb_count =
@@ -232,9 +262,13 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
						dpb_counts->max_ref_count,
						dpb_counts->max_dec_buffering);
				data_ptr +=
					sizeof(struct hfi_pic_struct);
					sizeof(struct hfi_dpb_counts);
				rem_size -= sizeof(struct hfi_dpb_counts);
				break;
			case HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE:
				if (!VALIDATE_PKT_SIZE(rem_size, sizeof(struct
					hfi_colour_space)))
					return -E2BIG;
				data_ptr = data_ptr + sizeof(u32);
				colour_info =
					(struct hfi_colour_space *) data_ptr;
@@ -245,8 +279,11 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
						colour_info->colour_space);
				data_ptr +=
					sizeof(struct hfi_colour_space);
				rem_size -= sizeof(struct hfi_colour_space);
				break;
			case HFI_PROPERTY_CONFIG_VDEC_ENTROPY:
				if (!VALIDATE_PKT_SIZE(rem_size, sizeof(u32)))
					return -E2BIG;
				data_ptr = data_ptr + sizeof(u32);
				entropy_mode = *(u32 *)data_ptr;
				event_notify.entropy_mode = entropy_mode;
@@ -254,8 +291,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
					"Entropy Mode: 0x%x\n", entropy_mode);
				data_ptr +=
					sizeof(u32);
				rem_size -= sizeof(u32);
				break;
			case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS:
				if (!VALIDATE_PKT_SIZE(rem_size, sizeof(struct
					hfi_buffer_requirements)))
					return -E2BIG;
				data_ptr = data_ptr + sizeof(u32);
				buf_req =
					(struct hfi_buffer_requirements *)
@@ -267,8 +308,13 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
						event_notify.capture_buf_count);
				data_ptr +=
					sizeof(struct hfi_buffer_requirements);
				rem_size -=
					sizeof(struct hfi_buffer_requirements);
				break;
			case HFI_INDEX_EXTRADATA_INPUT_CROP:
				if (!VALIDATE_PKT_SIZE(rem_size, sizeof(struct
				     hfi_index_extradata_input_crop_payload)))
					return -E2BIG;
				data_ptr = data_ptr + sizeof(u32);
				crop_info = (struct
				hfi_index_extradata_input_crop_payload *)
@@ -289,6 +335,8 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
				data_ptr +=
					sizeof(struct
					hfi_index_extradata_input_crop_payload);
				rem_size -= sizeof(struct
					hfi_index_extradata_input_crop_payload);
				break;
			default:
				dprintk(VIDC_ERR,
@@ -299,6 +347,7 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
			num_properties_changed--;
		} while (num_properties_changed > 0);
	}
#undef VALIDATE_PKT_SIZE

	info->response_type = HAL_SESSION_EVENT_CHANGE;
	info->response.event = event_notify;
@@ -754,7 +803,7 @@ static inline void copy_cap_prop(
}

static int hfi_fill_codec_info(u8 *data_ptr,
		struct vidc_hal_sys_init_done *sys_init_done)
		struct vidc_hal_sys_init_done *sys_init_done, u32 rem_size)
{
	u32 i;
	u32 codecs = 0, codec_count = 0, size = 0;
@@ -762,9 +811,20 @@ static int hfi_fill_codec_info(u8 *data_ptr,
	u32 prop_id = *((u32 *)data_ptr);
	u8 *orig_data_ptr = data_ptr;

#define VALIDATE_PKT_SIZE(__rem_size, __msg_size) ({ \
		if (__rem_size < __msg_size) { \
			dprintk(VIDC_ERR, \
			"hfi_msg_sys_init_done: Bad packet size\n"); \
			false; \
		} \
		true; \
	})
	if (prop_id ==  HFI_PROPERTY_PARAM_CODEC_SUPPORTED) {
		struct hfi_codec_supported *prop;

		if (!VALIDATE_PKT_SIZE(rem_size - sizeof(u32),
				       sizeof(struct hfi_codec_supported)))
			return -E2BIG;
		data_ptr = data_ptr + sizeof(u32);
		prop = (struct hfi_codec_supported *) data_ptr;
		sys_init_done->dec_codec_supported =
@@ -772,6 +832,8 @@ static int hfi_fill_codec_info(u8 *data_ptr,
		sys_init_done->enc_codec_supported =
			prop->encoder_codec_supported;
		size = sizeof(struct hfi_codec_supported) + sizeof(u32);
		rem_size -=
			sizeof(struct hfi_codec_supported) + sizeof(u32);
	} else {
		dprintk(VIDC_WARN,
			"%s: prop_id %#x, expected codec_supported property\n",
@@ -812,17 +874,26 @@ static int hfi_fill_codec_info(u8 *data_ptr,
	}
	sys_init_done->codec_count = codec_count;

	if (!VALIDATE_PKT_SIZE(rem_size, sizeof(u32)))
		return -E2BIG;
	prop_id = *((u32 *)(orig_data_ptr + size));
	if (prop_id == HFI_PROPERTY_PARAM_MAX_SESSIONS_SUPPORTED) {
		struct hfi_max_sessions_supported *prop =
			(struct hfi_max_sessions_supported *)
		struct hfi_max_sessions_supported *prop;

		if (!VALIDATE_PKT_SIZE(rem_size - sizeof(u32), sizeof(struct
				hfi_max_sessions_supported)))
			return -E2BIG;
		prop = (struct hfi_max_sessions_supported *)
			(orig_data_ptr + size + sizeof(u32));

		sys_init_done->max_sessions_supported = prop->max_sessions;
		size += sizeof(struct hfi_max_sessions_supported) + sizeof(u32);
		rem_size -=
			sizeof(struct hfi_max_sessions_supported) + sizeof(u32);
		dprintk(VIDC_DBG, "max_sessions_supported %d\n",
				prop->max_sessions);
	}
#undef VALIDATE_PKT_SIZE
	return size;
}

@@ -1184,6 +1255,10 @@ enum vidc_status hfi_process_sys_init_done_prop_read(
			"hfi_msg_sys_init_done: Invalid input\n");
		return VIDC_ERR_FAIL;
	}
	if (pkt->size < sizeof(struct hfi_msg_sys_init_done_packet)) {
		dprintk(VIDC_ERR, "hfi_msg_sys_init_done: bad packet size\n");
		return VIDC_ERR_FAIL;
	}

	rem_bytes = pkt->size - sizeof(struct
			hfi_msg_sys_init_done_packet) + sizeof(u32);
@@ -1211,7 +1286,7 @@ enum vidc_status hfi_process_sys_init_done_prop_read(
			"Venus didn't set any properties in SYS_INIT_DONE");
		return status;
	}
	bytes_read = hfi_fill_codec_info(data_ptr, sys_init_done);
	bytes_read = hfi_fill_codec_info(data_ptr, sys_init_done, rem_bytes);
	data_ptr += bytes_read;
	rem_bytes -= bytes_read;
	num_properties--;