summaryrefslogtreecommitdiff
path: root/drivers/target/iscsi/iscsi_target.c
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2011-11-16 11:59:00 +0400
committerNicholas Bellinger <nab@linux-iscsi.org>2011-12-06 10:00:54 +0400
commit7e46cf02687e40197ae07c623e660be2a2720064 (patch)
tree47e6b57863e2716dfa5a6347b12a23c063e446cd /drivers/target/iscsi/iscsi_target.c
parentfef58a6096770ed6ab49103a430cc755254a74d9 (diff)
downloadlinux-7e46cf02687e40197ae07c623e660be2a2720064.tar.xz
iscsi-target: Fix residual count hanlding + remove iscsi_cmd->residual_count
This patch fixes iscsi-target handling of underflow where residual data is causing an OOPs by using the incorrect iscsi_cmd_t->data_length initially assigned in iscsit_allocate_se_cmd(). It resets iscsi_cmd_t->data_length from se_cmd_t->data_length after transport_generic_allocate_tasks() has been invoked in iscsit_handle_scsi_cmd() RX context, and converts iscsi_cmd->residual_count usage to access iscsi_cmd->se_cmd.residual_count to get the proper residual count set by target-core. Reported-by: <lists@internyc.net> Cc: Christoph Hellwig <hch@lst.de> Cc: Andy Grover <agrover@redhat.com> Cc: stable@kernel.org Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target/iscsi/iscsi_target.c')
-rw-r--r--drivers/target/iscsi/iscsi_target.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index 4d81e1007c92..26834eff8960 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -1039,6 +1039,8 @@ done:
*/
send_check_condition = 1;
} else {
+ cmd->data_length = cmd->se_cmd.data_length;
+
if (iscsit_decide_list_to_build(cmd, payload_length) < 0)
return iscsit_add_reject_from_cmd(
ISCSI_REASON_BOOKMARK_NO_RESOURCES,
@@ -2508,10 +2510,10 @@ static int iscsit_send_data_in(
if (hdr->flags & ISCSI_FLAG_DATA_STATUS) {
if (cmd->se_cmd.se_cmd_flags & SCF_OVERFLOW_BIT) {
hdr->flags |= ISCSI_FLAG_DATA_OVERFLOW;
- hdr->residual_count = cpu_to_be32(cmd->residual_count);
+ hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count);
} else if (cmd->se_cmd.se_cmd_flags & SCF_UNDERFLOW_BIT) {
hdr->flags |= ISCSI_FLAG_DATA_UNDERFLOW;
- hdr->residual_count = cpu_to_be32(cmd->residual_count);
+ hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count);
}
}
hton24(hdr->dlength, datain.length);
@@ -3013,10 +3015,10 @@ static int iscsit_send_status(
hdr->flags |= ISCSI_FLAG_CMD_FINAL;
if (cmd->se_cmd.se_cmd_flags & SCF_OVERFLOW_BIT) {
hdr->flags |= ISCSI_FLAG_CMD_OVERFLOW;
- hdr->residual_count = cpu_to_be32(cmd->residual_count);
+ hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count);
} else if (cmd->se_cmd.se_cmd_flags & SCF_UNDERFLOW_BIT) {
hdr->flags |= ISCSI_FLAG_CMD_UNDERFLOW;
- hdr->residual_count = cpu_to_be32(cmd->residual_count);
+ hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count);
}
hdr->response = cmd->iscsi_response;
hdr->cmd_status = cmd->se_cmd.scsi_status;