Merge "msm: vidc: Validate session_id in video hardware response"
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index 653ba46..8350dde 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -78,6 +78,26 @@
return vidc_err;
}
+static int sanitize_session_pkt(struct list_head *sessions,
+ struct hal_session *sess, struct mutex *session_lock)
+{
+ struct hal_session *session;
+ int invalid = 1;
+ if (session_lock) {
+ mutex_lock(session_lock);
+ list_for_each_entry(session, sessions, list) {
+ if (session == sess) {
+ invalid = 0;
+ break;
+ }
+ }
+ mutex_unlock(session_lock);
+ }
+ if (invalid)
+ dprintk(VIDC_WARN, "Invalid session from FW: %p\n", sess);
+ return invalid;
+}
+
static void hfi_process_sess_evt_seq_changed(
msm_vidc_callback callback, u32 device_id,
struct hfi_msg_event_notify_packet *pkt)
@@ -1115,9 +1135,11 @@
u32 hfi_process_msg_packet(
msm_vidc_callback callback, u32 device_id,
- struct vidc_hal_msg_pkt_hdr *msg_hdr)
+ struct vidc_hal_msg_pkt_hdr *msg_hdr,
+ struct list_head *sessions, struct mutex *session_lock)
{
u32 rc = 0;
+ struct hal_session *sess;
if (!callback || !msg_hdr || msg_hdr->size <
VIDC_IFACEQ_MIN_PKT_SIZE) {
dprintk(VIDC_ERR, "hal_process_msg_packet:bad"
@@ -1126,10 +1148,19 @@
return rc;
}
+#define SANITIZE_SESSION_PKT(msg_pkt) ({ \
+ sess = (struct hal_session *) \
+ (((struct vidc_hal_session_cmd_pkt *) \
+ msg_pkt)->session_id); \
+ if (sanitize_session_pkt(sessions, sess, session_lock)) \
+ break; \
+ })
+
dprintk(VIDC_INFO, "Received: 0x%x in ", msg_hdr->packet);
rc = (u32) msg_hdr->packet;
switch (msg_hdr->packet) {
case HFI_MSG_EVENT_NOTIFY:
+ SANITIZE_SESSION_PKT(msg_hdr);
hfi_process_event_notify(callback, device_id,
(struct hfi_msg_event_notify_packet *) msg_hdr);
break;
@@ -1141,6 +1172,7 @@
case HFI_MSG_SYS_IDLE:
break;
case HFI_MSG_SYS_SESSION_INIT_DONE:
+ SANITIZE_SESSION_PKT(msg_hdr);
hfi_process_session_init_done(callback, device_id,
(struct hfi_msg_sys_session_init_done_packet *)
msg_hdr);
@@ -1151,44 +1183,53 @@
msg_hdr);
break;
case HFI_MSG_SYS_SESSION_END_DONE:
+ SANITIZE_SESSION_PKT(msg_hdr);
hfi_process_session_end_done(callback, device_id,
(struct hfi_msg_sys_session_end_done_packet *)
msg_hdr);
break;
case HFI_MSG_SESSION_LOAD_RESOURCES_DONE:
+ SANITIZE_SESSION_PKT(msg_hdr);
hfi_process_session_load_res_done(callback, device_id,
(struct hfi_msg_session_load_resources_done_packet *)
msg_hdr);
break;
case HFI_MSG_SESSION_START_DONE:
+ SANITIZE_SESSION_PKT(msg_hdr);
hfi_process_session_start_done(callback, device_id,
(struct hfi_msg_session_start_done_packet *)
msg_hdr);
break;
case HFI_MSG_SESSION_STOP_DONE:
+ SANITIZE_SESSION_PKT(msg_hdr);
hfi_process_session_stop_done(callback, device_id,
(struct hfi_msg_session_stop_done_packet *)
msg_hdr);
break;
case HFI_MSG_SESSION_EMPTY_BUFFER_DONE:
+ SANITIZE_SESSION_PKT(msg_hdr);
hfi_process_session_etb_done(callback, device_id,
(struct hfi_msg_session_empty_buffer_done_packet *)
msg_hdr);
break;
case HFI_MSG_SESSION_FILL_BUFFER_DONE:
+ SANITIZE_SESSION_PKT(msg_hdr);
hfi_process_session_ftb_done(callback, device_id, msg_hdr);
break;
case HFI_MSG_SESSION_FLUSH_DONE:
+ SANITIZE_SESSION_PKT(msg_hdr);
hfi_process_session_flush_done(callback, device_id,
(struct hfi_msg_session_flush_done_packet *)
msg_hdr);
break;
case HFI_MSG_SESSION_PROPERTY_INFO:
+ SANITIZE_SESSION_PKT(msg_hdr);
hfi_process_session_prop_info(callback, device_id,
(struct hfi_msg_session_property_info_packet *)
msg_hdr);
break;
case HFI_MSG_SESSION_RELEASE_RESOURCES_DONE:
+ SANITIZE_SESSION_PKT(msg_hdr);
hfi_process_session_rel_res_done(callback, device_id,
(struct hfi_msg_session_release_resources_done_packet *)
msg_hdr);
@@ -1199,18 +1240,21 @@
msg_hdr);
break;
case HFI_MSG_SESSION_GET_SEQUENCE_HEADER_DONE:
+ SANITIZE_SESSION_PKT(msg_hdr);
hfi_process_session_get_seq_hdr_done(
callback, device_id, (struct
hfi_msg_session_get_sequence_header_done_packet*)
msg_hdr);
break;
case HFI_MSG_SESSION_RELEASE_BUFFERS_DONE:
+ SANITIZE_SESSION_PKT(msg_hdr);
hfi_process_session_rel_buf_done(
callback, device_id, (struct
hfi_msg_session_release_buffers_done_packet*)
msg_hdr);
break;
case HFI_MSG_SYS_SESSION_ABORT_DONE:
+ SANITIZE_SESSION_PKT(msg_hdr);
hfi_process_session_abort_done(callback, device_id, (struct
hfi_msg_sys_session_abort_done_packet*) msg_hdr);
break;
@@ -1218,5 +1262,6 @@
dprintk(VIDC_DBG, "UNKNOWN_MSG_TYPE : %d", msg_hdr->packet);
break;
}
+#undef SANITIZE_SESSION_PKT
return rc;
}
diff --git a/drivers/media/platform/msm/vidc/q6_hfi.c b/drivers/media/platform/msm/vidc/q6_hfi.c
index 44c9613..7c99ec3 100644
--- a/drivers/media/platform/msm/vidc/q6_hfi.c
+++ b/drivers/media/platform/msm/vidc/q6_hfi.c
@@ -184,7 +184,8 @@
if (!rc)
hfi_process_msg_packet(device->callback,
device->device_id,
- (struct vidc_hal_msg_pkt_hdr *) packet);
+ (struct vidc_hal_msg_pkt_hdr *) packet,
+ &device->sess_head, &device->session_lock);
} while (!rc);
if (rc != -ENODATA)
@@ -483,6 +484,7 @@
}
INIT_LIST_HEAD(&dev->sess_head);
+ mutex_init(&dev->session_lock);
if (!dev->event_queue.buffer) {
rc = q6_init_event_queue(dev);
@@ -566,7 +568,9 @@
rc = -EBADE;
goto err_session_init;
}
+ mutex_lock(&dev->session_lock);
list_add_tail(&new_session->list, &dev->sess_head);
+ mutex_unlock(&dev->session_lock);
return new_session;
err_session_init:
@@ -629,7 +633,11 @@
sess_close = session;
dprintk(VIDC_DBG, "deleted the session: 0x%x",
sess_close->session_id);
+ mutex_lock(&((struct q6_hfi_device *)
+ sess_close->device)->session_lock);
list_del(&sess_close->list);
+ mutex_unlock(&((struct q6_hfi_device *)
+ sess_close->device)->session_lock);
kfree(sess_close);
return 0;
}
diff --git a/drivers/media/platform/msm/vidc/q6_hfi.h b/drivers/media/platform/msm/vidc/q6_hfi.h
index 67aed5a..5f48a51 100644
--- a/drivers/media/platform/msm/vidc/q6_hfi.h
+++ b/drivers/media/platform/msm/vidc/q6_hfi.h
@@ -52,6 +52,7 @@
struct q6_resources resources;
struct msm_vidc_platform_resources *res;
void *apr;
+ struct mutex session_lock;
};
struct q6_apr_cmd_sys_init_packet {
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 5416210..99c51bf 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -1045,6 +1045,7 @@
INIT_LIST_HEAD(&dev->sess_head);
mutex_init(&dev->read_lock);
mutex_init(&dev->write_lock);
+ mutex_init(&dev->session_lock);
venus_hfi_set_registers(dev);
if (!dev->hal_client) {
@@ -1484,7 +1485,10 @@
else if (session_type == 2)
new_session->is_decoder = 1;
new_session->device = dev;
+
+ mutex_lock(&dev->session_lock);
list_add_tail(&new_session->list, &dev->sess_head);
+ mutex_unlock(&dev->session_lock);
if (create_pkt_cmd_sys_session_init(&pkt, (u32)new_session,
session_type, codec_type)) {
@@ -1554,7 +1558,11 @@
sess_close = session;
dprintk(VIDC_DBG, "deleted the session: 0x%p",
sess_close);
+ mutex_lock(&((struct venus_hfi_device *)
+ sess_close->device)->session_lock);
list_del(&sess_close->list);
+ mutex_unlock(&((struct venus_hfi_device *)
+ sess_close->device)->session_lock);
kfree(sess_close);
return 0;
}
@@ -1985,7 +1993,8 @@
while (!venus_hfi_iface_msgq_read(device, packet)) {
rc = hfi_process_msg_packet(device->callback,
device->device_id,
- (struct vidc_hal_msg_pkt_hdr *) packet);
+ (struct vidc_hal_msg_pkt_hdr *) packet,
+ &device->sess_head, &device->session_lock);
if (rc == HFI_MSG_EVENT_NOTIFY)
venus_hfi_process_msg_event_notify(
device, (void *)packet);
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.h b/drivers/media/platform/msm/vidc/venus_hfi.h
index a59a053..44cdf31 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.h
+++ b/drivers/media/platform/msm/vidc/venus_hfi.h
@@ -188,6 +188,7 @@
struct mutex read_lock;
struct mutex write_lock;
struct mutex clock_lock;
+ struct mutex session_lock;
msm_vidc_callback callback;
struct vidc_mem_addr iface_q_table;
struct vidc_mem_addr qdss;
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi.h b/drivers/media/platform/msm/vidc/vidc_hfi.h
index 874738b..5059273 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi.h
@@ -832,6 +832,7 @@
};
u32 hfi_process_msg_packet(msm_vidc_callback callback,
- u32 device_id, struct vidc_hal_msg_pkt_hdr *msg_hdr);
+ u32 device_id, struct vidc_hal_msg_pkt_hdr *msg_hdr,
+ struct list_head *sessions, struct mutex *session_lock);
#endif