From: Cao Guanghui <[email protected]>
In iscsit_setup_scsi_cmd(), the Extended CDB AHS path allocates the CDB
buffer using only the iSCSI AHS-declared length. The buffer is then
handed to target_cmd_init_cdb(), which re-derives the CDB length from
the SCSI opcode via scsi_command_size(). For a VARIABLE_LENGTH_CMD
(0x7f) the size is cdb[7] + 8, where both cdb[0] and cdb[7] come
verbatim from the initiator-controlled hdr->cdb. The AHS-declared length
and the opcode-declared length are never cross-checked.
An initiator can thus advertise a minimal AHS (ahslength = 1, which
passes the !ahslength and ahslength > hlength*4 - 3 checks added by
commit 2f3835771dff ("scsi: target: iscsi: reject invalid size Extended
CDB AHS") while setting cdb[0]=0x7f and cdb[7]=252. This yields a
16-byte kmalloc but scsi_command_size() returns 260, so
target_cmd_init_cdb() reads 260 bytes from a 16-byte heap object, a heap
out-of-bounds read. The leaked bytes are later parsed as the CDB and can
be indirectly observed by the initiator through sense data and
responses.
commit 2f3835771dff ("scsi: target: iscsi: reject invalid size Extended
CDB AHS") fixed the zero-length ahslength overflows and the AHS-buffer
overread, but did not cover the orthogonal "allocation size vs.
opcode-declared size" path. Reject the command when the opcode-declared
CDB size exceeds the AHS-provided length, before the kmalloc.
Fixes: 8f1f7d297bce ("scsi: target: iscsi: Add support for extended CDB AHS")
Signed-off-by: Cao Guanghui <[email protected]>
---
drivers/target/iscsi/iscsi_target.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index 62ada3a52210..e3e9254df960 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -1124,6 +1124,19 @@ int iscsit_setup_scsi_cmd(struct iscsit_conn *conn, struct iscsit_cmd *cmd,
cdb_length = ahslength - 1 + ISCSI_CDB_SIZE;
+ /*
+ * The CDB buffer is later re-parsed by scsi_command_size() based
+ * on its opcode, which may claim a length larger than the AHS
+ * provided. Reject such a mismatch before allocating to avoid
+ * an out-of-bounds read of the CDB buffer in target_cmd_init_cdb().
+ */
+ if (scsi_command_size(hdr->cdb) > cdb_length) {
+ pr_err("Extended CDB AHS: SCSI command size %u exceeds AHS-provided CDB length %u, protocol error.\n",
+ scsi_command_size(hdr->cdb), cdb_length);
+ return iscsit_add_reject_cmd(cmd,
+ ISCSI_REASON_PROTOCOL_ERROR, buf);
+ }
+
cdb = kmalloc(cdb_length, GFP_KERNEL);
if (cdb == NULL)
return iscsit_add_reject_cmd(cmd,
--
2.34.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.