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

Commit c04a6091 authored by Christophe Vu-Brugier's avatar Christophe Vu-Brugier Committed by Nicholas Bellinger
Browse files

iscsi-target: remove support for obsolete markers

Support for markers is currently broken because of a bug in
iscsi_enforce_integrity_rules(): the "IFMarkInt_Reject" and
"OFMarkInt_Reject" variables are always equal to 1 in
iscsi_enforce_integrity_rules().

Moreover, fixed interval markers keys (IFMarker, OFMarker, IFMarkInt
and OFMarkInt) are obsolete according to iSCSI RFC 7143:

>From http://tools.ietf.org/html/rfc7143#section-13.25

:

   13.25.  Obsoleted Keys

   This document obsoletes the following keys defined in [RFC3720]:
   IFMarker, OFMarker, OFMarkInt, and IFMarkInt.  However, iSCSI
   implementations compliant to this document may still receive these
   obsoleted keys -- i.e., in a responder role -- in a text negotiation.

   When an IFMarker or OFMarker key is received, a compliant iSCSI
   implementation SHOULD respond with the constant "Reject" value.  The
   implementation MAY alternatively respond with a "No" value.

   However, the implementation MUST NOT respond with a "NotUnderstood"
   value for either of these keys.

   When an IFMarkInt or OFMarkInt key is received, a compliant iSCSI
   implementation MUST respond with the constant "Reject" value.  The
   implementation MUST NOT respond with a "NotUnderstood" value for
   either of these keys.

This patch disables markers by turning the corresponding parameters to
read-only. The default value of IFMarker and OFMarker remains "No" but
the user cannot change it to "Yes" anymore. The new value of IFMarkInt
and OFMarkInt is "Reject".

(Drop left-over iscsi_get_value_from_number_range + make configfs
 parameters attrs R/W nops - nab)

Signed-off-by: default avatarChristophe Vu-Brugier <cvubrugier@fastmail.fm>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent 414e4627
Loading
Loading
Loading
Loading
+4 −16
Original line number Diff line number Diff line
@@ -2736,11 +2736,7 @@ static int iscsit_send_datain(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
	cmd->iov_data_count = iov_count;
	cmd->tx_size = tx_size;

	/* sendpage is preferred but can't insert markers */
	if (!conn->conn_ops->IFMarker)
	ret = iscsit_fe_sendpage_sg(cmd, conn);
	else
		ret = iscsit_send_tx_data(cmd, conn, 0);

	iscsit_unmap_iovec(cmd);

@@ -4072,17 +4068,9 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf)
			" opcode while ERL=0, closing iSCSI connection.\n");
			return -1;
		}
		if (!conn->conn_ops->OFMarker) {
			pr_err("Unable to recover from unknown"
			" opcode while OFMarker=No, closing iSCSI"
				" connection.\n");
			return -1;
		}
		if (iscsit_recover_from_unknown_opcode(conn) < 0) {
			pr_err("Unable to recover from unknown"
				" opcode, closing iSCSI connection.\n");
			return -1;
		}
		pr_err("Unable to recover from unknown opcode while OFMarker=No,"
		       " closing iSCSI connection.\n");
		ret = -1;
		break;
	}

+0 −53
Original line number Diff line number Diff line
@@ -956,56 +956,3 @@ void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn)

	iscsit_handle_connection_cleanup(conn);
}

/*
 *	This is the simple function that makes the magic of
 *	sync and steering happen in the follow paradoxical order:
 *
 *	0) Receive conn->of_marker (bytes left until next OFMarker)
 *	   bytes into an offload buffer.  When we pass the exact number
 *	   of bytes in conn->of_marker, iscsit_dump_data_payload() and hence
 *	   rx_data() will automatically receive the identical u32 marker
 *	   values and store it in conn->of_marker_offset;
 *	1) Now conn->of_marker_offset will contain the offset to the start
 *	   of the next iSCSI PDU.  Dump these remaining bytes into another
 *	   offload buffer.
 *	2) We are done!
 *	   Next byte in the TCP stream will contain the next iSCSI PDU!
 *	   Cool Huh?!
 */
