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

Commit b7678704 authored by Mahesh Voorugonda's avatar Mahesh Voorugonda
Browse files

msm: vidc_3x: Add checks to avoid OOB access



validate structures and payload sizes in the
packet against packet size to avoid OOB access.

Change-Id: I8bc3002e51a18e08b212b13af724480ec48994d7
Signed-off-by: default avatarMahesh Voorugonda <mvooru@codeaurora.org>
parent de5b1d1f
Loading
Loading
Loading
Loading
+79 −17
Original line number Diff line number Diff line
@@ -843,6 +843,20 @@ static enum vidc_status hfi_parse_init_done_properties(
{
	enum vidc_status status = VIDC_ERR_NONE;
	u32 prop_id, next_offset;
#define VALIDATE_PROPERTY_STRUCTURE_SIZE(pkt_size, property_size) ({\
		if (pkt_size < property_size) { \
			status = VIDC_ERR_BAD_PARAM; \
			break; \
		} \
})

#define VALIDATE_PROPERTY_PAYLOAD_SIZE(pkt_size, payload_size, \
		property_count) ({\
		if (pkt_size/payload_size < property_count) { \
			status = VIDC_ERR_BAD_PARAM; \
			break; \
		} \
})

	while (status == VIDC_ERR_NONE && num_properties &&
			rem_bytes >= sizeof(u32)) {
@@ -856,6 +870,9 @@ static enum vidc_status hfi_parse_init_done_properties(
			struct hfi_codec_mask_supported *prop =
				(struct hfi_codec_mask_supported *)
				(data_ptr + next_offset);
			VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
					next_offset,
					sizeof(*prop));

			codecs = prop->codecs;
			domain = prop->video_domains;
@@ -869,11 +886,14 @@ static enum vidc_status hfi_parse_init_done_properties(
				(struct hfi_capability_supported_info *)
				(data_ptr + next_offset);

			if ((rem_bytes - next_offset) < prop->num_capabilities *
				sizeof(struct hfi_capability_supported)) {
				status = VIDC_ERR_BAD_PARAM;
				break;
			}
			VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
					next_offset,
					sizeof(*prop));
			VALIDATE_PROPERTY_PAYLOAD_SIZE(rem_bytes -
					next_offset - sizeof(u32),
					sizeof(struct hfi_capability_supported),
					prop->num_capabilities);

			next_offset += sizeof(u32) +
				prop->num_capabilities *
				sizeof(struct hfi_capability_supported);
@@ -894,10 +914,10 @@ static enum vidc_status hfi_parse_init_done_properties(
			char *fmt_ptr;
			struct hfi_uncompressed_plane_info *plane_info;

			if ((rem_bytes - next_offset) < sizeof(*prop)) {
				status = VIDC_ERR_BAD_PARAM;
				break;
			}
			VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
					next_offset,
					sizeof(*prop));

			num_format_entries = prop->format_entries;
			next_offset = sizeof(*prop);
			fmt_ptr = (char *)&prop->rg_format_info[0];
@@ -908,17 +928,19 @@ static enum vidc_status hfi_parse_init_done_properties(
				plane_info =
				(struct hfi_uncompressed_plane_info *) fmt_ptr;

				if ((rem_bytes - next_offset) <
						sizeof(*plane_info)) {
					status = VIDC_ERR_BAD_PARAM;
					break;
				}
				VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
						next_offset,
						sizeof(*plane_info));

				bytes_to_skip = sizeof(*plane_info) -
					sizeof(struct
					hfi_uncompressed_plane_constraints) +
					plane_info->num_planes *
					sizeof(struct
					hfi_uncompressed_plane_constraints);
				VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
						next_offset,
						bytes_to_skip);

				fmt_ptr += bytes_to_skip;
				next_offset += bytes_to_skip;
