aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2011-11-16 02:59:00 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2011-12-06 01:00:54 -0500
commit7e46cf02687e40197ae07c623e660be2a2720064 (patch)
tree47e6b57863e2716dfa5a6347b12a23c063e446cd /drivers/target
parentfef58a6096770ed6ab49103a430cc755254a74d9 (diff)
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')
-rw-r--r--drivers/target/iscsi/iscsi_target.c10
-rw-r--r--drivers/target/iscsi/iscsi_target_core.h1
2 files changed, 6 insertions, 5 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:
1039 */ 1039 */
1040 send_check_condition = 1; 1040 send_check_condition = 1;
1041 } else { 1041 } else {
1042 cmd->data_length = cmd->se_cmd.data_length;
1043
1042 if (iscsit_decide_list_to_build(cmd, payload_length) < 0) 1044 if (iscsit_decide_list_to_build(cmd, payload_length) < 0)
1043 return iscsit_add_reject_from_cmd( 1045 return iscsit_add_reject_from_cmd(
1044 ISCSI_REASON_BOOKMARK_NO_RESOURCES, 1046 ISCSI_REASON_BOOKMARK_NO_RESOURCES,
@@ -2508,10 +2510,10 @@ static int iscsit_send_data_in(
2508 if (hdr->flags & ISCSI_FLAG_DATA_STATUS) { 2510 if (hdr->flags & ISCSI_FLAG_DATA_STATUS) {
2509 if (cmd->se_cmd.se_cmd_flags & SCF_OVERFLOW_BIT) { 2511 if (cmd->se_cmd.se_cmd_flags & SCF_OVERFLOW_BIT) {
2510 hdr->flags |= ISCSI_FLAG_DATA_OVERFLOW; 2512 hdr->flags |= ISCSI_FLAG_DATA_OVERFLOW;
2511 hdr->residual_count = cpu_to_be32(cmd->residual_count); 2513 hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count);
2512 } else if (cmd->se_cmd.se_cmd_flags & SCF_UNDERFLOW_BIT) { 2514 } else if (cmd->se_cmd.se_cmd_flags & SCF_UNDERFLOW_BIT) {
2513 hdr->flags |= ISCSI_FLAG_DATA_UNDERFLOW; 2515 hdr->flags |= ISCSI_FLAG_DATA_UNDERFLOW;
2514 hdr->residual_count = cpu_to_be32(cmd->residual_count); 2516 hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count);
2515 } 2517 }
2516 } 2518 }
2517 hton24(hdr->dlength, datain.length); 2519 hton24(hdr->dlength, datain.length);
@@ -3013,10 +3015,10 @@ static int iscsit_send_status(
3013 hdr->flags |= ISCSI_FLAG_CMD_FINAL; 3015 hdr->flags |= ISCSI_FLAG_CMD_FINAL;
3014 if (cmd->se_cmd.se_cmd_flags & SCF_OVERFLOW_BIT) { 3016 if (cmd->se_cmd.se_cmd_flags & SCF_OVERFLOW_BIT) {
3015 hdr->flags |= ISCSI_FLAG_CMD_OVERFLOW; 3017 hdr->flags |= ISCSI_FLAG_CMD_OVERFLOW;
3016 hdr->residual_count = cpu_to_be32(cmd->residual_count); 3018 hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count);
3017 } else if (cmd->se_cmd.se_cmd_flags & SCF_UNDERFLOW_BIT) { 3019 } else if (cmd->se_cmd.se_cmd_flags & SCF_UNDERFLOW_BIT) {
3018 hdr->flags |= ISCSI_FLAG_CMD_UNDERFLOW; 3020 hdr->flags |= ISCSI_FLAG_CMD_UNDERFLOW;
3019 hdr->residual_count = cpu_to_be32(cmd->residual_count); 3021 hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count);
3020 } 3022 }
3021 hdr->response = cmd->iscsi_response; 3023 hdr->response = cmd->iscsi_response;
3022 hdr->cmd_status = cmd->se_cmd.scsi_status; 3024 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 3723d90d5ae5..0e96a6b13174 100644
--- a/drivers/target/iscsi/iscsi_target_core.h
+++ b/drivers/target/iscsi/iscsi_target_core.h
@@ -398,7 +398,6 @@ struct iscsi_cmd {
398 u32 pdu_send_order; 398 u32 pdu_send_order;
399 /* Current struct iscsi_pdu in struct iscsi_cmd->pdu_list */ 399 /* Current struct iscsi_pdu in struct iscsi_cmd->pdu_list */
400 u32 pdu_start; 400 u32 pdu_start;
401 u32 residual_count;
402 /* Next struct iscsi_seq to send in struct iscsi_cmd->seq_list */ 401 /* Next struct iscsi_seq to send in struct iscsi_cmd->seq_list */
403 u32 seq_send_order; 402 u32 seq_send_order;
404 /* Number of struct iscsi_seq in struct iscsi_cmd->seq_list */ 403 /* Number of struct iscsi_seq in struct iscsi_cmd->seq_list */