mdss: mhl3: add null pointer and safety checks to mhl
Add NULL checks and array bounds checks to ensure that no dereferencing of invalid data occurs in the MHL driver. Change-Id: I855412b4603cbe416d901be88a24a28dc6770d2c Signed-off-by: Casey Piper <cpiper@codeaurora.org>
This commit is contained in:
parent
e509f3b8cb
commit
cff7fea574
5 changed files with 34 additions and 15 deletions
|
@ -331,7 +331,7 @@ ssize_t send_scratch_pad(struct device *dev, struct device_attribute *attr,
|
||||||
* Parse the input string and extract the scratch pad register selection
|
* Parse the input string and extract the scratch pad register selection
|
||||||
* parameters
|
* parameters
|
||||||
*/
|
*/
|
||||||
str = strstr(pinput, "offset=");
|
str = strnstr(pinput, "offset=", count);
|
||||||
if (str != NULL) {
|
if (str != NULL) {
|
||||||
str += 7;
|
str += 7;
|
||||||
status = si_strtoul(&str, 0, &offset);
|
status = si_strtoul(&str, 0, &offset);
|
||||||
|
@ -3067,7 +3067,7 @@ void mhl_event_notify(struct mhl_dev_context *dev_context, u32 event,
|
||||||
"MHLEVENT=SPAD_CHG length=0x%02x data=", length);
|
"MHLEVENT=SPAD_CHG length=0x%02x data=", length);
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
while (idx < MAX_EVENT_STRING_LEN) {
|
while (buf && idx < MAX_EVENT_STRING_LEN) {
|
||||||
if (count >= length)
|
if (count >= length)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -484,12 +484,14 @@ void si_mhl_tx_push_block_transactions(struct mhl_dev_context *dev_context)
|
||||||
req->payload->hdr_and_burst_id.tport_hdr.length_remaining =
|
req->payload->hdr_and_burst_id.tport_hdr.length_remaining =
|
||||||
req->sub_payload_size;
|
req->sub_payload_size;
|
||||||
req->count = payload_size;
|
req->count = payload_size;
|
||||||
/* The driver layer will fill in the rx_unload_ack field */
|
if (req->count < EMSC_PAYLOAD_LEN) {
|
||||||
mhl_tx_drv_send_block((struct drv_hw_context *)
|
/* The driver layer will fill */
|
||||||
(&dev_context->drv_context), req);
|
/* in the rx_unload_ack field */
|
||||||
/* return request to free list */
|
mhl_tx_drv_send_block((struct drv_hw_context *)
|
||||||
return_block_queue_entry(dev_context, req);
|
(&dev_context->drv_context), req);
|
||||||
|
/* return request to free list */
|
||||||
|
return_block_queue_entry(dev_context, req);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (NULL == dev_context->block_protocol.marshalling_req) {
|
if (NULL == dev_context->block_protocol.marshalling_req) {
|
||||||
/* now start a new marshalling request */
|
/* now start a new marshalling request */
|
||||||
|
@ -1337,7 +1339,7 @@ void si_mhl_tx_drive_states(struct mhl_dev_context *dev_context)
|
||||||
next_req;
|
next_req;
|
||||||
}
|
}
|
||||||
|
|
||||||
} while (ret_val);
|
} while (ret_val && req);
|
||||||
break;
|
break;
|
||||||
case MHL_MSC_MSG:
|
case MHL_MSC_MSG:
|
||||||
if (MHL_MSC_MSG_RAP == req->msg_data[0]) {
|
if (MHL_MSC_MSG_RAP == req->msg_data[0]) {
|
||||||
|
|
|
@ -858,6 +858,11 @@ drain_rfifo:
|
||||||
MHL_TX_DBG_ERR("Draining %d bytes from RFIFO\n", data_len);
|
MHL_TX_DBG_ERR("Draining %d bytes from RFIFO\n", data_len);
|
||||||
|
|
||||||
pbit_bucket = kmalloc(data_len, GFP_KERNEL);
|
pbit_bucket = kmalloc(data_len, GFP_KERNEL);
|
||||||
|
if (!pbit_bucket) {
|
||||||
|
MHL_TX_DBG_ERR("Failed to allocate %d bytes for pbit bucket\n",
|
||||||
|
data_len);
|
||||||
|
goto done_emsc;
|
||||||
|
}
|
||||||
if (use_spi) {
|
if (use_spi) {
|
||||||
mhl_tx_read_spi_emsc(hw_context, data_len, pbit_bucket);
|
mhl_tx_read_spi_emsc(hw_context, data_len, pbit_bucket);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1831,8 +1836,10 @@ void mhl_tx_drv_send_block(struct drv_hw_context *hw_context,
|
||||||
if (use_spi) {
|
if (use_spi) {
|
||||||
mhl_tx_write_block_spi_emsc(hw_context, req);
|
mhl_tx_write_block_spi_emsc(hw_context, req);
|
||||||
} else {
|
} else {
|
||||||
mhl_tx_write_reg_block(hw_context, REG_EMSC_XMIT_WRITE_PORT,
|
if (req->count < EMSC_PAYLOAD_LEN)
|
||||||
req->count, &req->payload->as_bytes[0]);
|
mhl_tx_write_reg_block(hw_context,
|
||||||
|
REG_EMSC_XMIT_WRITE_PORT, req->count,
|
||||||
|
&req->payload->as_bytes[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2258,6 +2265,10 @@ uint8_t si_mhl_tx_drv_send_cbus_command(struct drv_hw_context *hw_context,
|
||||||
req->burst_offset, req->length);
|
req->burst_offset, req->length);
|
||||||
hw_context->hawb_write_pending = true;
|
hw_context->hawb_write_pending = true;
|
||||||
enable_gen2_write_burst_xmit(hw_context);
|
enable_gen2_write_burst_xmit(hw_context);
|
||||||
|
if (req->length > CBUS_REQ_MSG_DATA_LEN) {
|
||||||
|
ret_val = -EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
mhl_tx_write_reg_block(hw_context,
|
mhl_tx_write_reg_block(hw_context,
|
||||||
REG_MDT_XMIT_WRITE_PORT,
|
REG_MDT_XMIT_WRITE_PORT,
|
||||||
req->length, req->msg_data);
|
req->length, req->msg_data);
|
||||||
|
|
|
@ -1923,7 +1923,8 @@ static void si_mhl_tx_prune_edid(struct edid_3d_data_t *mhl_edid_3d_data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mhl_edid_3d_data->parse_data.p_three_d) {
|
if (mhl_edid_3d_data->parse_data.p_three_d &&
|
||||||
|
mhl_edid_3d_data->parse_data.p_HDMI_vsdb) {
|
||||||
uint8_t num_3D_structure_bytes_pruned = 0;
|
uint8_t num_3D_structure_bytes_pruned = 0;
|
||||||
union {
|
union {
|
||||||
union _3D_structure_and_detail_entry_u *p_3D;
|
union _3D_structure_and_detail_entry_u *p_3D;
|
||||||
|
@ -4288,7 +4289,10 @@ int si_mhl_tx_get_num_cea_861_extensions(void *context, uint8_t block_number)
|
||||||
uint8_t limit_blocks = sizeof(mhl_edid_3d_data->EDID_block_data) /
|
uint8_t limit_blocks = sizeof(mhl_edid_3d_data->EDID_block_data) /
|
||||||
EDID_BLOCK_SIZE;
|
EDID_BLOCK_SIZE;
|
||||||
|
|
||||||
uint8_t *pb_data =
|
uint8_t *pb_data;
|
||||||
|
if (block_number > NUM_VIDEO_DATA_BLOCKS_LIMIT)
|
||||||
|
return ne_BAD_DATA;
|
||||||
|
pb_data =
|
||||||
&mhl_edid_3d_data->EDID_block_data[EDID_BLOCK_SIZE * block_number];
|
&mhl_edid_3d_data->EDID_block_data[EDID_BLOCK_SIZE * block_number];
|
||||||
|
|
||||||
MHL_TX_EDID_INFO("block number:%d pb_data:%x\n", block_number, pb_data);
|
MHL_TX_EDID_INFO("block number:%d pb_data:%x\n", block_number, pb_data);
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
#if !defined(SI_MHL_TX_DRV_API_H)
|
#if !defined(SI_MHL_TX_DRV_API_H)
|
||||||
#define SI_MHL_TX_DRV_API_H
|
#define SI_MHL_TX_DRV_API_H
|
||||||
|
|
||||||
|
#define CBUS_REQ_MSG_DATA_LEN 16
|
||||||
|
#define EMSC_PAYLOAD_LEN 256
|
||||||
/*
|
/*
|
||||||
* Structure to hold command details from upper layer to CBUS module
|
* Structure to hold command details from upper layer to CBUS module
|
||||||
*/
|
*/
|
||||||
|
@ -34,7 +36,7 @@ struct cbus_req {
|
||||||
uint8_t reg_data;
|
uint8_t reg_data;
|
||||||
uint8_t burst_offset; /* register offset */
|
uint8_t burst_offset; /* register offset */
|
||||||
uint8_t length; /* Only applicable to write burst */
|
uint8_t length; /* Only applicable to write burst */
|
||||||
uint8_t msg_data[16]; /* scratch pad data area. */
|
uint8_t msg_data[CBUS_REQ_MSG_DATA_LEN]; /* scratch pad data area. */
|
||||||
const char *function;
|
const char *function;
|
||||||
int line;
|
int line;
|
||||||
int sequence;
|
int sequence;
|
||||||
|
@ -53,7 +55,7 @@ struct SI_PACK_THIS_STRUCT tport_hdr_and_burst_id_t {
|
||||||
};
|
};
|
||||||
union SI_PACK_THIS_STRUCT emsc_payload_t {
|
union SI_PACK_THIS_STRUCT emsc_payload_t {
|
||||||
struct SI_PACK_THIS_STRUCT tport_hdr_and_burst_id_t hdr_and_burst_id;
|
struct SI_PACK_THIS_STRUCT tport_hdr_and_burst_id_t hdr_and_burst_id;
|
||||||
uint8_t as_bytes[256];
|
uint8_t as_bytes[EMSC_PAYLOAD_LEN];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SI_PACK_THIS_STRUCT block_req {
|
struct SI_PACK_THIS_STRUCT block_req {
|
||||||
|
|
Loading…
Add table
Reference in a new issue