@@ -932,6 +954,13 @@ static enum vidc_status hfi_parse_init_done_properties(
			struct hfi_properties_supported *prop =
				(struct hfi_properties_supported *)
				(data_ptr + next_offset);
			VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
					next_offset,
					sizeof(*prop));
			VALIDATE_PROPERTY_PAYLOAD_SIZE(rem_bytes -
					next_offset - sizeof(*prop) +
					sizeof(u32), sizeof(u32),
					prop->num_properties);
			next_offset += sizeof(*prop) - sizeof(u32)
				+ prop->num_properties * sizeof(u32);
			num_properties--;
@@ -948,6 +977,9 @@ static enum vidc_status hfi_parse_init_done_properties(
				(struct hfi_profile_level_supported *)
				(data_ptr + next_offset);

			VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
					next_offset,
					sizeof(*prop));
			ptr = (char *) &prop->rg_profile_level[0];
			prof_count = prop->profile_count;
			next_offset += sizeof(u32);
@@ -960,6 +992,9 @@ static enum vidc_status hfi_parse_init_done_properties(
			}
			while (prof_count) {
				prof_level = (struct hfi_profile_level *)ptr;
				VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
					next_offset,
					sizeof(*prof_level));
				capability.
				profile_level.profile_level[count].profile
					= prof_level->profile;
@@ -976,6 +1011,9 @@ static enum vidc_status hfi_parse_init_done_properties(
		}
		case HFI_PROPERTY_PARAM_INTERLACE_FORMAT_SUPPORTED:
		{
			VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
				next_offset,
				sizeof(struct hfi_interlace_format_supported));
			next_offset +=
				sizeof(struct hfi_interlace_format_supported);
			num_properties--;
@@ -983,6 +1021,9 @@ static enum vidc_status hfi_parse_init_done_properties(
		}
		case HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SUPPORTED:
		{
			VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
				next_offset,
				sizeof(struct hfi_nal_stream_format_supported));
			next_offset +=
				sizeof(struct hfi_nal_stream_format_supported);
			num_properties--;
@@ -990,18 +1031,27 @@ static enum vidc_status hfi_parse_init_done_properties(
		}
		case HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SELECT:
		{
			VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
					next_offset,
					sizeof(u32));
			next_offset += sizeof(u32);
			num_properties--;
			break;
		}
		case HFI_PROPERTY_PARAM_MAX_SEQUENCE_HEADER_SIZE:
		{
			VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
					next_offset,
					sizeof(u32));
			next_offset += sizeof(u32);
			num_properties--;
			break;
		}
		case HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH:
		{
			VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
					next_offset,
					sizeof(struct hfi_intra_refresh));
			next_offset +=
				sizeof(struct hfi_intra_refresh);
			num_properties--;
@@ -1012,13 +1062,21 @@ static enum vidc_status hfi_parse_init_done_properties(
			struct hfi_buffer_alloc_mode_supported *prop =
				(struct hfi_buffer_alloc_mode_supported *)
				(data_ptr + next_offset);

			VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
					next_offset,
					sizeof(*prop));
			if (prop->num_entries >= 32) {
				dprintk(VIDC_ERR,
					"%s - num_entries: %d from f/w seems suspect\n",
					__func__, prop->num_entries);
				break;
			}
			VALIDATE_PROPERTY_PAYLOAD_SIZE(rem_bytes -
				next_offset -
				sizeof(struct hfi_buffer_alloc_mode_supported) +
				sizeof(u32),
				sizeof(u32),
				prop->num_entries);
			next_offset +=
				sizeof(struct hfi_buffer_alloc_mode_supported) -
				sizeof(u32) + prop->num_entries * sizeof(u32);
@@ -1036,8 +1094,12 @@ static enum vidc_status hfi_parse_init_done_properties(
				__func__, data_ptr, prop_id);
			break;
		}
		if (rem_bytes > next_offset) {
			rem_bytes -= next_offset;
			data_ptr += next_offset;
		} else {
			rem_bytes = 0;
		}
	}

	return status;