changeset 7001:9eb04b5ace1c

6697662 scsa needs to improve checking of uscsi_cdblen
author lh195018
date Tue, 01 Jul 2008 20:08:40 -0700
parents 3949d5f9243b
children 6f8d21f0cdfb
files usr/src/uts/common/io/scsi/impl/scsi_subr.c
diffstat 1 files changed, 18 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/io/scsi/impl/scsi_subr.c	Tue Jul 01 19:58:15 2008 -0700
+++ b/usr/src/uts/common/io/scsi/impl/scsi_subr.c	Tue Jul 01 20:08:40 2008 -0700
@@ -39,6 +39,8 @@
 
 extern uintptr_t scsi_callback_id;
 
+extern uchar_t scsi_cdb_size[];
+
 /*
  * Common buffer for scsi_log
  */
@@ -2114,15 +2116,22 @@
 		goto done;
 	}
 
-	/*
-	 * If the length of the CDB is greater than 16 bytes, it must be
-	 * a variable length CDB (i.e. the opcode must be 0x7f).
-	 */
-	if (uscmd->uscsi_cdblen > SCSI_CDB_SIZE &&
-	    uscmd->uscsi_cdb[0] != SCMD_VAR_LEN) {
-		kmem_free(uscmd->uscsi_cdb, (size_t)uscmd->uscsi_cdblen);
-		rval = EINVAL;
-		goto done;
+	if (uscmd->uscsi_cdb[0] != SCMD_VAR_LEN) {
+		if (uscmd->uscsi_cdblen > SCSI_CDB_SIZE ||
+		    scsi_cdb_size[CDB_GROUPID(uscmd->uscsi_cdb[0])] >
+		    uscmd->uscsi_cdblen) {
+			kmem_free(uscmd->uscsi_cdb,
+			    (size_t)uscmd->uscsi_cdblen);
+			rval = EINVAL;
+			goto done;
+		}
+	} else {
+		if ((uscmd->uscsi_cdblen % 4) != 0) {
+			kmem_free(uscmd->uscsi_cdb,
+			    (size_t)uscmd->uscsi_cdblen);
+			rval = EINVAL;
+			goto done;
+		}
 	}
 
 	/*