mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 13:11:40 +00:00
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: Quinn Tran <quinn.tran@cavium.com> Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com> Reviewed-by: Christoph Hellwig <hch@lst.de> [ bvanassche: Fixed spelling in patch title ] Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
This commit is contained in:
parent
fc1ffd6cb3
commit
5f35509db1
@ -1556,7 +1556,8 @@ typedef struct {
|
||||
struct atio {
|
||||
uint8_t entry_type; /* Entry type. */
|
||||
uint8_t entry_count; /* Entry count. */
|
||||
uint8_t data[58];
|
||||
__le16 attr_n_length;
|
||||
uint8_t data[56];
|
||||
uint32_t signature;
|
||||
#define ATIO_PROCESSED 0xDEADDEAD /* Signature */
|
||||
};
|
||||
|
@ -6454,12 +6454,29 @@ qlt_24xx_process_atio_queue(struct scsi_qla_host *vha, uint8_t ha_locked)
|
||||
if (!vha->flags.online)
|
||||
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;
|
||||
cnt = pkt->u.raw.entry_count;
|
||||
|
||||
qlt_24xx_atio_pkt_all_vps(vha, (struct atio_from_isp *)pkt,
|
||||
ha_locked);
|
||||
if (unlikely(fcpcmd_is_corrupted(ha->tgt.atio_ring_ptr))) {
|
||||
/*
|
||||
* 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++) {
|
||||
ha->tgt.atio_ring_index++;
|
||||
|
@ -427,13 +427,33 @@ struct atio_from_isp {
|
||||
struct {
|
||||
uint8_t entry_type; /* Entry type. */
|
||||
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;
|
||||
#define ATIO_PROCESSED 0xDEADDEAD /* Signature */
|
||||
} raw;
|
||||
} u;
|
||||
} __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) */
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user