2021-03-10 10:53:03

by Dinghao Liu

[permalink] [raw]
Subject: [PATCH] scsi: aic7xxx: aic79xx: Add missing check in ahc_handle_seqint

ahc_lookup_scb() may return a null pointer and further lead to
null-pointer-dereference in case DATA_OVERRUN. Fix this by adding
a null check.

Signed-off-by: Dinghao Liu <[email protected]>
---
drivers/scsi/aic7xxx/aic7xxx_core.c | 72 +++++++++++++++--------------
1 file changed, 37 insertions(+), 35 deletions(-)

diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c
index 4b04ab8908f8..3a1cd6a0334e 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_core.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_core.c
@@ -1382,43 +1382,45 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
u_int i;

scb = ahc_lookup_scb(ahc, scbindex);
- for (i = 0; i < num_phases; i++) {
- if (lastphase == ahc_phase_table[i].phase)
- break;
- }
- ahc_print_path(ahc, scb);
- printk("data overrun detected %s."
- " Tag == 0x%x.\n",
- ahc_phase_table[i].phasemsg,
- scb->hscb->tag);
- ahc_print_path(ahc, scb);
- printk("%s seen Data Phase. Length = %ld. NumSGs = %d.\n",
- ahc_inb(ahc, SEQ_FLAGS) & DPHASE ? "Have" : "Haven't",
- ahc_get_transfer_length(scb), scb->sg_count);
- if (scb->sg_count > 0) {
- for (i = 0; i < scb->sg_count; i++) {
-
- printk("sg[%d] - Addr 0x%x%x : Length %d\n",
- i,
- (ahc_le32toh(scb->sg_list[i].len) >> 24
- & SG_HIGH_ADDR_BITS),
- ahc_le32toh(scb->sg_list[i].addr),
- ahc_le32toh(scb->sg_list[i].len)
- & AHC_SG_LEN_MASK);
+ if (scb != NULL) {
+ for (i = 0; i < num_phases; i++) {
+ if (lastphase == ahc_phase_table[i].phase)
+ break;
}
+ ahc_print_path(ahc, scb);
+ printk("data overrun detected %s."
+ " Tag == 0x%x.\n",
+ ahc_phase_table[i].phasemsg,
+ scb->hscb->tag);
+ ahc_print_path(ahc, scb);
+ printk("%s seen Data Phase. Length = %ld. NumSGs = %d.\n",
+ ahc_inb(ahc, SEQ_FLAGS) & DPHASE ? "Have" : "Haven't",
+ ahc_get_transfer_length(scb), scb->sg_count);
+ if (scb->sg_count > 0) {
+ for (i = 0; i < scb->sg_count; i++) {
+
+ printk("sg[%d] - Addr 0x%x%x : Length %d\n",
+ i,
+ (ahc_le32toh(scb->sg_list[i].len) >> 24
+ & SG_HIGH_ADDR_BITS),
+ ahc_le32toh(scb->sg_list[i].addr),
+ ahc_le32toh(scb->sg_list[i].len)
+ & AHC_SG_LEN_MASK);
+ }
+ }
+ /*
+ * Set this and it will take effect when the
+ * target does a command complete.
+ */
+ ahc_freeze_devq(ahc, scb);
+ if ((scb->flags & SCB_SENSE) == 0) {
+ ahc_set_transaction_status(scb, CAM_DATA_RUN_ERR);
+ } else {
+ scb->flags &= ~SCB_SENSE;
+ ahc_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);
+ }
+ ahc_freeze_scb(scb);
}
- /*
- * Set this and it will take effect when the
- * target does a command complete.
- */
- ahc_freeze_devq(ahc, scb);
- if ((scb->flags & SCB_SENSE) == 0) {
- ahc_set_transaction_status(scb, CAM_DATA_RUN_ERR);
- } else {
- scb->flags &= ~SCB_SENSE;
- ahc_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);
- }
- ahc_freeze_scb(scb);

if ((ahc->features & AHC_ULTRA2) != 0) {
/*
--
2.17.1