disp: msm: dsi: fix kasan out of bound in dsi reception
Fix out of bounds access that occurs when reading dsi commands with custom non 4 bytes aligned payload. When misaligned, the code is overfetching data due to 32 bits reading constraint. This creates an offset in receiving buffer. Using a local copy buffer large enough to hold the extra bytes fixes the issue. Change-Id: Ia0ee791d2e87639edd58191cfd5cb6f8f825f8c8 Signed-off-by: Amine Najahi <anajahi@codeaurora.org> Signed-off-by: Ritesh Kumar <riteshk@codeaurora.org>
This commit is contained in:
@@ -1758,9 +1758,11 @@ static int dsi_message_rx(struct dsi_ctrl *dsi_ctrl, struct dsi_cmd_desc *cmd_de
|
|||||||
bool short_resp = false;
|
bool short_resp = false;
|
||||||
bool read_done = false;
|
bool read_done = false;
|
||||||
u32 dlen, diff, rlen;
|
u32 dlen, diff, rlen;
|
||||||
unsigned char *buff;
|
unsigned char *buff = NULL;
|
||||||
char cmd;
|
char cmd;
|
||||||
const struct mipi_dsi_msg *msg;
|
const struct mipi_dsi_msg *msg;
|
||||||
|
u32 buffer_sz = 0, header_offset = 0;
|
||||||
|
u8 *head = NULL;
|
||||||
|
|
||||||
if (!cmd_desc) {
|
if (!cmd_desc) {
|
||||||
DSI_CTRL_ERR(dsi_ctrl, "Invalid command\n");
|
DSI_CTRL_ERR(dsi_ctrl, "Invalid command\n");
|
||||||
@@ -1774,6 +1776,11 @@ static int dsi_message_rx(struct dsi_ctrl *dsi_ctrl, struct dsi_cmd_desc *cmd_de
|
|||||||
short_resp = true;
|
short_resp = true;
|
||||||
rd_pkt_size = msg->rx_len;
|
rd_pkt_size = msg->rx_len;
|
||||||
total_read_len = 4;
|
total_read_len = 4;
|
||||||
|
/*
|
||||||
|
* buffer size: header + data
|
||||||
|
* No 32 bits alignment issue, thus offset is 0
|
||||||
|
*/
|
||||||
|
buffer_sz = 4;
|
||||||
} else {
|
} else {
|
||||||
short_resp = false;
|
short_resp = false;
|
||||||
current_read_len = 10;
|
current_read_len = 10;
|
||||||
@@ -1783,8 +1790,22 @@ static int dsi_message_rx(struct dsi_ctrl *dsi_ctrl, struct dsi_cmd_desc *cmd_de
|
|||||||
rd_pkt_size = current_read_len;
|
rd_pkt_size = current_read_len;
|
||||||
|
|
||||||
total_read_len = current_read_len + 6;
|
total_read_len = current_read_len + 6;
|
||||||
|
/*
|
||||||
|
* buffer size: header + data + footer, rounded up to 4 bytes.
|
||||||
|
* Out of bound can occur if rx_len is not aligned to size 4.
|
||||||
|
*/
|
||||||
|
buffer_sz = 4 + msg->rx_len + 2;
|
||||||
|
buffer_sz = ALIGN(buffer_sz, 4);
|
||||||
|
if (buffer_sz < 16)
|
||||||
|
buffer_sz = 16;
|
||||||
}
|
}
|
||||||
buff = msg->rx_buf;
|
|
||||||
|
buff = kzalloc(buffer_sz, GFP_KERNEL);
|
||||||
|
if (!buff) {
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
head = buff;
|
||||||
|
|
||||||
while (!read_done) {
|
while (!read_done) {
|
||||||
rc = dsi_set_max_return_size(dsi_ctrl, cmd_desc, rd_pkt_size);
|
rc = dsi_set_max_return_size(dsi_ctrl, cmd_desc, rd_pkt_size);
|
||||||
@@ -1846,13 +1867,15 @@ static int dsi_message_rx(struct dsi_ctrl *dsi_ctrl, struct dsi_cmd_desc *cmd_de
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buff = head;
|
||||||
|
|
||||||
if (hw_read_cnt < 16 && !short_resp)
|
if (hw_read_cnt < 16 && !short_resp)
|
||||||
buff = msg->rx_buf + (16 - hw_read_cnt);
|
header_offset = (16 - hw_read_cnt);
|
||||||
else
|
else
|
||||||
buff = msg->rx_buf;
|
header_offset = 0;
|
||||||
|
|
||||||
/* parse the data read from panel */
|
/* parse the data read from panel */
|
||||||
cmd = buff[0];
|
cmd = buff[header_offset];
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
|
case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
|
||||||
DSI_CTRL_ERR(dsi_ctrl, "Rx ACK_ERROR 0x%x\n", cmd);
|
DSI_CTRL_ERR(dsi_ctrl, "Rx ACK_ERROR 0x%x\n", cmd);
|
||||||
@@ -1860,15 +1883,15 @@ static int dsi_message_rx(struct dsi_ctrl *dsi_ctrl, struct dsi_cmd_desc *cmd_de
|
|||||||
break;
|
break;
|
||||||
case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:
|
case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:
|
||||||
case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
|
case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
|
||||||
rc = dsi_parse_short_read1_resp(msg, buff);
|
rc = dsi_parse_short_read1_resp(msg, &buff[header_offset]);
|
||||||
break;
|
break;
|
||||||
case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE:
|
case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE:
|
||||||
case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:
|
case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:
|
||||||
rc = dsi_parse_short_read2_resp(msg, buff);
|
rc = dsi_parse_short_read2_resp(msg, &buff[header_offset]);
|
||||||
break;
|
break;
|
||||||
case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE:
|
case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE:
|
||||||
case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE:
|
case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE:
|
||||||
rc = dsi_parse_long_read_resp(msg, buff);
|
rc = dsi_parse_long_read_resp(msg, &buff[header_offset]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DSI_CTRL_WARN(dsi_ctrl, "Invalid response: 0x%x\n", cmd);
|
DSI_CTRL_WARN(dsi_ctrl, "Invalid response: 0x%x\n", cmd);
|
||||||
@@ -1876,6 +1899,7 @@ static int dsi_message_rx(struct dsi_ctrl *dsi_ctrl, struct dsi_cmd_desc *cmd_de
|
|||||||
}
|
}
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
kfree(buff);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user