diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2011-11-15 23:59:00 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-12-21 12:58:29 -0800 |
commit | 43dd6e6faffcacc6d8d9d12f15d6aa5f2f4fa351 (patch) | |
tree | 617a22e736a737abeb979aaf202cf7ba99f9c159 | |
parent | 1c9c1ada7ee0b4b42e451d35153dff3735b28cac (diff) |
iscsi-target: Fix residual count hanlding + remove iscsi_cmd->residual_count
commit 7e46cf02687e40197ae07c623e660be2a2720064 upstream.
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>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/target/iscsi/iscsi_target.c | 10 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target_core.h | 1 |
2 files changed, 6 insertions, 5 deletions
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 26a5d8b94ba8..114d274e1277 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -1043,6 +1043,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, @@ -2512,10 +2514,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); @@ -3017,10 +3019,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; diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index 470ed551eeb5..8d18b2cfafec 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -395,7 +395,6 @@ struct iscsi_cmd { u32 pdu_send_order; /* Current struct iscsi_pdu in struct iscsi_cmd->pdu_list */ u32 pdu_start; - u32 residual_count; /* Next struct iscsi_seq to send in struct iscsi_cmd->seq_list */ u32 seq_send_order; /* Number of struct iscsi_seq in struct iscsi_cmd->seq_list */ |