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>
Цей коміт міститься в:
Ritesh Kumar
2021-06-09 12:49:13 +05:30
джерело eacfafbaed
коміт d52b019c50

Переглянути файл

@@ -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 read_done = false;
u32 dlen, diff, rlen;
unsigned char *buff;
unsigned char *buff = NULL;
char cmd;
const struct mipi_dsi_msg *msg;
u32 buffer_sz = 0, header_offset = 0;
u8 *head = NULL;
if (!cmd_desc) {
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;
rd_pkt_size = msg->rx_len;
total_read_len = 4;
/*
* buffer size: header + data
* No 32 bits alignment issue, thus offset is 0
*/
buffer_sz = 4;
} else {
short_resp = false;
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;
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) {
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)
buff = msg->rx_buf + (16 - hw_read_cnt);
header_offset = (16 - hw_read_cnt);
else
buff = msg->rx_buf;
header_offset = 0;
/* parse the data read from panel */
cmd = buff[0];
cmd = buff[header_offset];
switch (cmd) {
case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
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;
case MIPI_DSI_RX_GENERIC_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;
case MIPI_DSI_RX_GENERIC_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;
case MIPI_DSI_RX_GENERIC_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;
default:
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:
kfree(buff);
return rc;
}