Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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: default avatar <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
Loading
Loading
Loading
Loading
+6 −4
Original line number Original line Diff line number Diff line
@@ -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;
+0 −1
Original line number Original line Diff line number Diff line
@@ -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 */