aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2019-04-15 22:29:18 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2019-04-15 22:29:19 -0700
commita12886d31b7e220d83c4cebaf07fafa0a40835a8 (patch)
tree39b3bb71aa083df888a58cb30040889760785443
parentdfe4fc94d39b018698d8fb8aaf86507ca42ae141 (diff)
parent7aaa4a64787a5e6ebee4f9ba56d0bce99a35f574 (diff)
Merge "msm: vidc: Ensure validity of shared Q indices" into LE.UM.2.3.2.r1.20LE.UM.2.3.2-06400-SDX24
-rw-r--r--drivers/media/platform/msm/vidc/venus_hfi.c68
1 files changed, 44 insertions, 24 deletions
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index c026fb4e88df..811414af41b5 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -327,7 +327,7 @@ static int __write_queue(struct vidc_iface_q_info *qinfo, u8 *packet,
{
struct hfi_queue_header *queue;
u32 packet_size_in_words, new_write_idx;
- u32 empty_space, read_idx;
+ u32 empty_space, read_idx, write_idx;
u32 *write_ptr;
if (!qinfo || !packet) {
@@ -350,16 +350,18 @@ static int __write_queue(struct vidc_iface_q_info *qinfo, u8 *packet,
}
packet_size_in_words = (*(u32 *)packet) >> 2;
- if (!packet_size_in_words) {
- dprintk(VIDC_ERR, "Zero packet size\n");
+ if (!packet_size_in_words || packet_size_in_words >
+ qinfo->q_array.mem_size>>2) {
+ dprintk(VIDC_ERR, "Invalid packet size\n");
return -ENODATA;
}
read_idx = queue->qhdr_read_idx;
+ write_idx = queue->qhdr_write_idx;
- empty_space = (queue->qhdr_write_idx >= read_idx) ?
- (queue->qhdr_q_size - (queue->qhdr_write_idx - read_idx)) :
- (read_idx - queue->qhdr_write_idx);
+ empty_space = (write_idx >= read_idx) ?
+ ((qinfo->q_array.mem_size>>2) - (write_idx - read_idx)) :
+ (read_idx - write_idx);
if (empty_space <= packet_size_in_words) {
queue->qhdr_tx_req = 1;
dprintk(VIDC_ERR, "Insufficient size (%d) to write (%d)\n",
@@ -369,13 +371,20 @@ static int __write_queue(struct vidc_iface_q_info *qinfo, u8 *packet,
queue->qhdr_tx_req = 0;
- new_write_idx = (queue->qhdr_write_idx + packet_size_in_words);
+ new_write_idx = write_idx + packet_size_in_words;
write_ptr = (u32 *)((qinfo->q_array.align_virtual_addr) +
- (queue->qhdr_write_idx << 2));
- if (new_write_idx < queue->qhdr_q_size) {
+ (write_idx << 2));
+ if (write_ptr < (u32 *)qinfo->q_array.align_virtual_addr ||
+ write_ptr > (u32 *)(qinfo->q_array.align_virtual_addr +
+ qinfo->q_array.mem_size)) {
+ dprintk(VIDC_ERR, "Invalid write index");
+ return -ENODATA;
+ }
+
+ if (new_write_idx < (qinfo->q_array.mem_size >> 2)) {
memcpy(write_ptr, packet, packet_size_in_words << 2);
} else {
- new_write_idx -= queue->qhdr_q_size;
+ new_write_idx -= qinfo->q_array.mem_size >> 2;
memcpy(write_ptr, packet, (packet_size_in_words -
new_write_idx) << 2);
memcpy((void *)qinfo->q_array.align_virtual_addr,
@@ -471,7 +480,8 @@ static int __read_queue(struct vidc_iface_q_info *qinfo, u8 *packet,
u32 packet_size_in_words, new_read_idx;
u32 *read_ptr;
u32 receive_request = 0;
- int rc = 0;
+ u32 read_idx, write_idx;
+ int rc = 0;
if (!qinfo || !packet || !pb_tx_req_is_set) {
dprintk(VIDC_ERR, "Invalid Params\n");
@@ -504,7 +514,10 @@ static int __read_queue(struct vidc_iface_q_info *qinfo, u8 *packet,
if (queue->qhdr_type & HFI_Q_ID_CTRL_TO_HOST_MSG_Q)
receive_request = 1;
- if (queue->qhdr_read_idx == queue->qhdr_write_idx) {
+ read_idx = queue->qhdr_read_idx;
+ write_idx = queue->qhdr_write_idx;
+
+ if (read_idx == write_idx) {
queue->qhdr_rx_req = receive_request;
/*
* mb() to ensure qhdr is updated in main memory
@@ -521,21 +534,28 @@ static int __read_queue(struct vidc_iface_q_info *qinfo, u8 *packet,
}
read_ptr = (u32 *)((qinfo->q_array.align_virtual_addr) +
- (queue->qhdr_read_idx << 2));
+ (read_idx << 2));
+ if (read_ptr < (u32 *)qinfo->q_array.align_virtual_addr ||
+ read_ptr > (u32 *)(qinfo->q_array.align_virtual_addr +
+ qinfo->q_array.mem_size - sizeof(*read_ptr))) {
+ dprintk(VIDC_ERR, "Invalid read index\n");
+ return -ENODATA;
+ }
+
packet_size_in_words = (*read_ptr) >> 2;
if (!packet_size_in_words) {
dprintk(VIDC_ERR, "Zero packet size\n");
return -ENODATA;
}
- new_read_idx = queue->qhdr_read_idx + packet_size_in_words;
- if (((packet_size_in_words << 2) <= VIDC_IFACEQ_VAR_HUGE_PKT_SIZE)
- && queue->qhdr_read_idx <= queue->qhdr_q_size) {
- if (new_read_idx < queue->qhdr_q_size) {
+ new_read_idx = read_idx + packet_size_in_words;
+ if (((packet_size_in_words << 2) <= VIDC_IFACEQ_VAR_HUGE_PKT_SIZE) &&
+ read_idx <= (qinfo->q_array.mem_size >> 2)) {
+ if (new_read_idx < (qinfo->q_array.mem_size >> 2)) {
memcpy(packet, read_ptr,
packet_size_in_words << 2);
} else {
- new_read_idx -= queue->qhdr_q_size;
+ new_read_idx -= (qinfo->q_array.mem_size >> 2);
memcpy(packet, read_ptr,
(packet_size_in_words - new_read_idx) << 2);
memcpy(packet + ((packet_size_in_words -
@@ -546,18 +566,18 @@ static int __read_queue(struct vidc_iface_q_info *qinfo, u8 *packet,
} else {
dprintk(VIDC_WARN,
"BAD packet received, read_idx: %#x, pkt_size: %d\n",
- queue->qhdr_read_idx, packet_size_in_words << 2);
+ read_idx, packet_size_in_words << 2);
dprintk(VIDC_WARN, "Dropping this packet\n");
- new_read_idx = queue->qhdr_write_idx;
+ new_read_idx = write_idx;
rc = -ENODATA;
}
- queue->qhdr_read_idx = new_read_idx;
-
- if (queue->qhdr_read_idx != queue->qhdr_write_idx)
+ if (new_read_idx != write_idx)
queue->qhdr_rx_req = 0;
else
queue->qhdr_rx_req = receive_request;
+
+ queue->qhdr_read_idx = new_read_idx;
/*
* mb() to ensure qhdr is updated in main memory
* so that venus reads the updated header values