msm: vidc: Ensure validity of shared Q indices
Video driver and firmware communicates over shared queue. The queue header has the indices which synchronizes the read and write between the driver and firmware modules. This change ensures that the indices are within the valid range before accessing them. CRs-fixed: 2345481 Change-Id: I8da6bb4218a5b8ec0e2e2c7b87f6cc9eec21bd16 Signed-off-by: Vikash Garodia <vgarodia@codeaurora.org> Signed-off-by: Paras Nagda <pnagda@codeaurora.org> Signed-off-by: Vasantha Balla <vballa@codeaurora.org>
This commit is contained in:
parent
38f4fba64d
commit
e18e27735c
1 changed files with 44 additions and 24 deletions
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2012-2017, 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
|
||||
|
@ -328,7 +328,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) {
|
||||
|
@ -351,16 +351,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",
|
||||
|
@ -370,13 +372,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,
|
||||
|
@ -468,7 +477,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");
|
||||
|
@ -499,7 +509,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
|
||||
|
@ -516,21 +529,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 -
|
||||
|
@ -541,15 +561,13 @@ 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;
|
||||
|
@ -559,6 +577,8 @@ static int __read_queue(struct vidc_iface_q_info *qinfo, u8 *packet,
|
|||
*/
|
||||
mb();
|
||||
|
||||
queue->qhdr_read_idx = new_read_idx;
|
||||
|
||||
*pb_tx_req_is_set = (1 == queue->qhdr_tx_req) ? 1 : 0;
|
||||
|
||||
if (msm_vidc_debug & VIDC_PKT) {
|
||||
|
|
Loading…
Add table
Reference in a new issue