[PATCH] scsi: bnx2i: fix OOB write in login/text response padding
From: Henry Martin
Date: Tue Oct 27 2026 - 11:19:20 EST
bnx2i_process_login_resp() and bnx2i_process_text_resp() take the
payload length straight from the CQE field (login->data_length /
text->data_length, u32) written back by the adapter, without any bounds
check:
pld_len = login->data_length;
bnx2i_conn->gen_pdu.resp_wr_ptr =
bnx2i_conn->gen_pdu.resp_buf + pld_len;
pad_len = 0;
if (pld_len & 0x3)
pad_len = 4 - (pld_len % 4);
if (pad_len) {
int i = 0;
for (i = 0; i < pad_len; i++) {
bnx2i_conn->gen_pdu.resp_wr_ptr[0] = 0;
bnx2i_conn->gen_pdu.resp_wr_ptr++;
}
}
resp_buf is an 8192-byte DMA buffer (ISCSI_DEF_MAX_RECV_SEG_LEN). A
CQE whose data_length exceeds the buffer makes resp_wr_ptr point past
its end, and the pad loop then writes 1-3 zero bytes out of bounds.
The data_length is also passed on to __iscsi_complete_pdu() as the
response buffer size, so a login response with a fabricated data_length
turns into an out-of-bounds read of the same buffer delivered to the
iscsi userspace daemon. The login response path is reachable before
authentication.
Clamp the payload length to the response buffer size before computing
the write pointer and pad bytes, in both the login and text response
handlers.
This issue was discovered by Tencent CodeBuddy Security.
Fixes: cf4e6363859d ("[SCSI] bnx2i: Add bnx2i iSCSI driver.")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Henry Martin <bsdhenrymartin@xxxxxxxxx>
---
drivers/scsi/bnx2i/bnx2i_hwi.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c
index d24cc2c795d61..735cfdb28289b 100644
--- a/drivers/scsi/bnx2i/bnx2i_hwi.c
+++ b/drivers/scsi/bnx2i/bnx2i_hwi.c
@@ -1466,6 +1466,8 @@ static int bnx2i_process_login_resp(struct iscsi_session *session,
resp_hdr->status_class = login->status_class;
resp_hdr->status_detail = login->status_detail;
pld_len = login->data_length;
+ if (pld_len > bnx2i_conn->gen_pdu.resp_buf_size)
+ pld_len = bnx2i_conn->gen_pdu.resp_buf_size;
bnx2i_conn->gen_pdu.resp_wr_ptr =
bnx2i_conn->gen_pdu.resp_buf + pld_len;
@@ -1528,6 +1530,8 @@ static int bnx2i_process_text_resp(struct iscsi_session *session,
resp_hdr->exp_cmdsn = cpu_to_be32(text->exp_cmd_sn);
resp_hdr->max_cmdsn = cpu_to_be32(text->max_cmd_sn);
pld_len = text->data_length;
+ if (pld_len > bnx2i_conn->gen_pdu.resp_buf_size)
+ pld_len = bnx2i_conn->gen_pdu.resp_buf_size;
bnx2i_conn->gen_pdu.resp_wr_ptr = bnx2i_conn->gen_pdu.resp_buf +
pld_len;
pad_len = 0;
--
2.43.7