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

Commit 5f35509d authored by Quinn Tran's avatar Quinn Tran Committed by Bart Van Assche
Browse files

qla2xxx: Terminate exchange if corrupted



Corrupted ATIO is defined as length of fcp_header & fcp_cmd
payload is less than 0x38. It's the minimum size for a frame to
carry 8..16 bytes SCSI CDB. The exchange will be dropped or
terminated if corrupted.

Signed-off-by: default avatarQuinn Tran <quinn.tran@cavium.com>
Signed-off-by: default avatarHimanshu Madhani <himanshu.madhani@cavium.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
[ bvanassche: Fixed spelling in patch title ]
Signed-off-by: default avatarBart Van Assche <bart.vanassche@sandisk.com>
parent fc1ffd6c
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -1556,7 +1556,8 @@ typedef struct {
struct atio {
struct atio {
	uint8_t		entry_type;		/* Entry type. */
	uint8_t		entry_type;		/* Entry type. */
	uint8_t		entry_count;		/* Entry count. */
	uint8_t		entry_count;		/* Entry count. */
	uint8_t		data[58];
	__le16		attr_n_length;
	uint8_t		data[56];
	uint32_t	signature;
	uint32_t	signature;
#define ATIO_PROCESSED 0xDEADDEAD		/* Signature */
#define ATIO_PROCESSED 0xDEADDEAD		/* Signature */
};
};
+20 −3
Original line number Original line Diff line number Diff line
@@ -6454,12 +6454,29 @@ qlt_24xx_process_atio_queue(struct scsi_qla_host *vha, uint8_t ha_locked)
	if (!vha->flags.online)
	if (!vha->flags.online)
		return;
		return;


	while (ha->tgt.atio_ring_ptr->signature != ATIO_PROCESSED) {
	while ((ha->tgt.atio_ring_ptr->signature != ATIO_PROCESSED) ||
	    fcpcmd_is_corrupted(ha->tgt.atio_ring_ptr)) {
		pkt = (struct atio_from_isp *)ha->tgt.atio_ring_ptr;
		pkt = (struct atio_from_isp *)ha->tgt.atio_ring_ptr;
		cnt = pkt->u.raw.entry_count;
		cnt = pkt->u.raw.entry_count;


		qlt_24xx_atio_pkt_all_vps(vha, (struct atio_from_isp *)pkt,
		if (unlikely(fcpcmd_is_corrupted(ha->tgt.atio_ring_ptr))) {
		    ha_locked);
			/*
			 * This packet is corrupted. The header + payload
			 * can not be trusted. There is no point in passing
			 * it further up.
			 */
			ql_log(ql_log_warn, vha, 0xffff,
			    "corrupted fcp frame SID[%3phN] OXID[%04x] EXCG[%x] %64phN\n",
			    pkt->u.isp24.fcp_hdr.s_id,
			    be16_to_cpu(pkt->u.isp24.fcp_hdr.ox_id),
			    le32_to_cpu(pkt->u.isp24.exchange_addr), pkt);

			adjust_corrupted_atio(pkt);
			qlt_send_term_exchange(vha, NULL, pkt, ha_locked, 0);
		} else {
			qlt_24xx_atio_pkt_all_vps(vha,
			    (struct atio_from_isp *)pkt, ha_locked);
		}


		for (i = 0; i < cnt; i++) {
		for (i = 0; i < cnt; i++) {
			ha->tgt.atio_ring_index++;
			ha->tgt.atio_ring_index++;
+21 −1
Original line number Original line Diff line number Diff line
@@ -427,13 +427,33 @@ struct atio_from_isp {
		struct {
		struct {
			uint8_t  entry_type;	/* Entry type. */
			uint8_t  entry_type;	/* Entry type. */
			uint8_t  entry_count;	/* Entry count. */
			uint8_t  entry_count;	/* Entry count. */
			uint8_t  data[58];
			__le16	 attr_n_length;
#define FCP_CMD_LENGTH_MASK 0x0fff
#define FCP_CMD_LENGTH_MIN  0x38
			uint8_t  data[56];
			uint32_t signature;
			uint32_t signature;
#define ATIO_PROCESSED 0xDEADDEAD		/* Signature */
#define ATIO_PROCESSED 0xDEADDEAD		/* Signature */
		} raw;
		} raw;
	} u;
	} u;
} __packed;
} __packed;


static inline int fcpcmd_is_corrupted(struct atio *atio)
{
	if (atio->entry_type == ATIO_TYPE7 &&
	    (le16_to_cpu(atio->attr_n_length & FCP_CMD_LENGTH_MASK) <
	    FCP_CMD_LENGTH_MIN))
		return 1;
	else
		return 0;
}

/* adjust corrupted atio so we won't trip over the same entry again. */
static inline void adjust_corrupted_atio(struct atio_from_isp *atio)
{
	atio->u.raw.attr_n_length = cpu_to_le16(FCP_CMD_LENGTH_MIN);
	atio->u.isp24.fcp_cmnd.add_cdb_len = 0;
}

#define CTIO_TYPE7 0x12 /* Continue target I/O entry (for 24xx) */
#define CTIO_TYPE7 0x12 /* Continue target I/O entry (for 24xx) */


/*
/*