Merge branch 'android-msm-pixel-4.9-qt' into android-msm-pixel-4.9-qt-qpr1
Feb 2020.1
Bug: 145881496
Bug: 145880318
Change-Id: I8b52fd2e170a2a3c4d01e013cea266e0772a15d6
Signed-off-by: Rick Yiu <rickyiu@google.com>
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index a1b6bf0..795ceb6 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -1772,6 +1772,7 @@
mask_info->update_buf = kzalloc(update_buf_len, GFP_KERNEL);
if (!mask_info->update_buf) {
kfree(mask_info->ptr);
+ mask_info->ptr = NULL;
return -ENOMEM;
}
kmemleak_not_leak(mask_info->update_buf);
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
index 5d20e22..3f566de 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
@@ -24,6 +24,32 @@
#include "cam_req_mgr_dev.h"
static struct cam_req_mgr_core_device *g_crm_core_dev;
+static struct cam_req_mgr_core_link g_links[MAX_LINKS_PER_SESSION];
+
+static void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link)
+{
+ link->link_hdl = 0;
+ link->num_devs = 0;
+ link->max_delay = CAM_PIPELINE_DELAY_0;
+ link->workq = NULL;
+ link->pd_mask = 0;
+ link->l_dev = NULL;
+ link->req.in_q = NULL;
+ link->req.l_tbl = NULL;
+ link->req.num_tbl = 0;
+ link->watchdog = NULL;
+ link->state = CAM_CRM_LINK_STATE_AVAILABLE;
+ link->parent = NULL;
+ link->subscribe_event = 0;
+ link->trigger_mask = 0;
+ link->sync_link = NULL;
+ link->sof_counter = 0;
+ link->sync_self_ref = 0;
+ link->frame_skip_flag = false;
+ link->sync_link_sof_skip = false;
+ link->open_req_cnt = 0;
+ link->last_flush_id = 0;
+}
void cam_req_mgr_handle_core_shutdown(void)
{
@@ -1232,25 +1258,25 @@
session->num_links, MAX_LINKS_PER_SESSION);
return NULL;
}
-
- link = (struct cam_req_mgr_core_link *)
- kzalloc(sizeof(struct cam_req_mgr_core_link), GFP_KERNEL);
- if (!link) {
- CAM_ERR(CAM_CRM, "failed to create link, no mem");
- return NULL;
+ for (i = 0; i < MAX_LINKS_PER_SESSION; i++) {
+ if (!atomic_cmpxchg(&g_links[i].is_used, 0, 1)) {
+ link = &g_links[i];
+ CAM_DBG(CAM_CRM, "alloc link index %d", i);
+ cam_req_mgr_core_link_reset(link);
+ break;
+ }
}
+ if (i == MAX_LINKS_PER_SESSION)
+ return NULL;
+
in_q = (struct cam_req_mgr_req_queue *)
kzalloc(sizeof(struct cam_req_mgr_req_queue), GFP_KERNEL);
if (!in_q) {
CAM_ERR(CAM_CRM, "failed to create input queue, no mem");
- kfree(link);
return NULL;
}
- mutex_init(&link->lock);
- spin_lock_init(&link->link_state_spin_lock);
mutex_lock(&link->lock);
- link->state = CAM_CRM_LINK_STATE_AVAILABLE;
link->num_devs = 0;
link->max_delay = 0;
memset(in_q->slot, 0,
@@ -1287,7 +1313,6 @@
return link;
error:
mutex_unlock(&session->lock);
- kfree(link);
kfree(in_q);
return NULL;
}
@@ -1302,9 +1327,12 @@
*/
static void __cam_req_mgr_free_link(struct cam_req_mgr_core_link *link)
{
+ ptrdiff_t i;
kfree(link->req.in_q);
link->req.in_q = NULL;
- kfree(link);
+ i = link - g_links;
+ CAM_DBG(CAM_CRM, "free link index %d", i);
+ atomic_set(&g_links[i].is_used, 0);
}
/**
@@ -2712,6 +2740,7 @@
int cam_req_mgr_core_device_init(void)
{
+ int i;
CAM_DBG(CAM_CRM, "Enter g_crm_core_dev %pK", g_crm_core_dev);
if (g_crm_core_dev) {
@@ -2728,6 +2757,12 @@
mutex_init(&g_crm_core_dev->crm_lock);
cam_req_mgr_debug_register(g_crm_core_dev);
+ for (i = 0; i < MAX_LINKS_PER_SESSION; i++) {
+ mutex_init(&g_links[i].lock);
+ spin_lock_init(&g_links[i].link_state_spin_lock);
+ atomic_set(&g_links[i].is_used, 0);
+ cam_req_mgr_core_link_reset(&g_links[i]);
+ }
return 0;
}
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h
index b19a043..1fe1bc6 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h
@@ -305,6 +305,8 @@
* frame in sync link as well.
* @open_req_cnt : Counter to keep track of open requests that are yet
* to be serviced in the kernel.
+ * @last_flush_id : Last request to flush
+ * @is_used : 1 if link is in use else 0
*
*/
struct cam_req_mgr_core_link {
@@ -329,6 +331,8 @@
bool frame_skip_flag;
bool sync_link_sof_skip;
int32_t open_req_cnt;
+ uint32_t last_flush_id;
+ atomic_t is_used;
};
/**
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index fee428a..554374c 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -103,12 +103,22 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
"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 @@
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 @@
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 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 @@
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 @@
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 @@
}
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);
}
@@ -933,6 +996,21 @@
u32 prop_id, next_offset;
u32 codecs = 0, domain = 0;
+#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)) {
@@ -946,6 +1024,10 @@
(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;
next_offset += sizeof(struct hfi_codec_mask_supported);
@@ -958,11 +1040,14 @@
(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);
@@ -983,10 +1068,10 @@
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];
@@ -997,11 +1082,10 @@
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) +
@@ -1009,6 +1093,10 @@
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;
num_format_entries--;
@@ -1021,6 +1109,15 @@
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--;
@@ -1032,6 +1129,15 @@
(struct hfi_profile_level_supported *)
(data_ptr + next_offset);
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*prop));
+ VALIDATE_PROPERTY_PAYLOAD_SIZE(rem_bytes -
+ next_offset -
+ sizeof(u32),
+ sizeof(struct hfi_profile_level),
+ prop->profile_count);
+
next_offset += sizeof(u32) +
prop->profile_count *
sizeof(struct hfi_profile_level);
@@ -1056,6 +1162,10 @@
(struct hfi_nal_stream_format_supported *)
(data_ptr + next_offset);
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*prop));
+
copy_nal_stream_format_caps_to_sessions(
prop->nal_stream_format_supported,
capabilities, num_sessions,
@@ -1068,12 +1178,18 @@
}
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_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--;
@@ -1081,6 +1197,9 @@
}
case HFI_PROPERTY_TME_VERSION_SUPPORTED:
{
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(u32));
capabilities->tme_version =
*((u32 *)(data_ptr + next_offset));
next_offset +=
@@ -1094,8 +1213,13 @@
__func__, data_ptr, prop_id);
break;
}
- rem_bytes -= next_offset;
- data_ptr += next_offset;
+
+ if (rem_bytes > next_offset) {
+ rem_bytes -= next_offset;
+ data_ptr += next_offset;
+ } else {
+ rem_bytes = 0;
+ }
}
return status;
@@ -1106,7 +1230,8 @@
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) {
@@ -1114,6 +1239,11 @@
"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);
@@ -1141,7 +1271,9 @@
"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--;
diff --git a/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c b/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c
index 9f85f5d..08f3e1a 100644
--- a/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c
@@ -100,12 +100,22 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 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 @@
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 @@
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 @@
}
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);
}
@@ -798,6 +843,20 @@
{
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)) {
@@ -811,6 +870,9 @@
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;
@@ -824,11 +886,14 @@
(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);
@@ -849,10 +914,10 @@
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];
@@ -863,17 +928,19 @@
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;
@@ -887,6 +954,13 @@
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--;
@@ -903,6 +977,9 @@
(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);
@@ -915,6 +992,9 @@
}
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;
@@ -931,6 +1011,9 @@
}
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--;
@@ -938,6 +1021,9 @@
}
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--;
@@ -945,18 +1031,27 @@
}
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--;
@@ -967,13 +1062,21 @@
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);
@@ -991,8 +1094,12 @@
__func__, data_ptr, prop_id);
break;
}
- rem_bytes -= next_offset;
- data_ptr += next_offset;
+ if (rem_bytes > next_offset) {
+ rem_bytes -= next_offset;
+ data_ptr += next_offset;
+ } else {
+ rem_bytes = 0;
+ }
}
return status;
@@ -1003,7 +1110,8 @@
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 +1120,11 @@
"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 +1152,9 @@
"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--;
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index 30c0ee1..66fd031 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -1350,7 +1350,7 @@
for (i = 0; i < resp.mem_region_info_len; i++) {
if (resp.mem_region_info[i].size > penv->msa_mem_size ||
- resp.mem_region_info[i].region_addr > max_mapped_addr ||
+ resp.mem_region_info[i].region_addr >= max_mapped_addr ||
resp.mem_region_info[i].region_addr < penv->msa_pa ||
resp.mem_region_info[i].size +
resp.mem_region_info[i].region_addr > max_mapped_addr) {
diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
index 0c71938..53f9bea 100644
--- a/drivers/usb/gadget/udc/core.c
+++ b/drivers/usb/gadget/udc/core.c
@@ -857,6 +857,8 @@
dev_err(dev, "failed to map buffer\n");
return -EFAULT;
}
+
+ req->dma_mapped = 1;
}
return 0;
@@ -881,9 +883,10 @@
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
req->num_mapped_sgs = 0;
- } else if (req->dma != DMA_ERROR_CODE) {
+ } else if (req->dma_mapped) {
dma_unmap_single(dev, req->dma, req->length,
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+ req->dma_mapped = 0;
}
}
EXPORT_SYMBOL_GPL(usb_gadget_unmap_request_by_dev);
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 0267bed..7c9e8aa 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -147,6 +147,7 @@
* by adding a zero length packet as needed;
* @short_not_ok: When reading data, makes short packets be
* treated as errors (queue stops advancing till cleanup).
+ * @dma_mapped: Indicates if request has been mapped to DMA (internal)
* @complete: Function called when request completes, so this request and
* its buffer may be re-used. The function will always be called with
* interrupts disabled, and it must not sleep.
@@ -203,6 +204,7 @@
unsigned no_interrupt:1;
unsigned zero:1;
unsigned short_not_ok:1;
+ unsigned dma_mapped:1;
void (*complete)(struct usb_ep *ep,
struct usb_request *req);