aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen M. Cameron <scameron@beardog.cce.hp.com>2011-06-03 10:57:34 -0400
committerJames Bottomley <JBottomley@Parallels.com>2011-06-29 13:09:56 -0400
commitdb111e18ec19bbadbf44a60f73bf2ff5991dc915 (patch)
treef6c18c036be2c0db91c432b80ad8f7c38e40200e
parentc2dd32e02648d77466f320d6edd157b5080e7c99 (diff)
[SCSI] hpsa: fix potential overrun while memcpy'ing sense data
This memcpy: memcpy(cmd->sense_buffer, ei->SenseInfo, ei->SenseLen > SCSI_SENSE_BUFFERSIZE ? SCSI_SENSE_BUFFERSIZE : ei->SenseLen); The ei->SenseLen field is filled in by the Smart Array. For requests to logical drives, it will not exceed 32 bytes, so should be ok, but for physical requests it depends on the target device, not the Smart Array. It's conceivable that this could exceed the 32 byte size of ei->SenseInfo. In that case, the memcpy would read past the end of ei->SenseInfo, copying data from the next command, as if it were sense data, or, if it happened to be the very last command in the block of allocated commands, could fall off the end of the allocated area and crash. I'm not aware of anyone ever encountering this behavior, but it could conceivably happen. This bug was found by Coverity. Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--drivers/scsi/hpsa.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index a75122d1c710..6bba23a26303 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -1037,6 +1037,7 @@ static void complete_scsi_command(struct CommandList *cp)
1037 unsigned char sense_key; 1037 unsigned char sense_key;
1038 unsigned char asc; /* additional sense code */ 1038 unsigned char asc; /* additional sense code */
1039 unsigned char ascq; /* additional sense code qualifier */ 1039 unsigned char ascq; /* additional sense code qualifier */
1040 unsigned long sense_data_size;
1040 1041
1041 ei = cp->err_info; 1042 ei = cp->err_info;
1042 cmd = (struct scsi_cmnd *) cp->scsi_cmd; 1043 cmd = (struct scsi_cmnd *) cp->scsi_cmd;
@@ -1051,10 +1052,14 @@ static void complete_scsi_command(struct CommandList *cp)
1051 cmd->result |= ei->ScsiStatus; 1052 cmd->result |= ei->ScsiStatus;
1052 1053
1053 /* copy the sense data whether we need to or not. */ 1054 /* copy the sense data whether we need to or not. */
1054 memcpy(cmd->sense_buffer, ei->SenseInfo, 1055 if (SCSI_SENSE_BUFFERSIZE < sizeof(ei->SenseInfo))
1055 ei->SenseLen > SCSI_SENSE_BUFFERSIZE ? 1056 sense_data_size = SCSI_SENSE_BUFFERSIZE;
1056 SCSI_SENSE_BUFFERSIZE : 1057 else
1057 ei->SenseLen); 1058 sense_data_size = sizeof(ei->SenseInfo);
1059 if (ei->SenseLen < sense_data_size)
1060 sense_data_size = ei->SenseLen;
1061
1062 memcpy(cmd->sense_buffer, ei->SenseInfo, sense_data_size);
1058 scsi_set_resid(cmd, ei->ResidualCnt); 1063 scsi_set_resid(cmd, ei->ResidualCnt);
1059 1064
1060 if (ei->CommandStatus == 0) { 1065 if (ei->CommandStatus == 0) {