int iscsit_recover_from_unknown_opcode(struct iscsi_conn *conn)
{
	/*
	 * Make sure the remaining bytes to next maker is a sane value.
	 */
	if (conn->of_marker > (conn->conn_ops->OFMarkInt * 4)) {
		pr_err("Remaining bytes to OFMarker: %u exceeds"
			" OFMarkInt bytes: %u.\n", conn->of_marker,
				conn->conn_ops->OFMarkInt * 4);
		return -1;
	}

	pr_debug("Advancing %u bytes in TCP stream to get to the"
			" next OFMarker.\n", conn->of_marker);

	if (iscsit_dump_data_payload(conn, conn->of_marker, 0) < 0)
		return -1;

	/*
	 * Make sure the offset marker we retrived is a valid value.
	 */
	if (conn->of_marker_offset > (ISCSI_HDR_LEN + (ISCSI_CRC_LEN * 2) +
	    conn->conn_ops->MaxRecvDataSegmentLength)) {
		pr_err("OfMarker offset value: %u exceeds limit.\n",
			conn->of_marker_offset);
		return -1;
	}

	pr_debug("Discarding %u bytes of TCP stream to get to the"
			" next iSCSI Opcode.\n", conn->of_marker_offset);

	if (iscsit_dump_data_payload(conn, conn->of_marker_offset, 0) < 0)
		return -1;

	return 0;
}
+0 −1
Original line number Diff line number Diff line
@@ -10,6 +10,5 @@ extern void iscsit_connection_reinstatement_rcfr(struct iscsi_conn *);
extern void iscsit_cause_connection_reinstatement(struct iscsi_conn *, int);
extern void iscsit_fall_back_to_erl0(struct iscsi_session *);
extern void iscsit_take_action_for_connection_exit(struct iscsi_conn *);
extern int iscsit_recover_from_unknown_opcode(struct iscsi_conn *);

#endif   /*** ISCSI_TARGET_ERL0_H ***/
+1 −57
Original line number Diff line number Diff line
@@ -410,8 +410,6 @@ static int iscsi_login_zero_tsih_s2(
	if (iscsi_change_param_sprintf(conn, "ErrorRecoveryLevel=%d", na->default_erl))
		return -1;

	if (iscsi_login_disable_FIM_keys(conn->param_list, conn) < 0)
		return -1;
	/*
	 * Set RDMAExtensions=Yes by default for iSER enabled network portals
	 */
@@ -477,59 +475,6 @@ static int iscsi_login_zero_tsih_s2(
	return 0;
}

/*
 * Remove PSTATE_NEGOTIATE for the four FIM related keys.
 * The Initiator node will be able to enable FIM by proposing them itself.
 */
int iscsi_login_disable_FIM_keys(
	struct iscsi_param_list *param_list,
	struct iscsi_conn *conn)
{
	struct iscsi_param *param;

	param = iscsi_find_param_from_key("OFMarker", param_list);
	if (!param) {
		pr_err("iscsi_find_param_from_key() for"
				" OFMarker failed\n");
		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
				ISCSI_LOGIN_STATUS_NO_RESOURCES);
		return -1;
	}
	param->state &= ~PSTATE_NEGOTIATE;

	param = iscsi_find_param_from_key("OFMarkInt", param_list);
	if (!param) {
		pr_err("iscsi_find_param_from_key() for"
				" IFMarker failed\n");
		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
				ISCSI_LOGIN_STATUS_NO_RESOURCES);
		return -1;
	}
	param->state &= ~PSTATE_NEGOTIATE;

	param = iscsi_find_param_from_key("IFMarker", param_list);
	if (!param) {
		pr_err("iscsi_find_param_from_key() for"
				" IFMarker failed\n");
		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
				ISCSI_LOGIN_STATUS_NO_RESOURCES);
		return -1;
	}
	param->state &= ~PSTATE_NEGOTIATE;

	param = iscsi_find_param_from_key("IFMarkInt", param_list);
	if (!param) {
		pr_err("iscsi_find_param_from_key() for"
				" IFMarker failed\n");
		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
				ISCSI_LOGIN_STATUS_NO_RESOURCES);
		return -1;
	}
	param->state &= ~PSTATE_NEGOTIATE;

	return 0;
}

static int iscsi_login_non_zero_tsih_s1(
	struct iscsi_conn *conn,
	unsigned char *buf)
@@ -616,7 +561,7 @@ static int iscsi_login_non_zero_tsih_s2(
	if (iscsi_change_param_sprintf(conn, "TargetPortalGroupTag=%hu", sess->tpg->tpgt))
		return -1;

	return iscsi_login_disable_FIM_keys(conn->param_list, conn);
	return 0;
}

int iscsi_login_post_auth_non_zero_tsih(
@@ -765,7 +710,6 @@ int iscsi_post_login_handler(
	conn->conn_state = TARG_CONN_STATE_LOGGED_IN;

	iscsi_set_connection_parameters(conn->conn_ops, conn->param_list);
	iscsit_set_sync_and_steering_values(conn);
	/*
	 * SCSI Initiator -> SCSI Target Port Mapping
	 */
+0 −1
Original line number Diff line number Diff line
@@ -16,6 +16,5 @@ extern int iscsi_post_login_handler(struct iscsi_np *, struct iscsi_conn *, u8);
extern void iscsi_target_login_sess_out(struct iscsi_conn *, struct iscsi_np *,
				bool, bool);
extern int iscsi_target_login_thread(void *);
extern int iscsi_login_disable_FIM_keys(struct iscsi_param_list *, struct iscsi_conn *);

#endif   /*** ISCSI_TARGET_LOGIN_H ***/
Loading