aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuinn Tran <quinn.tran@cavium.com>2016-12-23 21:06:11 -0500
committerBart Van Assche <bart.vanassche@sandisk.com>2017-01-17 14:26:56 -0500
commit5f35509db179ca7ed1feaa4b14f841adb06ed220 (patch)
treef5b4e6bc95ec09eed327291db14d45217ebb6e33
parentfc1ffd6cb38a1c1af625b9833c41928039e733f5 (diff)
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>
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h3
-rw-r--r--drivers/scsi/qla2xxx/qla_target.c23
-rw-r--r--drivers/scsi/qla2xxx/qla_target.h22
3 files changed, 43 insertions, 5 deletions
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index f7df01b76714..1f7c6d2c736d 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -1556,7 +1556,8 @@ typedef struct {
1556struct atio { 1556struct atio {
1557 uint8_t entry_type; /* Entry type. */ 1557 uint8_t entry_type; /* Entry type. */
1558 uint8_t entry_count; /* Entry count. */ 1558 uint8_t entry_count; /* Entry count. */
1559 uint8_t data[58]; 1559 __le16 attr_n_length;
1560 uint8_t data[56];
1560 uint32_t signature; 1561 uint32_t signature;
1561#define ATIO_PROCESSED 0xDEADDEAD /* Signature */ 1562#define ATIO_PROCESSED 0xDEADDEAD /* Signature */
1562}; 1563};
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 6eb051783dc8..85dcd7cdffca 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -6454,12 +6454,29 @@ qlt_24xx_process_atio_queue(struct scsi_qla_host *vha, uint8_t ha_locked)
6454 if (!vha->flags.online) 6454 if (!vha->flags.online)
6455 return; 6455 return;
6456 6456
6457 while (ha->tgt.atio_ring_ptr->signature != ATIO_PROCESSED) { 6457 while ((ha->tgt.atio_ring_ptr->signature != ATIO_PROCESSED) ||
6458 fcpcmd_is_corrupted(ha->tgt.atio_ring_ptr)) {
6458 pkt = (struct atio_from_isp *)ha->tgt.atio_ring_ptr; 6459 pkt = (struct atio_from_isp *)ha->tgt.atio_ring_ptr;
6459 cnt = pkt->u.raw.entry_count; 6460 cnt = pkt->u.raw.entry_count;
6460 6461
6461 qlt_24xx_atio_pkt_all_vps(vha, (struct atio_from_isp *)pkt, 6462 if (unlikely(fcpcmd_is_corrupted(ha->tgt.atio_ring_ptr))) {
6462 ha_locked); 6463 /*
6464 * This packet is corrupted. The header + payload
6465 * can not be trusted. There is no point in passing
6466 * it further up.
6467 */
6468 ql_log(ql_log_warn, vha, 0xffff,
6469 "corrupted fcp frame SID[%3phN] OXID[%04x] EXCG[%x] %64phN\n",
6470 pkt->u.isp24.fcp_hdr.s_id,
6471 be16_to_cpu(pkt->u.isp24.fcp_hdr.ox_id),
6472 le32_to_cpu(pkt->u.isp24.exchange_addr), pkt);
6473
6474 adjust_corrupted_atio(pkt);
6475 qlt_send_term_exchange(vha, NULL, pkt, ha_locked, 0);
6476 } else {
6477 qlt_24xx_atio_pkt_all_vps(vha,
6478 (struct atio_from_isp *)pkt, ha_locked);
6479 }
6463 6480
6464 for (i = 0; i < cnt; i++) { 6481 for (i = 0; i < cnt; i++) {
6465 ha->tgt.atio_ring_index++; 6482 ha->tgt.atio_ring_index++;
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index f26c5f60eedd..0824a8164a24 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -427,13 +427,33 @@ struct atio_from_isp {
427 struct { 427 struct {
428 uint8_t entry_type; /* Entry type. */ 428 uint8_t entry_type; /* Entry type. */
429 uint8_t entry_count; /* Entry count. */ 429 uint8_t entry_count; /* Entry count. */
430 uint8_t data[58]; 430 __le16 attr_n_length;
431#define FCP_CMD_LENGTH_MASK 0x0fff
432#define FCP_CMD_LENGTH_MIN 0x38
433 uint8_t data[56];
431 uint32_t signature; 434 uint32_t signature;
432#define ATIO_PROCESSED 0xDEADDEAD /* Signature */ 435#define ATIO_PROCESSED 0xDEADDEAD /* Signature */
433 } raw; 436 } raw;
434 } u; 437 } u;
435} __packed; 438} __packed;
436 439
440static inline int fcpcmd_is_corrupted(struct atio *atio)
441{
442 if (atio->entry_type == ATIO_TYPE7 &&
443 (le16_to_cpu(atio->attr_n_length & FCP_CMD_LENGTH_MASK) <
444 FCP_CMD_LENGTH_MIN))
445 return 1;
446 else
447 return 0;
448}
449
450/* adjust corrupted atio so we won't trip over the same entry again. */
451static inline void adjust_corrupted_atio(struct atio_from_isp *atio)
452{
453 atio->u.raw.attr_n_length = cpu_to_le16(FCP_CMD_LENGTH_MIN);
454 atio->u.isp24.fcp_cmnd.add_cdb_len = 0;
455}
456
437#define CTIO_TYPE7 0x12 /* Continue target I/O entry (for 24xx) */ 457#define CTIO_TYPE7 0x12 /* Continue target I/O entry (for 24xx) */
438 458
439/* 459/*