mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 09:19:51 +00:00
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>
This commit is contained in:
parent
fef58a6096
commit
7e46cf0268
2 changed files with 6 additions and 5 deletions
|
@ -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(
|
||||||
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(
|
||||||
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 {
|
||||||
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 */
|
||||||
|
|
Loading…
Reference in a new issue