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>
Цей коміт міститься в:
@@ -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;
|
||||
}
|
||||
|
||||
|
Посилання в новій задачі
Заблокувати користувача