aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/media/platform/msm/vidc/hfi_response_handler.c93
1 files changed, 82 insertions, 11 deletions
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index 4c0e1ddfda89..49925fcb7a4c 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -104,12 +104,22 @@ static int 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;
@@ -123,11 +133,9 @@ static int hfi_process_sess_evt_seq_changed(u32 device_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");
+ 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 +156,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 +177,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 +193,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 +229,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 +244,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 +264,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 +281,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 +293,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 +310,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 +337,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,
@@ -742,7 +792,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;
@@ -753,6 +803,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 =
@@ -760,6 +813,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",
@@ -800,14 +855,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);
}
@@ -1164,7 +1227,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) {
@@ -1172,6 +1236,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);
@@ -1199,7 +1268,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--;