[PATCH 2/2] scsi: bnx2i: bound the login and text response payload length

From: Yehyeong Lee

Date: Mon Oct 19 2026 - 03:50:39 EST


bnx2i_process_login_resp() and bnx2i_process_text_resp() take the payload
length out of the CQE and use it to place the write pointer inside the
buffer the chip DMA'd the payload into:

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++;
}
}

data_length is a u32 and nothing bounds it, so the padding bytes are
written wherever the length the chip reported puts the pointer. resp_buf
is an ISCSI_DEF_MAX_RECV_SEG_LEN coherent DMA allocation, two pages with
nothing to spare, and pld_len is an int, so a large enough length puts the
pointer in front of the buffer instead of past it. The length reaches
__iscsi_complete_pdu() afterwards as resp_wr_ptr - resp_buf.

The size is already on hand in gen_pdu.resp_buf_size, which so far has only
been handed to the chip in the login and text work queue entries. Cap the
length with it. The padding stays in bounds because resp_buf_size is a
multiple of four, so a capped length that needs padding is rounded up to at
most resp_buf_size itself.

Unlike the receive queue path in the previous patch this one is not covered
by the KUnit harness, since reaching these handlers needs a task and a
connection; the bound here is the size of the allocation the chip was
pointed at.

Fixes: cf4e6363859d ("[SCSI] bnx2i: Add bnx2i iSCSI driver.")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Yehyeong Lee <yhlee@xxxxxxxxxxxxxxxxxx>
---
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c
--- a/drivers/scsi/bnx2i/bnx2i_hwi.c
+++ b/drivers/scsi/bnx2i/bnx2i_hwi.c
@@ -1461,7 +1461,10 @@
resp_hdr->active_version = login->version_active;
resp_hdr->hlength = 0;

- hton24(resp_hdr->dlength, login->data_length);
+ /* The chip can only have filled the buffer it was given. */
+ pld_len = min_t(u32, login->data_length,
+ bnx2i_conn->gen_pdu.resp_buf_size);
+ hton24(resp_hdr->dlength, pld_len);
memcpy(resp_hdr->isid, &login->isid_lo, 6);
resp_hdr->tsih = cpu_to_be16(login->tsih);
resp_hdr->itt = task->hdr->itt;
@@ -1470,7 +1473,6 @@
resp_hdr->max_cmdsn = cpu_to_be32(login->max_cmd_sn);
resp_hdr->status_class = login->status_class;
resp_hdr->status_detail = login->status_detail;
- pld_len = login->data_length;
bnx2i_conn->gen_pdu.resp_wr_ptr =
bnx2i_conn->gen_pdu.resp_buf + pld_len;

@@ -1526,13 +1528,15 @@
resp_hdr->flags = text->response_flags;
resp_hdr->hlength = 0;

- hton24(resp_hdr->dlength, text->data_length);
+ /* The chip can only have filled the buffer it was given. */
+ pld_len = min_t(u32, text->data_length,
+ bnx2i_conn->gen_pdu.resp_buf_size);
+ hton24(resp_hdr->dlength, pld_len);
resp_hdr->itt = task->hdr->itt;
resp_hdr->ttt = cpu_to_be32(text->ttt);
resp_hdr->statsn = task->hdr->exp_statsn;
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;
bnx2i_conn->gen_pdu.resp_wr_ptr = bnx2i_conn->gen_pdu.resp_buf +
pld_len;
pad_len = 0;