Re: [PATCH v3 21/57] scsi: bnx2i: Enable lock context analysis
[email protected] Thu, 30 Jul 2026 23:29:41 +0000
| Newsgroups | org.kernel.vger.linux-scsi |
|---|---|
| Message-ID | <[email protected]> |
Thank you for your contribution! Sashiko AI review found 3 potential issue(= s) to consider: Pre-existing issues: - [High] bnx2i_cleanup_task() calls wait_for_completion_timeout() while lib= iscsi holds session->frwd_lock, causing a scheduling while atomic bug. - [High] Unbounded copy in bnx2i_process_reject_mesg allows a malicious iSC= SI target to cause a kernel heap buffer overflow. - [High] Missing bounds check in bnx2i_process_login_resp and bnx2i_process= _text_resp leads to out-of-bounds writes of padding zeros. -- --- Patch [21]: [PATCH v3 21/57] scsi: bnx2i: Enable lock context analysis = --- commit ba1d4ba847bd9f8639c38b0ed041d30d68619de6 Author: Bart Van Assche <[email protected]> scsi: bnx2i: Enable lock context analysis Document locking requirements with __must_hold(). Use __assume_ctx_lock() to inform the compiler about aliases for synchronization objects. > diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hw= i.c > index 4fb68ec8e9b08..5d927880d2971 100644 > --- a/drivers/scsi/bnx2i/bnx2i_hwi.c > +++ b/drivers/scsi/bnx2i/bnx2i_hwi.c [ ... ] > @@ -1443,6 +1444,7 @@ static int bnx2i_process_login_resp(struct iscsi_se= ssion *session, > =20 > login =3D (struct bnx2i_login_response *) cqe; > spin_lock(&session->back_lock); > + __assume_ctx_lock(&conn->session->back_lock); > task =3D iscsi_itt_to_task(conn, > login->itt & ISCSI_LOGIN_RESPONSE_INDEX); > if (!task) [Severity: High] This isn't a bug introduced by this patch, but there appears to be a missing bounds check when processing login responses. In bnx2i_process_login_resp(), the payload length is added to resp_buf to compute resp_wr_ptr: bnx2i_conn->gen_pdu.resp_wr_ptr =3D bnx2i_conn->gen_pdu.resp_buf + pld_len; Could an untrusted iSCSI target send an oversized LOGIN response PDU where pld_len exceeds the 8192 byte capacity of gen_pdu.resp_buf? If so, could th= is loop write out-of-bounds padding zeros? if (pad_len) { int i =3D 0; for (i =3D 0; i < pad_len; i++) { bnx2i_conn->gen_pdu.resp_wr_ptr[0] =3D 0; bnx2i_conn->gen_pdu.resp_wr_ptr++; } } [ ... ] > @@ -1511,6 +1513,7 @@ static int bnx2i_process_text_resp(struct iscsi_ses= sion *session, > =20 > text =3D (struct bnx2i_text_response *) cqe; > spin_lock(&session->back_lock); > + __assume_ctx_lock(&conn->session->back_lock); > task =3D iscsi_itt_to_task(conn, text->itt & ISCSI_LOGIN_RESPONSE_INDEX= ); > if (!task) > goto done; [Severity: High] This is a pre-existing issue, but similar to the login response processing, there seems to be a missing bounds check here in bnx2i_process_text_resp(). If the payload length exceeds the buffer size, could the padding logic write past the buffer? bnx2i_conn->gen_pdu.resp_wr_ptr =3D bnx2i_conn->gen_pdu.resp_buf + pld_len; [ ... ] if (pad_len) { int i =3D 0; for (i =3D 0; i < pad_len; i++) { bnx2i_conn->gen_pdu.resp_wr_ptr[0] =3D 0; bnx2i_conn->gen_pdu.resp_wr_ptr++; } } [ ... ] > @@ -1803,6 +1810,7 @@ static void bnx2i_process_reject_mesg(struct iscsi_= session *session, > bnx2i_unsol_pdu_adjust_rq(bnx2i_conn); > =20 > spin_lock(&session->back_lock); > + __assume_ctx_lock(&conn->session->back_lock); > hdr =3D (struct iscsi_reject *) &bnx2i_conn->gen_pdu.resp_hdr; > memset(hdr, 0, sizeof(struct iscsi_hdr)); > hdr->opcode =3D reject->op_code; [Severity: High] This is a pre-existing issue, but is there a risk of a kernel heap buffer overflow in bnx2i_process_reject_mesg()? When receiving an iSCSI REJECT message, the CQE's data_length is passed directly to bnx2i_get_rq_buf(): if (reject->data_length) { bnx2i_get_rq_buf(bnx2i_conn, conn->data, reject->data_length); bnx2i_put_rq_buf(bnx2i_conn, 1); } In bnx2i_get_rq_buf(), this executes a memcpy into the statically sized conn->data buffer: memcpy(ptr, (u8 *) bnx2i_conn->ep->qp.rq_cons_qe, len); If an untrusted iSCSI target sends an oversized REJECT PDU, will this write past the bounds of the 8192 byte buffer? > diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_= iscsi.c > index 6c80e5b514fda..c868eada72c3e 100644 > --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c > +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c > @@ -1154,6 +1154,7 @@ static void bnx2i_cpy_scsi_cdb(struct scsi_cmnd *sc= , struct bnx2i_cmd *cmd) > } > =20 > static void bnx2i_cleanup_task(struct iscsi_task *task) > + __must_hold(&task->conn->session->back_lock) > { > struct iscsi_conn *conn =3D task->conn; > struct bnx2i_conn *bnx2i_conn =3D conn->dd_data; [Severity: High] This isn't a bug introduced by this patch, but does bnx2i_cleanup_task() sl= eep while atomic? During error handling, such as in iscsi_conn_stop() or iscsi_eh_device_rese= t(), libiscsi acquires the session->frwd_lock and calls fail_scsi_tasks(). If fail_scsi_tasks() drops the task reference count to 0 via __iscsi_put_task(), it synchronously invokes iscsi_free_task(), which calls bnx2i_cleanup_task(). While bnx2i_cleanup_task() drops the back_lock, the implicitly held frwd_lo= ck remains locked when it waits for the completion: if (task->state =3D=3D ISCSI_TASK_ABRT_TMF) { bnx2i_send_cmd_cleanup_req(hba, task->dd_data); spin_unlock_bh(&conn->session->back_lock); wait_for_completion_timeout(&bnx2i_conn->cmd_cleanup_cmpl, msecs_to_jiffies(ISCSI_CMD_CLEANUP_TIMEOUT)); spin_lock_bh(&conn->session->back_lock); } Could this cause a scheduling while atomic bug when wait_for_completion_tim= eout is called with frwd_lock still held? --=20 Sashiko AI review =C2=B7 https://sashiko.dev/#/patchset/cover.1785451174.gi= [email protected]?part=3D21