Commit 7e46cf02 authored by Nicholas Bellinger's avatar Nicholas Bellinger

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: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent fef58a60
...@@ -1039,6 +1039,8 @@ static int iscsit_handle_scsi_cmd( ...@@ -1039,6 +1039,8 @@ static int iscsit_handle_scsi_cmd(
*/ */
send_check_condition = 1; send_check_condition = 1;
} else { } else {
cmd->data_length = cmd->se_cmd.data_length;
if (iscsit_decide_list_to_build(cmd, payload_length) < 0) if (iscsit_decide_list_to_build(cmd, payload_length) < 0)
return iscsit_add_reject_from_cmd( return iscsit_add_reject_from_cmd(
ISCSI_REASON_BOOKMARK_NO_RESOURCES, ISCSI_REASON_BOOKMARK_NO_RESOURCES,
...@@ -2508,10 +2510,10 @@ static int iscsit_send_data_in( ...@@ -2508,10 +2510,10 @@ static int iscsit_send_data_in(
if (hdr->flags & ISCSI_FLAG_DATA_STATUS) { if (hdr->flags & ISCSI_FLAG_DATA_STATUS) {
if (cmd->se_cmd.se_cmd_flags & SCF_OVERFLOW_BIT) { if (cmd->se_cmd.se_cmd_flags & SCF_OVERFLOW_BIT) {
hdr->flags |= ISCSI_FLAG_DATA_OVERFLOW; 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) { } else if (cmd->se_cmd.se_cmd_flags & SCF_UNDERFLOW_BIT) {
hdr->flags |= ISCSI_FLAG_DATA_UNDERFLOW; 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); hton24(hdr->dlength, datain.length);
...@@ -3013,10 +3015,10 @@ static int iscsit_send_status( ...@@ -3013,10 +3015,10 @@ static int iscsit_send_status(
hdr->flags |= ISCSI_FLAG_CMD_FINAL; hdr->flags |= ISCSI_FLAG_CMD_FINAL;
if (cmd->se_cmd.se_cmd_flags & SCF_OVERFLOW_BIT) { if (cmd->se_cmd.se_cmd_flags & SCF_OVERFLOW_BIT) {
hdr->flags |= ISCSI_FLAG_CMD_OVERFLOW; 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) { } else if (cmd->se_cmd.se_cmd_flags & SCF_UNDERFLOW_BIT) {
hdr->flags |= ISCSI_FLAG_CMD_UNDERFLOW; 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->response = cmd->iscsi_response;
hdr->cmd_status = cmd->se_cmd.scsi_status; hdr->cmd_status = cmd->se_cmd.scsi_status;
......
...@@ -398,7 +398,6 @@ struct iscsi_cmd { ...@@ -398,7 +398,6 @@ struct iscsi_cmd {
u32 pdu_send_order; u32 pdu_send_order;
/* Current struct iscsi_pdu in struct iscsi_cmd->pdu_list */ /* Current struct iscsi_pdu in struct iscsi_cmd->pdu_list */
u32 pdu_start; u32 pdu_start;
u32 residual_count;
/* Next struct iscsi_seq to send in struct iscsi_cmd->seq_list */ /* Next struct iscsi_seq to send in struct iscsi_cmd->seq_list */
u32 seq_send_order; u32 seq_send_order;
/* Number of struct iscsi_seq in struct iscsi_cmd->seq_list */ /* Number of struct iscsi_seq in struct iscsi_cmd->seq_list */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment