aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuinn Tran <quinn.tran@qlogic.com>2016-02-04 11:45:16 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2016-02-06 22:44:30 -0500
commitcb43285ff7039fe3c4b0bc476e6d6569c31104f3 (patch)
treed1187e0ce756d7d7006ff37f0b051808a90d5751
parent0633e123465b61a12a262b742bebf2a9945f7964 (diff)
qla2xxx: Fix stale pointer access.
[ Upstream Commit 84e32a06f4f8756ce9ec3c8dc7e97896575f0771 ] Commit 84e32a0 ("qla2xxx: Use pci_enable_msix_range() instead of pci_enable_msix()") introduced a regression when target mode is enabled. In qla24xx_enable_msix(), ha->max_rsp_queues was incorrectly set to a value higher than the number of response queues allocated causing an invalid dereference. Specifically here in qla2x00_init_rings(): *rsp->in_ptr = 0; Add additional check to make sure the pointer is valid. following call stack will be seen ---- 8< ---- RIP: 0010:[<ffffffffa02ccadc>] [<ffffffffa02ccadc>] qla2x00_init_rings+0xdc/0x320 [qla2xxx] RSP: 0018:ffff880429447dd8 EFLAGS: 00010082 .... Call Trace: [<ffffffffa02ceb40>] qla2x00_abort_isp+0x170/0x6b0 [qla2xxx] [<ffffffffa02c6f77>] qla2x00_do_dpc+0x357/0x7f0 [qla2xxx] [<ffffffffa02c6c20>] ? qla2x00_relogin+0x260/0x260 [qla2xxx] [<ffffffff8107d2c9>] kthread+0xc9/0xe0 [<ffffffff8107d200>] ? flush_kthread_worker+0x90/0x90 [<ffffffff8172cc6f>] ret_from_fork+0x3f/0x70 [<ffffffff8107d200>] ? flush_kthread_worker+0x90/0x90 ---- 8< ---- Cc: <stable@vger.kernel.org> Signed-off-by: Quinn Tran <quinn.tran@qlogic.com> Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c10
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_mid.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c6
-rw-r--r--drivers/scsi/qla2xxx/qla_tmpl.c16
5 files changed, 31 insertions, 9 deletions
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 52a87657c7dd..692a7570b5e1 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -2204,7 +2204,7 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
2204 /* Clear outstanding commands array. */ 2204 /* Clear outstanding commands array. */
2205 for (que = 0; que < ha->max_req_queues; que++) { 2205 for (que = 0; que < ha->max_req_queues; que++) {
2206 req = ha->req_q_map[que]; 2206 req = ha->req_q_map[que];
2207 if (!req) 2207 if (!req || !test_bit(que, ha->req_qid_map))
2208 continue; 2208 continue;
2209 req->out_ptr = (void *)(req->ring + req->length); 2209 req->out_ptr = (void *)(req->ring + req->length);
2210 *req->out_ptr = 0; 2210 *req->out_ptr = 0;
@@ -2221,7 +2221,7 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
2221 2221
2222 for (que = 0; que < ha->max_rsp_queues; que++) { 2222 for (que = 0; que < ha->max_rsp_queues; que++) {
2223 rsp = ha->rsp_q_map[que]; 2223 rsp = ha->rsp_q_map[que];
2224 if (!rsp) 2224 if (!rsp || !test_bit(que, ha->rsp_qid_map))
2225 continue; 2225 continue;
2226 rsp->in_ptr = (void *)(rsp->ring + rsp->length); 2226 rsp->in_ptr = (void *)(rsp->ring + rsp->length);
2227 *rsp->in_ptr = 0; 2227 *rsp->in_ptr = 0;
@@ -4981,7 +4981,7 @@ qla25xx_init_queues(struct qla_hw_data *ha)
4981 4981
4982 for (i = 1; i < ha->max_rsp_queues; i++) { 4982 for (i = 1; i < ha->max_rsp_queues; i++) {
4983 rsp = ha->rsp_q_map[i]; 4983 rsp = ha->rsp_q_map[i];
4984 if (rsp) { 4984 if (rsp && test_bit(i, ha->rsp_qid_map)) {
4985 rsp->options &= ~BIT_0; 4985 rsp->options &= ~BIT_0;
4986 ret = qla25xx_init_rsp_que(base_vha, rsp); 4986 ret = qla25xx_init_rsp_que(base_vha, rsp);
4987 if (ret != QLA_SUCCESS) 4987 if (ret != QLA_SUCCESS)
@@ -4996,8 +4996,8 @@ qla25xx_init_queues(struct qla_hw_data *ha)
4996 } 4996 }
4997 for (i = 1; i < ha->max_req_queues; i++) { 4997 for (i = 1; i < ha->max_req_queues; i++) {
4998 req = ha->req_q_map[i]; 4998 req = ha->req_q_map[i];
4999 if (req) { 4999 if (req && test_bit(i, ha->req_qid_map)) {
5000 /* Clear outstanding commands array. */ 5000 /* Clear outstanding commands array. */
5001 req->options &= ~BIT_0; 5001 req->options &= ~BIT_0;
5002 ret = qla25xx_init_req_que(base_vha, req); 5002 ret = qla25xx_init_req_que(base_vha, req);
5003 if (ret != QLA_SUCCESS) 5003 if (ret != QLA_SUCCESS)
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index d4d65eb0e9b4..4af95479a9db 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -3063,9 +3063,9 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
3063 "MSI-X: Failed to enable support " 3063 "MSI-X: Failed to enable support "
3064 "-- %d/%d\n Retry with %d vectors.\n", 3064 "-- %d/%d\n Retry with %d vectors.\n",
3065 ha->msix_count, ret, ret); 3065 ha->msix_count, ret, ret);
3066 ha->msix_count = ret;
3067 ha->max_rsp_queues = ha->msix_count - 1;
3066 } 3068 }
3067 ha->msix_count = ret;
3068 ha->max_rsp_queues = ha->msix_count - 1;
3069 ha->msix_entries = kzalloc(sizeof(struct qla_msix_entry) * 3069 ha->msix_entries = kzalloc(sizeof(struct qla_msix_entry) *
3070 ha->msix_count, GFP_KERNEL); 3070 ha->msix_count, GFP_KERNEL);
3071 if (!ha->msix_entries) { 3071 if (!ha->msix_entries) {
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index c5dd594f6c31..cf7ba52bae66 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -600,7 +600,7 @@ qla25xx_delete_queues(struct scsi_qla_host *vha)
600 /* Delete request queues */ 600 /* Delete request queues */
601 for (cnt = 1; cnt < ha->max_req_queues; cnt++) { 601 for (cnt = 1; cnt < ha->max_req_queues; cnt++) {
602 req = ha->req_q_map[cnt]; 602 req = ha->req_q_map[cnt];
603 if (req) { 603 if (req && test_bit(cnt, ha->req_qid_map)) {
604 ret = qla25xx_delete_req_que(vha, req); 604 ret = qla25xx_delete_req_que(vha, req);
605 if (ret != QLA_SUCCESS) { 605 if (ret != QLA_SUCCESS) {
606 ql_log(ql_log_warn, vha, 0x00ea, 606 ql_log(ql_log_warn, vha, 0x00ea,
@@ -614,7 +614,7 @@ qla25xx_delete_queues(struct scsi_qla_host *vha)
614 /* Delete response queues */ 614 /* Delete response queues */
615 for (cnt = 1; cnt < ha->max_rsp_queues; cnt++) { 615 for (cnt = 1; cnt < ha->max_rsp_queues; cnt++) {
616 rsp = ha->rsp_q_map[cnt]; 616 rsp = ha->rsp_q_map[cnt];
617 if (rsp) { 617 if (rsp && test_bit(cnt, ha->rsp_qid_map)) {
618 ret = qla25xx_delete_rsp_que(vha, rsp); 618 ret = qla25xx_delete_rsp_que(vha, rsp);
619 if (ret != QLA_SUCCESS) { 619 if (ret != QLA_SUCCESS) {
620 ql_log(ql_log_warn, vha, 0x00eb, 620 ql_log(ql_log_warn, vha, 0x00eb,
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index f1788db43195..f6c7ce35b542 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -409,6 +409,9 @@ static void qla2x00_free_queues(struct qla_hw_data *ha)
409 int cnt; 409 int cnt;
410 410
411 for (cnt = 0; cnt < ha->max_req_queues; cnt++) { 411 for (cnt = 0; cnt < ha->max_req_queues; cnt++) {
412 if (!test_bit(cnt, ha->req_qid_map))
413 continue;
414
412 req = ha->req_q_map[cnt]; 415 req = ha->req_q_map[cnt];
413 qla2x00_free_req_que(ha, req); 416 qla2x00_free_req_que(ha, req);
414 } 417 }
@@ -416,6 +419,9 @@ static void qla2x00_free_queues(struct qla_hw_data *ha)
416 ha->req_q_map = NULL; 419 ha->req_q_map = NULL;
417 420
418 for (cnt = 0; cnt < ha->max_rsp_queues; cnt++) { 421 for (cnt = 0; cnt < ha->max_rsp_queues; cnt++) {
422 if (!test_bit(cnt, ha->rsp_qid_map))
423 continue;
424
419 rsp = ha->rsp_q_map[cnt]; 425 rsp = ha->rsp_q_map[cnt];
420 qla2x00_free_rsp_que(ha, rsp); 426 qla2x00_free_rsp_que(ha, rsp);
421 } 427 }
diff --git a/drivers/scsi/qla2xxx/qla_tmpl.c b/drivers/scsi/qla2xxx/qla_tmpl.c
index ddbe2e7ac14d..c3e622524604 100644
--- a/drivers/scsi/qla2xxx/qla_tmpl.c
+++ b/drivers/scsi/qla2xxx/qla_tmpl.c
@@ -395,6 +395,10 @@ qla27xx_fwdt_entry_t263(struct scsi_qla_host *vha,
395 if (ent->t263.queue_type == T263_QUEUE_TYPE_REQ) { 395 if (ent->t263.queue_type == T263_QUEUE_TYPE_REQ) {
396 for (i = 0; i < vha->hw->max_req_queues; i++) { 396 for (i = 0; i < vha->hw->max_req_queues; i++) {
397 struct req_que *req = vha->hw->req_q_map[i]; 397 struct req_que *req = vha->hw->req_q_map[i];
398
399 if (!test_bit(i, vha->hw->req_qid_map))
400 continue;
401
398 if (req || !buf) { 402 if (req || !buf) {
399 length = req ? 403 length = req ?
400 req->length : REQUEST_ENTRY_CNT_24XX; 404 req->length : REQUEST_ENTRY_CNT_24XX;
@@ -408,6 +412,10 @@ qla27xx_fwdt_entry_t263(struct scsi_qla_host *vha,
408 } else if (ent->t263.queue_type == T263_QUEUE_TYPE_RSP) { 412 } else if (ent->t263.queue_type == T263_QUEUE_TYPE_RSP) {
409 for (i = 0; i < vha->hw->max_rsp_queues; i++) { 413 for (i = 0; i < vha->hw->max_rsp_queues; i++) {
410 struct rsp_que *rsp = vha->hw->rsp_q_map[i]; 414 struct rsp_que *rsp = vha->hw->rsp_q_map[i];
415
416 if (!test_bit(i, vha->hw->rsp_qid_map))
417 continue;
418
411 if (rsp || !buf) { 419 if (rsp || !buf) {
412 length = rsp ? 420 length = rsp ?
413 rsp->length : RESPONSE_ENTRY_CNT_MQ; 421 rsp->length : RESPONSE_ENTRY_CNT_MQ;
@@ -634,6 +642,10 @@ qla27xx_fwdt_entry_t274(struct scsi_qla_host *vha,
634 if (ent->t274.queue_type == T274_QUEUE_TYPE_REQ_SHAD) { 642 if (ent->t274.queue_type == T274_QUEUE_TYPE_REQ_SHAD) {
635 for (i = 0; i < vha->hw->max_req_queues; i++) { 643 for (i = 0; i < vha->hw->max_req_queues; i++) {
636 struct req_que *req = vha->hw->req_q_map[i]; 644 struct req_que *req = vha->hw->req_q_map[i];
645
646 if (!test_bit(i, vha->hw->req_qid_map))
647 continue;
648
637 if (req || !buf) { 649 if (req || !buf) {
638 qla27xx_insert16(i, buf, len); 650 qla27xx_insert16(i, buf, len);
639 qla27xx_insert16(1, buf, len); 651 qla27xx_insert16(1, buf, len);
@@ -645,6 +657,10 @@ qla27xx_fwdt_entry_t274(struct scsi_qla_host *vha,
645 } else if (ent->t274.queue_type == T274_QUEUE_TYPE_RSP_SHAD) { 657 } else if (ent->t274.queue_type == T274_QUEUE_TYPE_RSP_SHAD) {
646 for (i = 0; i < vha->hw->max_rsp_queues; i++) { 658 for (i = 0; i < vha->hw->max_rsp_queues; i++) {
647 struct rsp_que *rsp = vha->hw->rsp_q_map[i]; 659 struct rsp_que *rsp = vha->hw->rsp_q_map[i];
660
661 if (!test_bit(i, vha->hw->rsp_qid_map))
662 continue;
663
648 if (rsp || !buf) { 664 if (rsp || !buf) {
649 qla27xx_insert16(i, buf, len); 665 qla27xx_insert16(i, buf, len);
650 qla27xx_insert16(1, buf, len); 666 qla27xx_insert16(1, buf, len);