]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
scsi: libiscsi_tcp: Bound SCSI Response data segment to the connection buffer
authorHyeongJun An <sammiee5311@gmail.com>
Thu, 16 Jul 2026 06:58:48 +0000 (15:58 +0900)
committerMartin K. Petersen <martin.petersen@oracle.com>
Sun, 26 Jul 2026 19:31:33 +0000 (15:31 -0400)
iscsi_tcp_hdr_dissect() receives the data segment of several PDU types
into the fixed-size conn->data buffer, which is allocated for
ISCSI_DEF_MAX_RECV_SEG_LEN (8192) bytes.  For the LOGIN_RSP, TEXT_RSP,
REJECT and ASYNC_EVENT opcodes the dissect path already rejects a PDU
whose DataSegmentLength exceeds that buffer.

The SCSI Command Response (ISCSI_OP_SCSI_CMD_RSP) path also copies its
data segment (sense/response data) into conn->data via
iscsi_tcp_data_recv_prep(), but it does so without the same check.  The
only upstream bound on in.datalen is conn->max_recv_dlength, the
initiator's advertised MaxRecvDataSegmentLength, which is commonly
negotiated well above 8192 (open-iscsi defaults to 262144).  A target
that returns a SCSI Response with a DataSegmentLength between 8193 and
max_recv_dlength therefore overflows the 8192-byte conn->data buffer.

Once the same bound applies, ISCSI_OP_SCSI_CMD_RSP is handled exactly
like those responses: bound the data segment, receive it into conn->data
when present, and otherwise complete the PDU with no data.  Fold the
opcode into that case group rather than duplicating the check.

Fixes: a081c13e39b5 ("[SCSI] iscsi_tcp: split module into lib and lld")
Suggested-by: Chris Leech <cleech@redhat.com>
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: HyeongJun An <sammiee5311@gmail.com>
Acked-by: Chris Leech <cleech@redhat.com>
Link: https://patch.msgid.link/20260716065848.1653431-1-sammiee5311@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/libiscsi_tcp.c

index e90805ba868fbedac5567455767b3ac104a02044..7223bb18b04809489530668cbe93ff64eb266291 100644 (file)
@@ -752,13 +752,6 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
                rc = __iscsi_complete_pdu(conn, hdr, NULL, 0);
                spin_unlock(&conn->session->back_lock);
                break;
-       case ISCSI_OP_SCSI_CMD_RSP:
-               if (tcp_conn->in.datalen) {
-                       iscsi_tcp_data_recv_prep(tcp_conn);
-                       return 0;
-               }
-               rc = iscsi_complete_pdu(conn, hdr, NULL, 0);
-               break;
        case ISCSI_OP_R2T:
                if (ahslen) {
                        rc = ISCSI_ERR_AHSLEN;
@@ -766,6 +759,7 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
                }
                rc = iscsi_tcp_r2t_rsp(conn, hdr);
                break;
+       case ISCSI_OP_SCSI_CMD_RSP:
        case ISCSI_OP_LOGIN_RSP:
        case ISCSI_OP_TEXT_RSP:
        case ISCSI_OP_REJECT: