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

Commit 146756d4 authored by Priyanka Gujjula's avatar Priyanka Gujjula
Browse files

msm: vidc: Avoid information leak while accessing the packet



Use trusted packet size on the received packet and check
for the size of the data received against the expected
size before accessing the packet.

Change-Id: I1bd6008249a0bf4edeec711ec8d23cf7b8dac1f1
Signed-off-by: default avatarPriyanka Gujjula <pgujjula@codeaurora.org>
parent 96aa5972
Loading
Loading
Loading
Loading
+83 −12
Original line number Diff line number Diff line
@@ -103,12 +103,22 @@ static enum msm_vidc_pixel_depth get_hal_pixel_depth(u32 hfi_bit_depth)
	return MSM_VIDC_BIT_DEPTH_UNSUPPORTED;
}

static inline int validate_pkt_size(u32 rem_size, u32 msg_size)
{
	if (rem_size < msg_size) {
		dprintk(VIDC_ERR, "%s: bad_pkt_size: %d\n",
			__func__, rem_size);
		return false;
	}
	return true;
}

static int hfi_process_sess_evt_seq_changed(u32 device_id,
		struct hfi_msg_event_notify_packet *pkt,
		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;
@@ -116,17 +126,15 @@ 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;
	enum msm_vidc_pixel_depth 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");
	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;
@@ -147,10 +155,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;
@@ -160,8 +176,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;
@@ -172,8 +192,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;
				/*
@@ -204,8 +228,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 =
@@ -215,8 +243,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 =
@@ -231,9 +263,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;
@@ -244,8 +280,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;
@@ -253,8 +292,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 *)
@@ -266,8 +309,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 *)
@@ -288,6 +336,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,
@@ -747,7 +797,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;
	struct msm_vidc_capability *capability;
@@ -757,6 +807,9 @@ static int hfi_fill_codec_info(u8 *data_ptr,
	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 =
@@ -764,6 +817,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",
@@ -804,14 +859,22 @@ 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);
	}
@@ -1167,7 +1230,8 @@ enum vidc_status hfi_process_sys_init_done_prop_read(
	struct vidc_hal_sys_init_done *sys_init_done)
{
	enum vidc_status status = VIDC_ERR_NONE;
	u32 rem_bytes, bytes_read, num_properties;
	int bytes_read;
	u32 rem_bytes, num_properties;
	u8 *data_ptr;

	if (!pkt || !sys_init_done) {
@@ -1175,6 +1239,11 @@ 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, "%s: bad_packet_size: %d\n",
			__func__, pkt->size);
		return VIDC_ERR_FAIL;
	}

	rem_bytes = pkt->size - sizeof(struct
			hfi_msg_sys_init_done_packet) + sizeof(u32);
@@ -1202,7 +1271,9 @@ 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);
	if (bytes_read < 0)
		return VIDC_ERR_FAIL;
	data_ptr += bytes_read;
	rem_bytes -= bytes_read;
	num_properties--;
+65 −12
Original line number Diff line number Diff line
@@ -100,12 +100,22 @@ static enum msm_vidc_pixel_depth get_hal_pixel_depth(u32 hfi_bit_depth)
	return MSM_VIDC_BIT_DEPTH_UNSUPPORTED;
}

static inline int validate_pkt_size(u32 rem_size, u32 msg_size)
{
	if (rem_size < msg_size) {
		dprintk(VIDC_ERR, "%s: bad_pkt_size: %d\n",
			__func__, rem_size);
		return false;
	}
	return true;
}

static int hfi_process_sess_evt_seq_changed(u32 device_id,
		struct hfi_msg_event_notify_packet *pkt,
		struct msm_vidc_cb_info *info)
{
	struct msm_vidc_cb_event event_notify = {0};
	int num_properties_changed;
	u32 num_properties_changed, rem_size;
	struct hfi_frame_size *frame_sz;
	struct hfi_profile_level *profile_level;
	struct hfi_bit_depth *pixel_depth;
@@ -114,15 +124,11 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
	int prop_id;
	enum msm_vidc_pixel_depth luma_bit_depth, chroma_bit_depth;
	struct hfi_colour_space *colour_info;

	 /* Initialize pic_struct to unknown as default */
	event_notify.pic_struct = MSM_VIDC_PIC_STRUCT_UNKNOWN;

	if (sizeof(struct hfi_msg_event_notify_packet) > pkt->size) {
		dprintk(VIDC_ERR,
				"hal_process_session_init_done: bad_pkt_size\n");
	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;
@@ -143,10 +149,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;
@@ -156,8 +170,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;
@@ -166,8 +184,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;
				/*
@@ -198,8 +220,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 =
@@ -209,8 +235,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_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;
@@ -221,6 +251,8 @@ 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;
				break;
			default:
				dprintk(VIDC_ERR,
@@ -579,7 +611,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;
	struct msm_vidc_capability *capability;
@@ -589,6 +621,9 @@ static int hfi_fill_codec_info(u8 *data_ptr,
	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 =
@@ -596,6 +631,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",
@@ -636,14 +673,22 @@ 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);
	}
@@ -1003,7 +1048,8 @@ enum vidc_status hfi_process_sys_init_done_prop_read(
	struct vidc_hal_sys_init_done *sys_init_done)
{
	enum vidc_status status = VIDC_ERR_NONE;
	u32 rem_bytes, bytes_read, num_properties;
	int bytes_read;
	u32 rem_bytes, num_properties;
	u8 *data_ptr;
	u32 codecs = 0, domain = 0;

@@ -1012,6 +1058,11 @@ 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, "%s: bad packet size: %d\n",
			__func__, pkt->size);
		return VIDC_ERR_FAIL;
	}

	rem_bytes = pkt->size - sizeof(struct
			hfi_msg_sys_init_done_packet) + sizeof(u32);
@@ -1039,7 +1090,9 @@ 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);
	if (bytes_read < 0)
		return VIDC_ERR_FAIL;
	data_ptr += bytes_read;
	rem_bytes -= bytes_read;
	num_properties--;